2015-10-10 2 views
18

Итак, у меня есть код, который открывает камеру, захватывает изображение и сохраняет его на SDCard.android: камера не открывается в зефире

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. На самом деле он даже не открывает камеру :(

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

Благодаря

ответ

34

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

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

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

У меня было приложение, работающее на устройстве с Lollipop, а затем не удалось на двух устройствах, работавших с Marshmallow. Я получал сообщение при запуске. Кажется, ваше устройство не поддерживает камеру (или она заблокирована). Я проследил ошибку через Camera.open() полностью до Camera.cameraInitVersion(), где он возвращал ошибку, не имея возможности получить доступ к службе Camera. Не понял, что для модели разрешения на Marshmallow необходимы изменения в кодировке. – medloh

+0

@ChintanSoni это Показать один запрос Только за один раз в приложении? – RushDroid

+1

что такое mediaFile? это файл? спасибо за пример! –

7

Цитирование developers.android.com:..

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

Системные требования делятся на две категории, нормальный и опасному:

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

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

WRITE_EXTERNAL_STORAGE находится в опасной категории, по этой причине вы должны просить разрешения для пользователя перед вызовом mediaStorageDir.mkdirs() или 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 
+0

Спасибо .. За указание этой особенности Зефир .. Я не знаю, как я его забыл? В любом случае .. Спасибо .. Я пытаюсь дать разрешение на запуск и вскоре обновить вопрос. –

+0

Чувак, ты, черт возьми, спас мой хвост. Большое спасибо. Вы джентльмен и негодяй.;) – LukeWaggoner

+0

Согласно рекомендациям, в нем также говорится, что вы можете избежать слишком большого количества разрешений, используя намерения использовать другие приложения, такие как камера, для выполнения этой работы. Это означает, что приложение камеры должно иметь необходимые разрешения для съемки и должно возвращать результат. Правильно? Если это так, то почему его камера не открывается? Я спрашиваю, потому что у меня проблема с моим приложением, где результат кода не RESULT_OK. Я думаю, что это связано с этим изменением прав доступа. –

Смежные вопросы