apache / cordova-plugin-camera

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

Error Code 20 on Android with Plugin v7.0.0 #875

Open scyclops opened 5 months ago

scyclops commented 5 months ago

Bug Report

Problem

I'm seeing error code 20 returned as a result of calls to navigator.camera.getPicture on Android. It's happening pretty regularly with between 2 and 15 reports a day. I'm using cordova-plugin-camera version 7.0.0 with cordova-android 12.0.0

What is expected to happen?

User should be able to use their device camera to take a photo and the image data should be returned to the getPicture success callback.

What does actually happen?

The getPicture error callback is called with error code 20.

Information

This issue was previously reported in #826

I had previously tried using the jalios fork to fix this problem before cordova-plugin-camera version 7.0.0 was released but the jalios fork also resulted in error code 20 reports.

Code

// after deviceready event

let Camera = window.Camera,
    options = {
        quality: 75,
        destinationType: Camera.DestinationType.FILE_URI,
        sourceType: Camera.PictureSourceType.CAMERA,
        allowEdit: false,
        encodingType: Camera.EncodingType.JPEG,
        targetWidth: 1024,
        targetHeight: 1024,
        correctOrientation: true
    };

navigator.camera.getPicture(
    () => {
        console.log('success');
    },
    (error) => {
        console.log('error: ' + JSON.stringify(error));
    },
    options
);

Environment, Platform, Device

On Android devices using cordova-plugin-camera version 7.0.0 and cordova-android 12.0.0

The error has occurred with the following devices (this is not an exhaustive list):

-- Android 12 -- Nokia 5.4 ITEL A60 Samsung Galaxy A21s Oppo A16s Moto G Stylus 5G

-- Android 11 -- Samsung Galaxy A50 Samsung Galaxy A10

-- Android 10 -- Moto G7 Plus Moto G7 Power Moto G7 Play Samsung Galaxy Note9 Samsung Galaxy S9+

-- Android 8.1.0 -- Samsung Galaxy J5

fjckls commented 5 months ago

Same here on devices with Android 13, getting the same error:20.

fjckls commented 5 months ago

OK, I think I found it. Looking at the source code inside CameraLauncher.java we have public static final int PERMISSION_DENIED_ERROR = 20;. So I did a little investigation and stumbled upon these 2 permissions that are used in this plugin:

https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE _Note: Starting in API level 33, this permission has no effect. If your app accesses other apps' media files, request one or more of these permissions instead: READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIAAUDIO. Learn more about the storage permissions that are associated with media files.

https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE. If your app is on a device that runs API level 19 or higher, you don't need to declare this permission to read and write files in your application-specific directories returned by Context.getExternalFilesDir(String) and Context.getExternalCacheDir()

As quick fix - I replaced all _READ_EXTERNALSTORAGE with _READ_MEDIAIMAGES and removed completely _WRITE_EXTERNALSTORAGE everywhere in the code (CameraLauncher.java) and voila - it works.

Todo - make sure it still works on older Android

bstmedia commented 5 months ago

I'm on an older plugin version and prepared a hotfix for the 5.0.x branche.

https://github.com/apache/cordova-plugin-camera/compare/5.0.x...bstmedia:cordova-plugin-camera:5.0.x

In case anyone else needs this as well. I tested this with Android 5, 9 and 13 and it seems to work fine.

scyclops commented 4 months ago

I forked the plugin and added some debug code to get more details. The updated error reports I'm seeing show that Error code 20 happens on Android 7, 8 and 9 when READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions are requested and the READ_EXTERNAL_STORAGE permission is denied.