Android M Camera Intent + Permission Bug?


Answer :

I had the same issue and find this doc from google: https://developer.android.com/reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE

"Note: if you app targets M and above and declares as using the CAMERA permission which is not granted, then atempting to use this action will result in a SecurityException."

This is really weird. Don't make sense at all. The app declares Camera permission using intent with action IMAGE_CAPTURE just run into SecurityException. But if your app doesn't declare Camera permission using intent with action IMAGE_CAPTURE can launch Camera app without issue.

The workaround would be check is the app has camera permission included in the manifest, if it's , request camera permission before launching intent.

Here is the way to check if the permission is included in the manifest, doesn't matter the permission is granted or not.

public boolean hasPermissionInManifest(Context context, String permissionName) {     final String packageName = context.getPackageName();     try {         final PackageInfo packageInfo = context.getPackageManager()                 .getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);         final String[] declaredPermisisons = packageInfo.requestedPermissions;         if (declaredPermisisons != null && declaredPermisisons.length > 0) {             for (String p : declaredPermisisons) {                 if (p.equals(permissionName)) {                     return true;                 }             }         }     } catch (NameNotFoundException e) {      }     return false; } 

If you are using the Android M permission model, you first need to check if the app has this permission during runtime, and have to prompt the user for this permission during runtime. The permission you define on your manifest will not automatically be granted on install time.

if (checkSelfPermission(Manifest.permission.CAMERA)         != PackageManager.PERMISSION_GRANTED) {      requestPermissions(new String[]{Manifest.permission.CAMERA},             MY_REQUEST_CODE); } 

MY_REQUEST_CODE is a static constant that you can define, which will be used again for the requestPermission dialog callback.

You will need a callback for the dialog result:

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {     super.onRequestPermissionsResult(requestCode, permissions, grantResults);     if (requestCode == MY_REQUEST_CODE) {         if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {             // Now user should be able to use camera         }         else {             // Your app will not have this permission. Turn off all functions              // that require this permission or it will force close like your              // original question         }     } } 

edit

Reading from the stack trace, it looks like Google Camera doesn't have the CAMERA permission enabled. This might actually look like a backwards compatibility thing after all.

Let's assume that Google Camera (or whatever other application handling your ACTION intent) requires a certain permission.

When your app does not have the CAMERA permission, it is just letting Google Camera do it's thing with the old permissions model.

However, with the CAMERA permission declared in your manifest, it is also enforcing the CAMERA permission within Google Camera (which does not have Android M permissions model) to use the Android M permissions model (I think.)

So that means using the above method, you will need to provide your app permission during runtime, which means its child task (in this case Google Camera) will now also have that permission.


As far as your question 'Is this a known problem in M?' A google dev responded to someone reporting this issue as a bug.

See here: https://issuetracker.google.com/issues/37063818#comment8

Here is the word from the Google guy: “ This is intended behavior to avoid user frustration where they revoked the camera permission from an app and the app still being able to take photos via the intent. Users are not aware that the photo taken after the permission revocation happens via different mechanism and would question the correctness of the permission model. This applies to MediaStore.ACTION_IMAGE_CAPTURE, MediaStore.ACTION_VIDEO_CAPTURE, and Intent.ACTION_CALL the docs for which document the behavior change for apps targeting M."

Since Google doesn't mind abstracting the mechanics of using the camera from your user, you might as well strategically trigger the first request for camera permission and reference the functionality of the Activity that uses the Camera as your reasoning for the request. If you allow your app to first make this permission request when the user is simply attempting to take a picture, the user may think your app is behaving strangely as taking a photo does not typically require granting permission.


Comments

Popular posts from this blog

Converting A String To Int In Groovy

"Cannot Create Cache Directory /home//.composer/cache/repo/https---packagist.org/, Or Directory Is Not Writable. Proceeding Without Cache"

Android How Can I Convert A String To A Editable