0

I'm debugging my application on my Nexus 5 with Android M 6.0.1 and I'm getting problems with camera's permissions. In my application I need to open the camera when a button is clicked, but it throws me this exception:

04-06 14:03:25.213 15330-15330/clyky.cartracker W/System.err: java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE flg=0x3 cmp=com.google.android.GoogleCamera/com.android.camera.activity.CaptureActivity clip={text/uri-list U:file:///storage/emulated/0/TesseractSample/imgs/ocr.jpg} (has extras) } from ProcessRecord{50bae23 15330:clyky.cartracker/u0a117} (pid=15330, uid=10117) with revoked permission android.permission.CAMERA
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.os.Parcel.readException(Parcel.java:1666)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.os.Parcel.readException(Parcel.java:1619)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2658)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.app.Activity.startActivityForResult(Activity.java:3930)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.app.Activity.startActivityForResult(Activity.java:3890)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at clyky.cartracker.activities.AddVehicleActivity.startCameraActivity(AddVehicleActivity.java:99)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at clyky.cartracker.activities.AddVehicleActivity.access$000(AddVehicleActivity.java:35)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at clyky.cartracker.activities.AddVehicleActivity$1.onClick(AddVehicleActivity.java:66)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.view.View.performClick(View.java:5204)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.view.View$PerformClick.run(View.java:21156)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.os.Looper.loop(Looper.java:148)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5458)
04-06 14:03:25.226 15330-15330/clyky.cartracker W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
04-06 14:03:25.227 15330-15330/clyky.cartracker W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
04-06 14:03:25.227 15330-15330/clyky.cartracker W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

I've already added permission of read/write external folder and camera in my manifest:

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

This is the method where I try to start the camera:

private void startCameraActivity()
{
    try
    {
        Log.d("debug", "sto provando a lanciare la fotocamera");
        String IMGS_PATH = Environment.getExternalStorageDirectory().toString() + "/TesseractSample/imgs";
        prepareDirectory(IMGS_PATH);

        String img_path = IMGS_PATH + "/ocr.jpg";

        outputFileUri = Uri.fromFile(new File(img_path));

        final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);

        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, PHOTO_REQUEST_CODE);
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

I think the problem is that the ask for camera's permissions is never shown. When my activity is launched it asks me for read/write external storage, but never for the camera. I've taken the code for the permissions on the web. It uses this class:

public class RequestPermissionsToolToolImpl implements RequestPermissionsTool
{
    private static final String CONFIRMATION_DIALOG = "ConfirmationDialog";
    private static final String TAG = RequestPermissionsToolToolImpl.class.getSimpleName();
    private Activity activity;

