apache / cordova-plugin-camera

Apache Cordova Plugin camera
https://cordova.apache.org/
Apache License 2.0
960 stars 1.52k forks source link

feat(android)!: Android 13 support #844

Closed erisu closed 8 months ago

erisu commented 9 months ago

Platforms affected

android

Motivation and Context

Android 13 Support

Description

closes #814 resolves #825

Testing

Checklist

erisu commented 8 months ago

I believe this would be something you fix within your project.

cordova-plugin-file version 8.0.0 has removed permission WRITE_EXTERNAL_STORAGE.

If you are using a plugin that depends on cordova-plugin-file make sure it is requesting for version 8.0.0.

If it is not, check if there is a new plugin version that hopefully supports cordova-plugin-file 8.0.0.

Note: Some Cordova core plugins depend on the file plugin and not updated, but it is in the process of being updated.

If you are adding the cordova-plugin-file directly and it is not a depedency of another plugin, it might be OK to bump its version.

christiaan commented 8 months ago

If you are adding the cordova-plugin-file directly and it is not a depedency of another plugin, it might be OK to bump its version.

That is exactly how I fixed it :smile: and seeing the original PR already mentioning this issue I removed the question.

christiaan commented 8 months ago

On an Android 8.0 (and 7.1.1) device it fails after it asks for permission the first time with the following error

FATAL EXCEPTION: main
Process: com.myapp.app, PID: 22690
java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=1, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.myapp.app/com.myapp.app.MainActivity}: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=22690, uid=10176 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4491)
    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)
Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=22690, uid=10176 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
    at android.os.Parcel.readException(Parcel.java:1967)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:418)
    at android.content.ContentResolver.query(ContentResolver.java:760)
    at android.content.ContentResolver.query(ContentResolver.java:710)
    at android.content.ContentResolver.query(ContentResolver.java:668)
    at org.apache.cordova.camera.CameraLauncher.queryImgDB(CameraLauncher.java:1222)
    at org.apache.cordova.camera.CameraLauncher.takePicture(CameraLauncher.java:325)
    at org.apache.cordova.camera.CameraLauncher.onRequestPermissionResult(CameraLauncher.java:1362)
    at org.apache.cordova.CordovaInterfaceImpl.onRequestPermissionResult(CordovaInterfaceImpl.java:222)
    at org.apache.cordova.CordovaActivity.onRequestPermissionsResult(CordovaActivity.java:527)
    at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:7780)
    at android.app.Activity.dispatchActivityResult(Activity.java:7603)
    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) 

If I then choose to pick a picture using using Camera.PictureSourceType.PHOTOLIBRARY it requests permission for storage and after that the Camera.PictureSourceType.CAMERA also works again.

I am calling getPicture like so

navigator.camera.getPicture(this.onCameraSuccess.bind(this), this.onCameraError.bind(this), {
    quality: 50,
    destinationType: Camera.DestinationType.DATA_URL,
    sourceType: Camera.PictureSourceType.CAMERA,
    allowEdit: false,
    encodingType: Camera.EncodingType.JPEG,
    correctOrientation: true,
    targetWidth: 1024,
    targetHeight: 1024
});

It appears to be because of this line in the plugin; on my phone the content store is aparently on the external storage.

        // Save the number of images currently on disk for later
        this.numPics = queryImgDB(whichContentStore()).getCount();

It appears the checkForDuplicateImage needs access to the storage even if you take a picture without saving it anywhere.

I worked around/fixed it by changing

        boolean saveAlbumPermission;
        if (this.saveToPhotoAlbum) {
            saveAlbumPermission = hasPermissions(storagePermissions);
        } else {
            saveAlbumPermission = true;
        }

to

        boolean saveAlbumPermission = hasPermissions(storagePermissions);

Seeing as even when not saving the image you still need storage permission to process duplicates.

erisu commented 8 months ago

@christiaan I updated the PR to fix the Android 8.0 and lower issue you reported. Can you confirm if it resolved for you?

christiaan commented 8 months ago

@erisu I can confirm the last commit resolved the issue on Android 8.0 (Samsung A3 2017) :+1: thanks!

breautek commented 8 months ago

untested, but code-wise lgtm

Just an update, I tested this PR against my app and it seems good to go, at least in my usage of the camera plugin.

michelsondan commented 8 months ago

Thank you, now camera working on android 13

EinfachHans commented 8 months ago

Looks like 7.0.0 is not published on npm, can someone please do this?