android : camera doesn't open in marshmallow

So, I have below code that open camera, capture the image and save it on SDCard.

public void getPhotoFromCamera() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    File mediaStorageDir = new File(
            Environment.getExternalStorageDirectory()
                    + File.separator
                    + getString(R.string.directory_name_corp_chat)
                    + File.separator
                    + getString(R.string.directory_name_temp)
    );

    if (!mediaStorageDir.exists()) {
        mediaStorageDir.mkdirs();
    }

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
            Locale.getDefault()).format(new Date());
    try {
        mediaFile = File.createTempFile(
                "TEMP_FULL_IMG_" + timeStamp,
                ".jpg",
                mediaStorageDir
        );
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mediaFile));
        startActivityForResult(takePictureIntent, PICK_FROM_CAMERA);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void performCrop(Uri picUri) {
    try {
        Intent cropIntent = new Intent("com.android.camera.action.CROP");
        cropIntent.setDataAndType(picUri, "image/*");
        cropIntent.putExtra("crop", "true");
        cropIntent.putExtra("aspectX", 1);
        cropIntent.putExtra("aspectY", 1);
        cropIntent.putExtra("outputX", 128);
        cropIntent.putExtra("outputY", 128);
        // retrieve data on return
        cropIntent.putExtra("return-data", true);

        File mediaStorageDir = new File(
                Environment.getExternalStorageDirectory()
                        + File.separator
                        + getString(R.string.directory_name_corp_chat)
                        + File.separator
                        + getString(R.string.directory_name_temp)
        );

        if (!mediaStorageDir.exists()) {
            mediaStorageDir.mkdirs();
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
                Locale.getDefault()).format(new Date());
        try {
            croppedFile = File.createTempFile(
                    "TEMP_CROPPED_IMG_" + timeStamp,
                    ".jpg",
                    mediaStorageDir
            );
            cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(croppedFile));
            startActivityForResult(cropIntent, PIC_CROP);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // respond to users whose devices do not support the crop action
    catch (ActivityNotFoundException anfe) {
        // display an error message
        String errorMessage = "Whoops - your device doesn't support the crop action!";
        Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
        toast.show();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == PICK_FROM_CAMERA) {
        if (resultCode == RESULT_OK) {
            performCrop(Uri.fromFile(mediaFile));
        } else {
            Log.i("Camera", "result cancel. Hence, deleting file: " + mediaFile.getPath());
            Log.i("File deleted ", mediaFile.delete() + "");
        }
    }

    if (requestCode == PICK_FROM_GALLERY) {
        if (resultCode == RESULT_OK) {
            performCrop(data.getData());
        } else {
            Log.i("Gallery", "result cancel");
        }
    }

    if (requestCode == PIC_CROP) {
        if (resultCode == RESULT_OK) {
            imageView.setImageBitmap(BitmapFactory.decodeFile(croppedFile.getAbsolutePath()));
            if (mediaFile != null) {
                Log.i("Camera", "result cancel. Hence, deleting file: " + mediaFile.getPath());
                Log.i("File deleted ", mediaFile.delete() + "");
            }
        } else {
            if (croppedFile != null) {
                Log.i("Camera", "result cancel. Hence, deleting file: " + croppedFile.getPath());
                Log.i("File deleted ", croppedFile.delete() + "");
            }
            if (mediaFile != null) {
                Log.i("Camera", "result cancel. Hence, deleting file: " + mediaFile.getPath());
                Log.i("File deleted ", mediaFile.delete() + "");
            }
        }
    }
}

Everything works perfect as expected below Android 6.0. But it doesn’t work on Android 6.0 Marshmallow. In fact it doesn’t even open the camera 🙁

  • CamcorderProfile.QUALITY_HIGH resolution produces green flickering video
  • Android: SQLite transactions when using ContentResolver
  • Get the file size in android sdk?
  • Android ScrollView doesn't scroll when the keyboard is up
  • Android Studio: Switching a URL depending on buildtype? (used for testing in debug /release)
  • Self-compiled dalvik doesn't load shared libraries
  • I don’t know whether I have to do something special for marshmallow. I am not getting any kind of error too, that I can post it here. Please help me out.

    Thanks.

    Related posts:

    create Bitmap from byteArray in android
    OpenGL ES drop shadows for 2D sprites
    Android SDK Windows Failed to execute Android.bat
    Cordova + JqueryMobile: Ajax fails with
    Resource id cannot be an empty string (at 'text' with value '?')...
    Custom ttf fonts are not showing properly in TextView on Android 4.4 KitKat
  • RadioGroup: How to check programmatically
  • When Is a TextureView's “Consumer Side” Closed?
  • Check if intent uri is available
  • Unexpected LayoutParams with an inflated LinearLayout
  • How to add a calendar event on an Android device with a given date?
  • How to read a pdf in android
  • 2 Solutions collect form web for “android : camera doesn't open in marshmallow”

    So, I accomplished my task like as below:

    For Checking permission I created a separate class as below:

    public class MarshMallowPermission {
    
        public static final int RECORD_PERMISSION_REQUEST_CODE = 1;
        public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 2;
        public static final int CAMERA_PERMISSION_REQUEST_CODE = 3;
        Activity activity;
    
        public MarshMallowPermission(Activity activity) {
            this.activity = activity;
        }
    
        public boolean checkPermissionForRecord(){
            int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO);
            if (result == PackageManager.PERMISSION_GRANTED){
                return true;
            } else {
                return false;
            }
        }
    
        public boolean checkPermissionForExternalStorage(){
            int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (result == PackageManager.PERMISSION_GRANTED){
                return true;
            } else {
                return false;
            }
        }
    
        public boolean checkPermissionForCamera(){
            int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
            if (result == PackageManager.PERMISSION_GRANTED){
                return true;
            } else {
                return false;
            }
        }
    
        public void requestPermissionForRecord(){
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.RECORD_AUDIO)){
               Toast.makeText(activity, "Microphone permission needed for recording. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
            } else {
                ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.RECORD_AUDIO},RECORD_PERMISSION_REQUEST_CODE);
            }
        }
    
        public void requestPermissionForExternalStorage(){
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
                Toast.makeText(activity, "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
            } else {
                ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
            }
        }
    
        public void requestPermissionForCamera(){
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
                Toast.makeText(activity, "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
            } else {
                ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
            }
        }
    }
    

    Then, for getting

    ...
    MarshMallowPermission marshMallowPermission = new MarshMallowPermission(this);
    ...
    
    public void getPhotoFromCamera() {
    
        if (!marshMallowPermission.checkPermissionForCamera()) {
            marshMallowPermission.requestPermissionForCamera();
        } else {
            if (!marshMallowPermission.checkPermissionForExternalStorage()) {
                marshMallowPermission.requestPermissionForExternalStorage();
            } else {
                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File mediaStorageDir = new File(
                        Environment.getExternalStorageDirectory()
                                + File.separator
                                + getString(R.string.directory_name_corp_chat)
                                + File.separator
                                + getString(R.string.directory_name_images)
                );
    
                if (!mediaStorageDir.exists()) {
                    mediaStorageDir.mkdirs();
                }
    
                String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
                        Locale.getDefault()).format(new Date());
                try {
                    mediaFile = File.createTempFile(
                            "IMG_" + timeStamp,  /* prefix */
                            ".jpg",         /* suffix */
                            mediaStorageDir      /* directory */
                    );
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mediaFile));
                    startActivityForResult(takePictureIntent, PICK_FROM_CAMERA);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    Quoting developers.android.com:

    Beginning in Android 6.0 (API level 23), users grant permissions to
    apps while the app is running, not when they install the app. This
    approach streamlines the app install process, since the user does not
    need to grant permissions when they install or update the app. It also
    gives the user more control over the app’s functionality; for example,
    a user could choose to give a camera app access to the camera but not
    to the device location. The user can revoke the permissions at any
    time, by going to the app’s Settings screen.

    System permissions are divided into two categories, normal and
    dangerous:

    • Normal permissions do not directly risk the user’s privacy. If your
      app lists a normal permission in its manifest, the system grants the
      permission automatically.

    • Dangerous permissions can give the app
      access to the user’s confidential data. If your app lists a normal
      permission in its manifest, the system grants the permission
      automatically. If you list a dangerous permission, the user has to
      explicitly give approval to your app.

    WRITE_EXTERNAL_STORAGE is in the Dangerous category, for this reason you need to request the permission to the user before call mediaStorageDir.mkdirs() or File.createTempFile otherwise you program crash with this exception:

    W/System.err: java.io.IOException: open failed: EACCES (Permission denied)
    W/System.err:     at java.io.File.createNewFile(File.java:939)
    W/System.err:     at java.io.File.createTempFile(File.java:1004)
    W/System.err:     at com.example.MainActivity.getPhotoFromCamera(MainActivity.java:98)
    W/System.err:     at com.example.MainActivity.onCreate(MainActivity.java:48)
    W/System.err:     at android.app.Activity.performCreate(Activity.java:6237)
    W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.
    W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.
    W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476
    W/System.err:     at android.app.ActivityThread.-wrap11(ActivityThread.java)
    W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
    W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
    W/System.err:     at android.os.Looper.loop(Looper.java:148)
    W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
    W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
    W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.
    W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission 
    W/System.err:     at libcore.io.Posix.open(Native Method)
    W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
    W/System.err:     at java.io.File.createNewFile(File.java:932)
    W/System.err:   ... 15 more
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.