    @Override
    public void requestPermissions(Activity activity, String[] permissions)
    {
        Log.d("debug", "sto chiedendo i permessi.");
        int x = 0;

        Map<Integer, String> permissionsMap = new HashMap<>();
        this.activity = activity;


        for (int i = 0; i < permissions.length; i++) {
            permissionsMap.put(i, permissions[i]);
        }

        for (Map.Entry<Integer, String> permission : permissionsMap.entrySet())
        {
            if (!isPermissionGranted(activity, permission.getValue()))
            {
                if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission.getValue()))
                {
                    ConfirmationDialog.newInstance(permission.getKey(), permission.getValue()).show(activity.getFragmentManager(), CONFIRMATION_DIALOG);
                }
                else {
                    ActivityCompat.requestPermissions(activity, permissions,
                            permission.getKey());
                    return;
                }
            }
        }
    }

    @Override
    public boolean isPermissionsGranted(Context context, String[] permissions) {

        for (String permission : permissions)
        {
            if (!isPermissionGranted(context, permission)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void onPermissionDenied() {
        ErrorDialog.newInstance("Permission needs").
                show(activity.getFragmentManager(), CONFIRMATION_DIALOG);
    }

    private boolean isPermissionGranted(Context context, String permission)
    {
        return ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
    }


    /**
     * Shows OK/Cancel confirmation dialog about permission.
     */
    public static class ConfirmationDialog extends DialogFragment
    {

        private static final String ARG_PERMISSION = "permission";
        private static final String ARG_REQUEST_CODE = "request_code";

        public static ConfirmationDialog newInstance(int permissionKey, String permissionValue) {
            ConfirmationDialog dialog = new ConfirmationDialog();
            Bundle bundle = new Bundle();
            bundle.putString(ARG_PERMISSION, permissionValue);
            bundle.putInt(ARG_REQUEST_CODE, permissionKey);
            dialog.setArguments(bundle);
            return dialog;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            return new AlertDialog.Builder(getActivity())
                    .setMessage("Please allow permission")
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                            ActivityCompat.requestPermissions(getActivity(),
                                    new String[]{getArguments().getString(ARG_PERMISSION)},
                                    getArguments().getInt(ARG_REQUEST_CODE));
                        }
                    })
                    .setNegativeButton(android.R.string.cancel,
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    Toast.makeText(getActivity(), "Not available", Toast.LENGTH_SHORT).show();
                                }
                            })
                    .create();
        }
    }

    /**
     * Shows an error message dialog.
     */
    public static class ErrorDialog extends DialogFragment {

        private static final String ARG_MESSAGE = "message";

        public static ErrorDialog newInstance(String message) {
            ErrorDialog dialog = new ErrorDialog();
            Bundle args = new Bundle();
            args.putString(ARG_MESSAGE, message);
            dialog.setArguments(args);
            return dialog;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final Activity activity = getActivity();
            return new AlertDialog.Builder(activity)
                    .setMessage(getArguments().getString(ARG_MESSAGE))
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
//nothing
                        }
                    })
                    .create();
        }

    }
}

and these are methods in my activity which uses permissions:

private void requestPermissions()
    {
        String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
        requestTool = new RequestPermissionsToolToolImpl();
        requestTool.requestPermissions(this, permissions);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        boolean grantedAllPermissions = true;
        for (int grantResult : grantResults) {
            if (grantResult != PackageManager.PERMISSION_GRANTED) {
                grantedAllPermissions = false;
            }
        }

        if (grantResults.length != permissions.length || (!grantedAllPermissions)) {

            requestTool.onPermissionDenied();
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
  • 2
    Try this [enter link description here](http://stackoverflow.com/questions/32789027/android-m-camera-intent-permission-bug) – Alexander Palshyn Apr 06 '17 at 12:32
  • @Alexander Palshyn thank you very much, I've removed the camera permission's declaration in my manifest and now it works. I was completely unaware that Google Camera doesn't declare the camera permission. –  Apr 06 '17 at 12:50

1 Answers1

0

Use this simple piece of Code to open Camera in Android M or after versions

public static final int REQUEST_CAMERA = 111;

void checkPermissionToOpenCamera(){
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                if (ActivityCompat.checkSelfPermission(ProfileActivity.this, Manifest.permission.CAMERA)
                        != PackageManager.PERMISSION_GRANTED &&
                        ActivityCompat.checkSelfPermission(ProfileActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                                != PackageManager.PERMISSION_GRANTED) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(ProfileActivity.this,
                            Manifest.permission.CAMERA)) {
                        AlertDialog.Builder alertBuilder = new AlertDialog.Builder(ProfileActivity.this);
                        alertBuilder.setCancelable(false);
                        alertBuilder.setTitle("Permission necessary");
                        alertBuilder.setMessage("Camera and Gallery permissions are necessary");
                        alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(ProfileActivity.this,
                                        new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                        REQUEST_CAMERA);
                            }
                        });
                        AlertDialog alert = alertBuilder.create();
                        alert.show();
                    } else {
                        ActivityCompat.requestPermissions(ProfileActivity.this,
                                new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                REQUEST_CAMERA);
                    }
                } else {
                    startCameraActivity();
                }
            } else {
                startCameraActivity();
            } 
            }

Check permission status accept or decline by made a check in onRequestPermissionsResult like this :

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
   case REQUEST_CAMERA:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startCameraActivity();
            } else {
            Log.d(TAG,"You will not able to Upload your Profile picture");
            }
            break;
Kapil Rajput
  • 11,429
  • 9
  • 50
  • 65
  • thank you for your answer, but your solution doesn't work. it still gives me the security exception. –  Apr 06 '17 at 12:46