cordova-plugin-camera icon indicating copy to clipboard operation
cordova-plugin-camera copied to clipboard

Android 13 : Camera/Gallery doesn't open

Open Houdhey opened this issue 2 years ago • 5 comments

Bug Report

Msg: cannot open camera: 20

Problem

Camera doesn't open, Gallery doesn't open, for Android 13 emulator Pointing API 33 of Android in the build.gradle

What is expected to happen?

Camera should open, Gallery should open

What does actually happen?

Nothing, display a bug message : Msg: cannot open camera: 20 E/Capacitor/Browser: Error binding to custom tabs service

Command or Code

    const options: CameraOptions = {
      quality: 100,
      destinationType: this.camera.DestinationType.DATA_URL,
      sourceType: this.camera.PictureSourceType.SAVEDPHOTOALBUM,
      correctOrientation: true,
      allowEdit: false,
      targetHeight: 1280,
      targetWidth: 1280,
    };

    this.camera.getPicture(options).then()....

  

Environment, Platform, Device

Ionic, Android 13

Workarounds

Use API 32

Houdhey avatar Jun 29 '22 09:06 Houdhey

In my case picking an image from Library works, but taking an image with whichever options gives the error Illegal Argument Exception Also occurs on Android 12 devices:

  • Xiaomi POCO X3 Pro | MIUI 13.0.1 | Android 12
  • Pixel 6 | Android 12
  • Pixel 6 Pro | Android 12

Edit: Select from Library works, but when the image is picked, the callback also gives the error Illegal Argument Exception

LeParadoxHD avatar Jul 15 '22 13:07 LeParadoxHD

Confirmed on pure cordova app

Cordova android v11.0.0 cordova camera plugin v6.0.0

Build Tools / Target SDK 33 on Android 13 emulator

Error code 20 is produced to the JS console

Native logcat:

07-16 00:23:38.096   575   914 V UserSystemPackageInstaller: dumpPackageWhitelistProblems(): using mode ENFORCE|IMPLICIT_WHITELIST|IMPLICIT_WHITELIST_SYSTEM
07-16 00:23:38.113   575   914 I ActivityTaskManager: START u0 {act=android.content.pm.action.REQUEST_PERMISSIONS pkg=com.google.android.permissioncontroller cmp=com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.GrantPermissionsActivity (has extras)} from uid 10157
07-16 00:23:38.120  6334  6334 D CordovaActivity: Paused the activity.
07-16 00:23:38.121   575   917 W ActivityTaskManager: Tried to set launchTime (0) < mLastActivityLaunchTime (352665)
07-16 00:23:38.125   575   594 D OomAdjuster: Not killing cached processes
07-16 00:23:38.142   575   917 D CoreBackPreview: Window{e737f07 u0 com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.GrantPermissionsActivity}: Setting back callback OnBackInvokedCallbackInfo{mCallback=android.window.IOnBackInvokedCallback$Stub$Proxy@c13665d, mPriority=0}
07-16 00:23:38.150   402   446 D goldfish-address-space: claimShared: Ask to claim region [0x3f683d000 0x3f6e40000]
07-16 00:23:38.160  6334  6334 D CordovaActivity: Resumed the activity.
07-16 00:23:38.161  6334  6334 I chromium: [INFO:CONSOLE(1)] "20", source:  (1)
07-16 00:23:38.173   575   917 D CoreBackPreview: Window{e737f07 u0 com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.GrantPermissionsActivity}: Setting back callback null
07-16 00:23:38.173   575  3087 W InputManager-JNI: Input channel object 'e737f07 com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.GrantPermissionsActivity (client)' was disposed without first being removed with the input manager!
07-16 00:23:38.189  7107  7107 I GoogleInputMethodService: GoogleInputMethodService.onFinishInput():3204 
07-16 00:23:38.190  7107  7107 I GoogleInputMethodService: GoogleInputMethodService.updateDeviceLockedStatus():2100 checkRepeatedly = false, unlocked = true
07-16 00:23:38.190  7107  7107 I GoogleInputMethodService: GoogleInputMethodService.onStartInput():1903 onStartInput(EditorInfo{inputType=0x0(NULL) imeOptions=0x12000000 privateImeOptions=null actionName=UNSPECIFIED actionLabel=null actionId=0 initialSelStart=-1 initialSelEnd=-1 initialCapsMode=0x0 hintText=null label=null packageName=io.cordova.hellocordovagh797 fieldId=100 fieldName=null extras=null}, false)
07-16 00:23:38.190  7107  7107 I GoogleInputMethodService: GoogleInputMethodService.updateDeviceLockedStatus():2100 checkRepeatedly = true, unlocked = true

