web-dev-qa-db-fra.com

android: la caméra ne s'ouvre pas dans la guimauve

Donc, j'ai ci-dessous le code qui ouvre la caméra, capture l'image et l'enregistre sur 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() + "");
            }
        }
    }
}

Tout fonctionne parfaitement comme prévu ci-dessous Android 6.0. Mais cela ne fonctionne pas sur Android 6.0 Marshmallow. En fait, il n'ouvre même pas la caméra :(

Je ne sais pas si je dois faire quelque chose de spécial pour Marshmallow. Je ne reçois pas non plus d'erreur, que je peux poster ici. Sil te plait aide moi.

Merci.

18
Chintan Soni

J'ai donc accompli ma tâche comme ci-dessous:

Pour vérifier l'autorisation, j'ai créé une classe distincte comme ci-dessous:

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);
        }
    }
}

Ensuite, pour obtenir

...
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();
            }
        }
    }
}
34
Chintan Soni

Citation developers.Android.com :

À partir de Android 6.0 (API niveau 23), les utilisateurs accordent des autorisations aux applications pendant que l'application est en cours d'exécution, et non lorsqu'ils installent l'application. Cette approche rationalise le processus d'installation de l'application, car l'utilisateur ne le fait pas doivent accorder des autorisations lors de l'installation ou de la mise à jour de l'application. Cela donne également à l'utilisateur plus de contrôle sur les fonctionnalités de l'application; par exemple, un utilisateur peut choisir de donner à une application de caméra un accès à la caméra mais pas à l'emplacement de l'appareil. L'utilisateur peut révoquer les autorisations à tout moment, en allant à l'écran Paramètres de l'application.

Les autorisations système sont divisées en deux catégories, normales et dangereuses:

  • Les autorisations normales ne mettent pas directement en danger la vie privée de l'utilisateur. Si votre application répertorie une autorisation normale dans son manifeste, le système accorde automatiquement l'autorisation.

  • Des autorisations dangereuses peuvent donner à l'application accès aux données confidentielles de l'utilisateur. Si votre application répertorie une autorisation normale dans son manifeste, le système accorde automatiquement l'autorisation. Si vous répertoriez une autorisation dangereuse, l'utilisateur doit donner explicitement son approbation à votre application.

WRITE_EXTERNAL_STORAGE Est dans la catégorie Dangereux, pour cette raison, vous devez demander l'autorisation à l'utilisateur avant d'appeler mediaStorageDir.mkdirs() ou File.createTempFile Sinon vous programmez un plantage avec cette 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
7
Mattia Maestrini