Closed AleFons closed 3 years ago
I also confirm that issue. On Android 9 all features works great, but after update my device to Android 10 I got "Error capturing image" when flag saveToPhotoAlbum is set to the value true.
Device: Samsung A40
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.
Unfortunately requestLegacyExternalStorage
in config.xml doesn't work.
I tried this code:
`
</edit-config>`
And I got:
AAPT: error: attribute android:requestLegacyExternalStorage not found.
I downgraded compileSdkVersion
from 29 to 28 and now saveToPhotoAlbum works properly.
Even on an Android 10 phone?
Yes, I tested this solution on Samsung A40 with Android 10. When I had Android 9 then all camera features worked properly with setting compileSdkVersion=29, but after upgrade to Android 10 I had to downgrade compileSdkVersion. Of course if you utilize features from Android 10, then this solution isn't correct.
@bartdeveloper Appreciate if you could share your git repo link.
Looks like API 29 requires Scoped Locations
There are two current workarounds:
android-targetSdkVersion
preference.<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.
The commit e9aba07926072a069acefe614726e171c25004a6 is bad and causes this issue.
@isamuAsial That commit is not officially released and only exists in master.
I would recommend using 4.1.0 which had been voted on and official released for production use. 4.1.0 release does not contain that commit.
Looks like API 29 requires Scoped Locations
There are two current workarounds:
- Reduce the target sdk to 28, which can be done via the
android-targetSdkVersion
preference.- Use the requestLegacyExternalStorage flag. Which can be added using the
<edit-config>
. This flag requires you to target/compile for API 29 (the default incordova-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 had white screen issues when trying to use that flag.
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.
@isamuAsial That commit is not officially released and only exists in master.
I would recommend using 4.1.0 which had been voted on and official released for production use. 4.1.0 release does not contain that commit.
We're using 4.1.0 and we have exactly same problem on Android 10 devices. The stacktrace is same as provided by @jwasnoggin above. So it seems production version is affected as well.
Cordova CLI: 10.0.0 Cordova platform: android 9.0.0
I am having this same issue on API SDK 29, tried adding this snippet to my Android platform in the config.xml
file.
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
<application android:requestLegacyExternalStorage="true" />
</edit-config>
Which either causes the app to crash when I accept permissions or do nothing at all.
Cordova CLI: 10.0.0 Cordova Platform : Android 9.0.0 As I mentioned above I am building for Android 29
Hello, Is there any solution for this yet? I have tried solutions given in this, but the issue persists.
Hello, Is there any solution for this yet? I have tried solutions given in this, but the issue persists.
Same here.
Not sure if this is related or not, but v5.0.0 of the plugin fails for me as well with saveToPhotoAlbum set true. For me, it is also failing on my Android 8 test device with the following stack trace:
java.io.FileNotFoundException: content:/com.fi.pmp.cordova.plugin.camera.provider/cache_files/.Pic.jpg (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:200)
at java.io.FileInputStream.<init>(FileInputStream.java:150)
at java.io.FileInputStream.<init>(FileInputStream.java:103)
at org.apache.cordova.camera.CameraLauncher.writeUncompressedImage(CameraLauncher.java:906)
at org.apache.cordova.camera.CameraLauncher.processResultFromCamera(CameraLauncher.java:503)
at org.apache.cordova.camera.CameraLauncher.onActivityResult(CameraLauncher.java:808)
at org.apache.cordova.CordovaInterfaceImpl.onActivityResult(CordovaInterfaceImpl.java:159)
at org.apache.cordova.CordovaActivity.onActivityResult(CordovaActivity.java:361)
at android.app.Activity.dispatchActivityResult(Activity.java:7599)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4487)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4534)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1752)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
It appears that the source URI has a content: scheme instead of a file: scheme that writeUncompressedImage() expects.
I was able to get it working by changing line 903 of CameraLauncher.java from:
FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString()));
to
InputStream fis = this.cordova.getActivity().getContentResolver().openInputStream(src);
openInputStream() is documented to accept both file: and content: schemes, so this change should handle both cases.
With this change, saveToPhotoAlbum works again on this Android 8 device. I haven't had a chance to test on any other devices yet.
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
With my above change, it is now working for me on my Android 10 device using "cordova-android": "^9.0.0" and "cordova-plugin-camera": "^5.0.0".
The options that I am passing in to getPicture() are:
sourceType: navigator.camera.PictureSourceType.CAMERA
destinationType: navigator.camera.DestinationType.FILE_URI,,
encodingType: navigator.camera.EncodingType.JPEG,
quality: 75,
saveToPhotoAlbum: true,
targetWidth: 2048,
targetHeight: 2048
Hey @wifisher , Have you tried setting targetSDKVersion to 29? Thanks!
Isn't the targetSDKVersion set to 29 by cordova-android 9.0.0?
Isn't the targetSDKVersion set to 29 by cordova-android 9.0.0?
I am unaware of this. Can you check whether it is 29 or not?
According to https://cordova.apache.org/announcements/2020/06/29/cordova-android-9.0.0.html the default targetSDKVersion is 29 with cordova-android 9.0.0.
I did a test by setting the version in config.xml with the following line:
<preference name="android-targetSdkVersion" value="29"/>
I was able to take a picture and have it appear in the gallery.
The app I am working on we also have <preference name="android-targetSdkVersion" value="29" />
enabled, but it still fails when the savePhotoToAlbum
is enabled. Only way to fix is force it to sdk28
which is not preferred :/
You can test my fix by making the change to CameraLauncher.java that I mentioned above. Test by making the change to the file at this location: platforms/android/app/src/main/java/org/apache/cordova/camera. Then build and run.
If it works, then your problem is the same as mine. I wouldn't build a release with this change hacked in, but it would be useful to know if it is the same problem or not.
It's a small change, but it would be nice to see it come out in a 5.0.1 version of the camera plugin.
@wifisher I did made a change to the code. I've read your suggestion of the content uri.
You can test the changes with next commands.
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
Can you test this? After testing I could make a PR for this.
Another remark: It should be saved to the photo album, if you take a picture with the camera. This issue is about selecting from the gallery and saving a copy to the gallery of it. ( sourceType: this.Camera.PictureSourceType.PHOTOLIBRARY, ) But that's another issue. The issue you are refering to is https://github.com/apache/cordova-plugin-camera/issues/577 or https://github.com/apache/cordova-plugin-camera/issues/341
Kind regards.
@PieterVanPoyer I installed your plugin and it appears to be working correctly for me.
I "solved" this issue by using Capacitor instead of Cordova using https://capacitorjs.com/docs/apis/camera
@PieterVanPoyer I can confirm that your fix is also working for me.
@PieterVanPoyer , I have following config:
Ionic Framework : ionic-angular 3.9.2
@ionic/app-scripts : 3.2.4
Cordova CLI : 8.1.2
Cordova Platforms : android 7.1.4, ios 4.5.5
cordova-plugin-camera : 4.0.3
Should updating Cordova-plugin-camera
to 5.0 resolve this without changing the Cordova version?
Thanks!
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'm using the latest version of this plugin from master after the above merge but it seems that it doesn't work with android 10, even if I set requestLegacyExternalStorage
to true (using the latest cordova-file-plugin
adds this to the manifest).
When I'm trying to open the camera to take a picture I get to the following code:
if (takePicturePermission && saveAlbumPermission) {
takePicture(returnType, encodingType);
} else if (saveAlbumPermission && !takePicturePermission) {
PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.CAMERA);
} else if (!saveAlbumPermission && takePicturePermission) {
/// ---> I'm getting here which doesn't do anything in android 10...
PermissionHelper.requestPermissions(this, TAKE_PIC_SEC,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
} else {
PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, permissions);
}
Has anyone else got to this point? Am I missing something? Should I just remove the saveToPhoto
album?
Any help would be appreciated.
Cordova 10, cordova-android 9.0, of course.
@HarelM I was able to reproduce it.
In my testsetup I removed the <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- tag of the AndroidManifest.xml.
Is this tag present in your AndroidManifest?
When I remove this line <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
, I can reproduce the behaviour.
What is the content of your AndroidManifest.xml?
Kind regards Pieter
Hello @PieterVanPoyer ,
I have used the latest Camera plugin version and I am facing an issue in which I am unable to upload files from the google drive.
I have created an issue in the file plugin repo, but haven't got a reply. If you can look into it. Here is the link: https://github.com/apache/cordova-plugin-file/issues/432
Thanks.
@PieterVanPoyer Thanks! Seems like this permission is now missing, I have no idea why, I see it on both the camera plugin plugin.xml
and file plugin plugin.xml
with the same annotation:
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
But it doesn't get to the manifest.xml file as it used to. Since I upgraded to Cordova 10 the entire environment had become shaky and I need to place stuff in different places in the 'package.json` file to make the app compile. So it might be another bug I'm just not sure where to report it...
@HarelM indeed normally the permission must be set by cordova itself.
Because the WRITE_EXTERNAL_STORAGE must be declared in the manifest, else the user is unable to allow it later. The reason is, that the permission holds a high risk and it must be whitelisted
. [ https://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE ]
It is indeed correctly declared in the plugin.xml.
Does removing the platform and plugin and afterwards reïnstalling it solve the problem?
Can you reproduce it in a blank Cordova 10 project in anyway, with just the camera plugin included? If yes, then you could make a new issue for the camera plugin.
I'm not sure I can reproduce it on a blank project. but my project is open source and the CI build machine is always a clean start. The turn point from my point of view is upgrading the cordova cli version and not the camera plugin... I have opened some issues in the cordova-fetch and cordova-cli project but didn't get any response yet...
BTW @PieterVanPoyer, after fixing all the permission issues and build issues I still don't see the image I take in the photo gallery so I'm not sure the latest version (after the #669 PR merged here) does fix this bug in all android versions... Let me know if you want me to test anything specific... Package.json and config.xml can be found here: https://github.com/IsraelHikingMap/Site/tree/master/IsraelHiking.Web
@HarelM I won't be able to test every Android device offcourse.
But just to be curious, is the taken picture returned to your app? So it is only the save to gallery that fails, or do you receive an error in your javascript. If yes, what is the error?
Do you use DATA_URI or FILE_URI as type? In what Android version does it fail? Android 10, Android 11, Android 9, ... ?
I'm using android 9. The image is returned to the client without any error as far as I understand. I'm using DATA_URI as can be seen here. @PieterVanPoyer I fully understand you won't be able to test every android device, this is why I'm reporting this, so I can help in testing. You can see here the configuration: https://github.com/IsraelHikingMap/Site/blob/master/IsraelHiking.Web/sources/application/directives/image-capture.directive.ts#L49
Originally, there was an error thrown and no image was returned.
You could try to test with next repo: https://github.com/PieterVanPoyer/cordova-camera-plugin-testing-app/tree/master If you set the camera plugin to the master, you could try this repo.
Then maybe we can pinpoint the issue. Do you test on an emulator or on a real device?
My bad, I now see the photo I took in the Pictures folder (not the camera folder, which is what google photos is showing). Thanks for the fix! Sorry for miss-leading...
No problem. We figured out the permission issue. Cheers!
Hello @PieterVanPoyer ,
I have used the latest Camera plugin version and I am facing an issue in which I am unable to upload files from the google drive.
I have created an issue in the file plugin repo, but haven't got a reply. If you can look into it. Here is the link: apache/cordova-plugin-file#432
Thanks.
Can anyone help me on this?
@AleFons is this issue still happening with the latest released version? If not, feel free to close this issue.
Any updates on this?
Can't speak for @AleFons, but I encountered the same issue, and the latest version resolved it for me.
The latest version has solved it for me too. I believe the issue has been solved with Cordova 10.
@AleFons nice, maybe you should close this issue then? Kind regards Pieter
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.
This worked for me, it is a great solution
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()
: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