Android: камера не открывается в зефире

Итак, у меня есть код ниже, который открывает камеру, захватывает изображение и сохраняет его на 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() + ""); } } } } 

Все работает как ожидалось ниже Android 6.0. Но он не работает на Android 6.0 Marshmallow. На самом деле он даже не открывает камеру 🙁

Я не знаю, нужно ли мне делать что-то особенное для зефира. Я тоже не получаю никаких ошибок, могу опубликовать его здесь. Пожалуйста, помогите мне.

Благодарю.

    Итак, я выполнил свою задачу, как показано ниже:

    Для проверки разрешения я создал отдельный class, как показано ниже:

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

    Затем для получения

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

    Цитата developer.android.com :

    Начиная с Android 6.0 (уровень API 23), пользователи предоставляют разрешения для приложений во время работы приложения, а не при установке приложения. Этот подход упрощает процесс установки приложения, поскольку пользователю не нужно предоставлять разрешения при установке или обновлении приложения. Он также дает пользователю больше контроля над функциональностью приложения; например, пользователь может выбрать доступ к камере для камеры, но не к местоположению устройства. Пользователь может отменить разрешения в любое время, перейдя на экран настроек приложения.

    Системные разрешения делятся на две категории: нормальные и опасные:

    • Обычные разрешения напрямую не влияют на конфиденциальность пользователя. Если ваше приложение отображает нормальное разрешение в своем манифесте, система автоматически предоставляет разрешение.

    • Опасные разрешения могут предоставить приложению доступ к конфиденциальным данным пользователя. Если ваше приложение отображает нормальное разрешение в своем манифесте, система автоматически предоставляет разрешение. Если вы указываете опасное разрешение, пользователь должен явно предоставить одобрение вашему приложению.

    WRITE_EXTERNAL_STORAGE находится в категории Dangerous, поэтому вам нужно запросить разрешение пользователя перед вызовом mediaStorageDir.mkdirs() или File.createTempFile иначе вы File.createTempFile :

     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 
    Давайте будем гением компьютера.