Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android M Camera Intent + permission bug?

I'm trying to get my app ready for the new Android M permissions changes and found some weird behaviour. My app uses the Camera intent mechanism to allow the user to get a picture form the camera. But in another activity needs to make use of the camera itself with Camera permission (because of a library dependency card.io that requires this).

However with M in the activity that only needs a camera intent when I try to launch the Camera intent I see the following crash (this does not happen if I remove the Camera permission from the Manifest),

> 09-25 21:57:55.260 774-8053/? I/ActivityManager: START u0 > {act=android.media.action.IMAGE_CAPTURE flg=0x3000003 > pkg=com.google.android.GoogleCamera > cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity > (has clip) (has extras)} from uid 10098 on display 0 09-25 > 21:57:55.261 774-8053/? W/ActivityManager: Permission Denial: starting > Intent { act=android.media.action.IMAGE_CAPTURE flg=0x3000003 > pkg=com.google.android.GoogleCamera > cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity > (has clip) (has extras) } from null (pid=-1, uid=10098) with revoked > permission android.permission.CAMERA 09-25 21:57:55.263 32657-32657/? > E/ResolverActivity: Unable to launch as uid 10098 package > com.example.me.mycamerselectapp, while running in android:ui 09-25 > 21:57:55.263 32657-32657/? E/ResolverActivity: > java.lang.SecurityException: Permission Denial: starting Intent { > act=android.media.action.IMAGE_CAPTURE flg=0x3000003 > pkg=com.google.android.GoogleCamera > cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity > (has clip) (has extras) } from null (pid=-1, uid=10098) with revoked > permission android.permission.CAMERA 09-25 21:57:55.263 32657-32657/? > E/ResolverActivity:     at > android.os.Parcel.readException(Parcel.java:1599) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > android.os.Parcel.readException(Parcel.java:1552) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > android.app.ActivityManagerProxy.startActivityAsCaller(ActivityManagerNative.java:2730) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > android.app.Instrumentation.execStartActivityAsCaller(Instrumentation.java:1725) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > android.app.Activity.startActivityAsCaller(Activity.java:4047) 09-25 > 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.app.ResolverActivity$DisplayResolveInfo.startAsCaller(ResolverActivity.java:983) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.app.ResolverActivity.safelyStartActivity(ResolverActivity.java:772) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.app.ResolverActivity.onTargetSelected(ResolverActivity.java:754) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.app.ChooserActivity.onTargetSelected(ChooserActivity.java:305) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.app.ResolverActivity.startSelected(ResolverActivity.java:603) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.app.ChooserActivity.startSelected(ChooserActivity.java:310) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.app.ChooserActivity$ChooserRowAdapter$2.onClick(ChooserActivity.java:990) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > android.view.View.performClick(View.java:5198) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > android.view.View$PerformClick.run(View.java:21147) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > android.os.Handler.handleCallback(Handler.java:739) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > android.os.Handler.dispatchMessage(Handler.java:95) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > android.os.Looper.loop(Looper.java:148) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > android.app.ActivityThread.main(ActivityThread.java:5417) 09-25 > 21:57:55.263 32657-32657/? E/ResolverActivity:     at > java.lang.reflect.Method.invoke(Native Method) 09-25 21:57:55.263 > 32657-32657/? E/ResolverActivity:     at > com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) > 09-25 21:57:55.263 32657-32657/? E/ResolverActivity:     at > com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 09-25 > 21:57:55.286 1159-1159/? I/Keyboard.Facilitator: onFinishInput() 09-25 > 21:57:55.297 32657-32676/? E/Surface: getSlotFromBufferLocked: unknown > buffer: 0xaec352e0 09-25 21:57:55.344 325-349/? V/RenderScript: > 0xb3693000 Launching thread(s), CPUs 4 09-25 21:57:57.290 325-349/? > E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb3f88240 

Is this a known problem with Android M? And more importantly how do I work around this?

in the manifest I have the following,

<uses-permission android:name="android.permission.CAMERA" /> 

and this is the code I use to let the user click a pic with the Camera and/or select an image

public static Intent openImageIntent(Context context, Uri cameraOutputFile) {      // Camera.     final List<Intent> cameraIntents = new ArrayList<Intent>();     final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);     final PackageManager packageManager = context.getPackageManager();     final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);     for(ResolveInfo res : listCam) {         final String packageName = res.activityInfo.packageName;         final Intent intent = new Intent(captureIntent);         intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));         intent.setPackage(packageName);         intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraOutputFile);         cameraIntents.add(intent);     }      // Filesystem.     final Intent galleryIntent = new Intent();     galleryIntent.setType("image/*");     galleryIntent.setAction(Intent.ACTION_GET_CONTENT);      // Chooser of filesystem options.     final Intent chooserIntent = Intent.createChooser(galleryIntent, "Take or select pic");      // Add the camera options.     chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));     return chooserIntent; } 

I call the openImageIntent() on a button click in my activity. When I do not have the CAMERA permission in my app it works fine, but with that added I get the exception posted above.

    @Override     public void onClick(View v) {         Intent picCaptureIntenet = openImageIntent(MainActivity.this, getTempImageFileUri(MainActivity.this));         try {             startActivityForResult(picCaptureIntenet, 100);         } catch(Exception e) {             Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();         }     } 

like image 228
source.rar Avatar asked Sep 25 '15 19:09

source.rar


People also ask

How do I open camera with intent?

This is done as follows: Intent camera_intent = new Intent(MediaStore. ACTION_IMAGE_CAPTURE); startActivityForResult(camera_intent, pic_id); Now use the onActivityResult() method to get the result, here is the captured image.

What is camera intent?

Take a photo with a camera appAndroid delegates actions to other applications by invoking an Intent . This process involves three pieces: the Intent itself, a call to start the external Activity , and some code to handle the image data when focus returns to your activity.


1 Answers

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; } 
like image 73
luna Avatar answered Oct 18 '22 04:10

luna