cordova-plugin-camera: Cannot use saveToPhotoAlbum: true on Android 10

Bug Report

Problem

What is expected to happen?

Using saveToPhotoAlbum: true should allow the user to take a picture and save a backup to the phone’s gallery.

What does actually happen?

The plugin instead throws an error on Android 10.

Information

Setting the option to false avoids the problem, but then no backup is made.

Command or Code

I use these options for Camera.getPicture():

annex_options: CameraOptions = {
    destinationType: this.Camera.DestinationType.FILE_URI,
    sourceType: this.Camera.PictureSourceType.PHOTOLIBRARY,
    correctOrientation: false,
    saveToPhotoAlbum: false
  }

Environment, Platform, Device

Android 10, has happened on multiple devices.

Version information

Ionic:

ionic (Ionic CLI) : 4.6.0 Ionic Framework : ionic-angular 3.9.6 @ionic/app-scripts : 3.2.4

Cordova:

cordova (Cordova CLI) : 9.0.0 (cordova-lib@9.0.1) Cordova Platforms : android 8.1.0, ios 5.0.0 Cordova Plugins : cordova-plugin-ionic-keyboard 2.0.5, cordova-plugin-ionic-webview 2.2.0, (and 18 other plugins)

System:

Android SDK Tools : 26.1.1 NodeJS : v12.16.3 npm : 6.14.4 OS : Linux 4.15

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 52 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Looks like API 29 requires Scoped Locations

There are two current workarounds:

  1. Reduce the target sdk to 28, which can be done via the android-targetSdkVersion preference.
  2. Use the requestLegacyExternalStorage flag. Which can be added using the <edit-config>. This flag requires you to target/compile for API 29 (the default in cordova-android@9)

I’m not familiar with this plugin’s codebase, but it looks like MediaStore is already used, and that’s what the Android docs suggest that we need to use. So further investigation is going to be required to determine what the actual problem is.

The plugin instead throws an error on Android 10.

It would be nice to know exactly what that error is, and perhaps stacktrace.

I downgraded compileSdkVersion from 29 to 28 and now saveToPhotoAlbum works properly.

From my understanding, what appears to be happening is that saving to photo album is triggering an access to storage outside the app’s permitted storage, as android 10 comes with changes to where the app is permitted to do file operations. It may be possible to fix it with android:requestLegacyExternalStorage="true" but I have had issues with testing that.

I did make a Pull Request to solve the issue with saveToPhotoAlbum and the camera. https://github.com/apache/cordova-plugin-camera/pull/669 But this code is not in the master. You could try (for testing purposes) to install my fork (for now).

npx cordova plugin remove cordova-plugin-camera
npx cordova plugin add https://github.com/PieterVanPoyer/cordova-plugin-camera.git#bugfix/issue-341-save-to-photo-gallery

I don’t think updating (or installing the fork) is possible without updating the Cordova CLI and cordova android version. (Current version of the cli is 10, I believe.)

Kind regards

I have this issue on Android 11. None of the above solutions work! I upgraded to cordova-android 10. That didn’t help either. Anyone tried the solutions on Android 11?

Hello, Is there any solution for this yet? I have tried solutions given in this, but the issue persists.

Same here. Any solution or workarounds for Android 10

It would be nice to know exactly what that error is, and perhaps stacktrace.

This is the stacktrace that I got in the logcat:

java.io.FileNotFoundException: open failed: EACCES (Permission denied)
    at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:315)
    at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:220)
    at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1498)
    at android.content.ContentResolver.openOutputStream(ContentResolver.java:1227)
    at android.content.ContentResolver.openOutputStream(ContentResolver.java:1203)
    at org.apache.cordova.camera.CameraLauncher.writeUncompressedImage(CameraLauncher.java:866)
    at org.apache.cordova.camera.CameraLauncher.writeUncompressedImage(CameraLauncher.java:902)
    at org.apache.cordova.camera.CameraLauncher.processResultFromCamera(CameraLauncher.java:508)
    at org.apache.cordova.camera.CameraLauncher.onActivityResult(CameraLauncher.java:806)
    at org.apache.cordova.CordovaInterfaceImpl.onActivityResult(CordovaInterfaceImpl.java:159)
    at org.apache.cordova.CordovaActivity.onActivityResult(CordovaActivity.java:361)

I was ultimately able to resolve the error using the requestLegacyExternalStorage flag.