At a glance, it appears something to do with handling permissions has changed in Android 13, as error code 20 is a Permission Error Code...

https://github.com/apache/cordova-plugin-camera/blob/4608f8ef8027a5c7130a3479c2d37a5e391c70e8/src/android/CameraLauncher.java#L100

I've also tested against build tools / target SDK 32 on an Android 13 emulator which appears to work fine. So this appears to be exclusively an API 33 issue.

breautek avatar Jul 16 '22 03:07 breautek

Can we have an update on this bug please? I think Android 13 is gonna be released soon

Houdhey avatar Jul 25 '22 15:07 Houdhey

breautek

I tried adding the permissions as said in the Android doc https://developer.android.com/about/versions/13/behavior-changes-13

Like this :

<manifest ...>
    <!-- Required only if your app targets Android 13. -->
    <!-- Declare one or more the following permissions only if your app needs
    to access data that's protected by them. -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

    <!-- Required to maintain app compatibility. -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
                     android:maxSdkVersion="32" />
    <application ...>
        ...
    </application>
</manifest> 

But it didn't change. "Cannot open camera : 20" , "Cannot open gallery : 20"

Houdhey avatar Jul 27 '22 08:07 Houdhey

After investigating, the error comes from this method on CameraLauncher.java file :

    public void onRequestPermissionResult(int requestCode, String[] permissions,
                                          int[] grantResults) {
        for (int r : grantResults) {
            System.out.println("PHOTO DEBUG - " + r);
         /*   if (r == PackageManager.PERMISSION_DENIED) {
                this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
                System.out.println("PHOTO DEBUG - " + r);
                return;
            }
*/

        }
        switch (requestCode) {
            case TAKE_PIC_SEC:
                takePicture(this.destType, this.encodingType);
                break;
            case SAVE_TO_ALBUM_SEC:
                this.getImage(this.srcType, this.destType);
                break;
        }
    }

If I comment this section about comparing value of r and PackageManager.PERMISSION_DENIED value, camera and gallery work good. It means we are always getting -1 value even if we allow permissions. I'm not Android Expert but i try to get explanations, how to fix this permission section

Houdhey avatar Jul 27 '22 09:07 Houdhey

Is there any work to actually fix this issue? The solution above me doesn't seem that fitting since it can crash the application if the user declines to give access to the camera/gallery. Is there a reason why all the grantResults are -1 for android 13?

Tolfx avatar Oct 13 '22 13:10 Tolfx

hello.. any update for this issue.

xuanphu123 avatar Nov 07 '22 06:11 xuanphu123

Hi all, is there any information on this issue and if/when it's planned to be fixed? Regards

coderbit-net avatar Nov 15 '22 10:11 coderbit-net

This pull request is related : https://github.com/apache/cordova-plugin-camera/pull/814

felicienfrancois avatar Nov 21 '22 09:11 felicienfrancois

I am hoping for this bug to be fixed too. It is producing strange results where the gallery refuses to open on Android 33 Emulator, but works fine on my Pixel 7 with Android 13.

TDola avatar Nov 25 '22 21:11 TDola

Is there a reason why all the grantResults are -1 for android 13?

Because Google changed permission requirements with Android 13

https://developer.android.com/about/versions/13/behavior-changes-13?hl=en

jfoclpf avatar Feb 01 '23 09:02 jfoclpf

Before Android 13 the permission requested was READ_EXTERNAL_STORAGE

With Android 13 and higher (SDK version >= 33) this permission was divided in three: Images, Video and Audio. For this plugin we just need images, thus with Android 13 and higher we will need to request READ_MEDIA_IMAGES

It should be noted this just happens for new installations

if your app was previously granted the READ_EXTERNAL_STORAGE permission, then any requested READ_MEDIA_* permissions are granted automatically when upgrading

@breautek I was digging into the repo and READ_EXTERNAL_STORAGE just pops up in /src/android/CameraLauncher.java. I guess we should have some sort of global switch that replaces READ_EXTERNAL_STORAGE by READ_MEDIA_IMAGES when faced with Android 13 or higher (SDK version >= 33). This will be backwards compatible because, as said if READ_EXTERNAL_STORAGE was already granted in Android 12 or lower and user upgraded to Android 13, READ_MEDIA_IMAGES is granted automatically.

