Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 :(

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.

like image 908
Chintan Soni Avatar asked Oct 10 '15 06:10

Chintan Soni


2 Answers

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();
            }
        }
    }
}
like image 181
Chintan Soni Avatar answered Nov 15 '22 21:11

Chintan Soni


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
like image 7
Mattia Maestrini Avatar answered Nov 15 '22 20:11

Mattia Maestrini