jfoclpf avatar Feb 01 '23 10:02 jfoclpf

@Houdhey now I have no access to my test PC, but instead of commenting that portion of code, can you kindly just make another test? Can you try to replace all the READ_EXTERNAL_STORAGE entries by READ_MEDIA_IMAGES in /src/android/CameraLauncher.java and see if it works in a new installation in Android 13? Pleeease ;)

jfoclpf avatar Feb 02 '23 11:02 jfoclpf

Hello @jfoclpf
Yes, there is a similar Pull Request doing this : https://github.com/apache/cordova-plugin-camera/pull/814/files Now the problem is fixed, I can't reproduce the bug. Thank you for your investigation @jfoclpf , and thanks to all investigators. I can close

Houdhey avatar Feb 02 '23 13:02 Houdhey

@Houdhey but did you solve the problem with that PR or by commenting the code as you've shown above?

jfoclpf avatar Feb 02 '23 16:02 jfoclpf

Commenting the code is not sufficient, so the PR solved it, that's the hack i was using actually but i should've make a PR

Houdhey avatar Feb 02 '23 16:02 Houdhey

Just to clarify, I should install plugin like this

cordova plugin add https://github.com/apache/cordova-plugin-camera.git#pull/814

Just temporarily obviously, till it is integrated and deployed into NPM repository

jfoclpf avatar Feb 03 '23 12:02 jfoclpf

Actually, at the time I opened this bug, I was using this plugin with Capacitor 2.0 (I don't know if they totally replaced Cordova). So my installation process was : npm install@ionic-native/camera && npm install cordova-plugin-camera

Now, I don't work anymore on this project, so I created a new Ionic Project, and installed same versions that was bugging at the time. With this : npm install@ionic-native/[email protected] && npm install [email protected] And with this new project, Camera is working. But it uses Capacitor 4

I couldn't update Capacitor in my project, in the time I opened this bug. So if you still have this bug, I recommend you to upgrade latest version of Capacitor.

If you need more help, we can see this in a private conversation

Houdhey avatar Feb 03 '23 13:02 Houdhey

Hi , I tried to use the PR but i still can't build 🤔 I got this error : image

This is my setup : image image image

keva91 avatar Feb 06 '23 18:02 keva91

Hi , I tried to use the PR but i still can't build 🤔 I got this error : image

This is my setup : image image image

Show your full AndroidManifest.xml file

Houdhey avatar Feb 06 '23 18:02 Houdhey

@Houdhey @keva91 this issue was already discussed on the PR. It is due to manifest merge conflicts with other plugins using WRITE_EXTERNAL_STORAGE permission without setting android:maxSdkVersion="32" in their manifest.

As discussed on the PR #814 , the android:maxSdkVersion="32" constraint should be removed from the PR as it would create issues for most people.

Also, from my tests, #814 PR has also another issue with DATA_URI output.

I forked this PR to solve both issues here : https://github.com/felicienfrancois/cordova-plugin-camera

felicienfrancois avatar Feb 06 '23 19:02 felicienfrancois

@felicienfrancois I tried your fork and yes i can build now but i still get the error '20' on android 13 phone. image

keva91 avatar Feb 07 '23 10:02 keva91

@keva91 read this comment

Try using PR #814 as you did before and try to guess which plugin is creating the conflict, the one which uses WRITE_EXTERNAL_STORAGE without setting android:maxSdkVersion

Can you show us your list of plugins?

jfoclpf avatar Feb 07 '23 10:02 jfoclpf

@keva91 thank you for your feedback, I have not submitted my fork as a PR yet because it deserve tests and adjustment on the required permissions at runtime, depending on case. I personaly use it with success, in DATA_URI mode.

Can you tell me what parameters do you use ? Which mode ? DATA_URI ? FILE ? Taking photo or picking from library ?

Also, you can try thoose different versions :

  • READ_MEDIA_IMAGES Always requested (Same as PR #814 ) https://github.com/felicienfrancois/cordova-plugin-camera#f53d3cb2ef5add8f7ba37503c4a10fc8e1337600

  • READ_MEDIA_IMAGES Never requested (The one I use) https://github.com/felicienfrancois/cordova-plugin-camera#e6e49b85b59263fc5782e835160d01a8932e3690

  • READ_MEDIA_IMAGES requested only when picking from library (Head, i.e. the one you tried) https://github.com/felicienfrancois/cordova-plugin-camera#efcd9190d98130d815b442b96e0c69fe17637908

As far as I understand, the READ_MEDIA_IMAGES should not be requested as it may not be granted (even refused without prompt in my case) and it is not necessary, at least in my case. But maybe it is needed when using FILE mode

felicienfrancois avatar Feb 07 '23 11:02 felicienfrancois

@keva91 read this comment

Try using PR #814 as you did before and try to guess which plugin is creating the conflict, the one which uses WRITE_EXTERNAL_STORAGE without setting android:maxSdkVersion

Can you show us your list of plugins?

image

@keva91 thank you for your feedback, I have not submitted my fork as a PR yet because it deserve tests and adjustment on the required permissions at runtime, depending on case. I personaly use it with success, in DATA_URI mode.

Can you tell me what parameters do you use ? Which mode ? DATA_URI ? FILE ? Taking photo or picking from library ?

Also, you can try thoose different versions :

  • READ_MEDIA_IMAGES Always requested (Same as PR Android 13 support #814 ) https://github.com/felicienfrancois/cordova-plugin-camera#f53d3cb2ef5add8f7ba37503c4a10fc8e1337600
  • READ_MEDIA_IMAGES Never requested (The one I use) https://github.com/felicienfrancois/cordova-plugin-camera#e6e49b85b59263fc5782e835160d01a8932e3690
  • READ_MEDIA_IMAGES requested only when picking from library (Head, i.e. the one you tried) https://github.com/felicienfrancois/cordova-plugin-camera#efcd9190d98130d815b442b96e0c69fe17637908

As far as I understand, the READ_MEDIA_IMAGES should not be requested as it may not be granted (even refused without prompt in my case) and it is not necessary, at least in my case. But maybe it is needed when using FILE mode

I use FILE_URI with few parameters when i try to take a photo : image

@felicienfrancois I'll try those different versions thank you 😉

keva91 avatar Feb 07 '23 13:02 keva91

Also, you can try thoose different versions :

  • READ_MEDIA_IMAGES Always requested (Same as PR Android 13 support #814 ) https://github.com/felicienfrancois/cordova-plugin-camera#f53d3cb2ef5add8f7ba37503c4a10fc8e1337600

android 13: ❌ android 11: ✅ android 10: ✅

  • READ_MEDIA_IMAGES Never requested (The one I use) https://github.com/felicienfrancois/cordova-plugin-camera#e6e49b85b59263fc5782e835160d01a8932e3690

android 13: ✅ android 11: ✅ android 10: ✅

  • READ_MEDIA_IMAGES requested only when picking from library (Head, i.e. the one you tried) https://github.com/felicienfrancois/cordova-plugin-camera#efcd9190d98130d815b442b96e0c69fe17637908

android 13: ❌ android 11: ✅ android 10: ✅

So the one you're using is working for me as well

keva91 avatar Feb 07 '23 15:02 keva91

@keva91 ok, thank you. So PR #814 has definitelly an issue with READ_MEDIA_IMAGES. According to android doc this permission is required when accessing images on external storage or created by other apps so there may still be cases where it is needed. I just made another change on my fork (adding READ_MEDIA_IMAGES to manifest), if you want to test it: https://github.com/felicienfrancois/cordova-plugin-camera#7d66143ed55d817676c10a460c66938519d4b85b

felicienfrancois avatar Feb 07 '23 16:02 felicienfrancois

@keva91 ok, thank you. So PR #814 has definitelly an issue with READ_MEDIA_IMAGES. According to android doc this permission is required when accessing images on external storage or created by other apps so there may still be cases where it is needed. I just made another change on my fork (adding READ_MEDIA_IMAGES to manifest), if you want to test it: https://github.com/felicienfrancois/cordova-plugin-camera#7d66143ed55d817676c10a460c66938519d4b85b

It works too. And it also prompt for permissions which is better i think :)

keva91 avatar Feb 08 '23 17:02 keva91

@felicienfrancois regarding your repo and user permissions, should't your add min and max sdk versions to avoid excessive user permissions requests ? That is:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33" />

jfoclpf avatar Feb 19 '23 11:02 jfoclpf

I see @felicienfrancois , I tested now, although correct my suggestions they are more likely to create conflicts with other plugins as @keva91 experienced. I tested your repo and it works, thanks

jfoclpf avatar Feb 19 '23 11:02 jfoclpf