Android намерение ACTION_IMAGE_CAPTURE

Мы пытаемся использовать собственное приложение для камеры, чтобы позволить пользователю сделать новый снимок. Это работает просто великолепно, если мы не учитываем EXTRA_OUTPUT extra и возвращает маленькое Растровое изображение. Однако, если мы putExtra(EXTRA_OUTPUT,...) на намерении прежде, чем запустить его, все работает, пока Вы не пытаетесь нажать кнопку "Ok" в приложении для камеры. Кнопка "Ok" просто ничего не делает. Приложение для камеры остается открытым, и ничто не запирается. Мы можем отменить из него, но файл никогда не пишется. Что точно делает мы должны сделать для получения ACTION_IMAGE_CAPTURE записать снимок, сделанный в файл?

Править: Это сделано через MediaStore.ACTION_IMAGE_CAPTURE намерение, только чтобы быть ясным

161
задан Alex Cohn 25 December 2017 в 15:07
поделиться

3 ответа

это хорошо задокументированная ошибка в некоторых версиях Android. то есть в сборках Android для Google Experience захват изображений работает не так, как описано в документации. то, что я обычно использовал, это что-то вроде этого в классе утилит.

public boolean hasImageCaptureBug() {

    // list of known devices that have the bug
    ArrayList<String> devices = new ArrayList<String>();
    devices.add("android-devphone1/dream_devphone/dream");
    devices.add("generic/sdk/generic");
    devices.add("vodafone/vfpioneer/sapphire");
    devices.add("tmobile/kila/dream");
    devices.add("verizon/voles/sholes");
    devices.add("google_ion/google_ion/sapphire");

    return devices.contains(android.os.Build.BRAND + "/" + android.os.Build.PRODUCT + "/"
            + android.os.Build.DEVICE);

}

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

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (hasImageCaptureBug()) {
    i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp")));
} else {
    i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
startActivityForResult(i, mRequestCode);

затем в действии, к которому я возвращаюсь, я делаю разные вещи на основе устройства.

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
     switch (requestCode) {
         case GlobalConstants.IMAGE_CAPTURE:
             Uri u;
             if (hasImageCaptureBug()) {
                 File fi = new File("/sdcard/tmp");
                 try {
                     u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null));
                     if (!fi.delete()) {
                         Log.i("logMarker", "Failed to delete " + fi);
                     }
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
                 }
             } else {
                u = intent.getData();
            }
    }

это избавляет вас от необходимости писать новое приложение камеры, но и этот код не очень хорош. большие проблемы

  1. : вы никогда не получите полноразмерные изображения устройства с ошибкой. Вы получаете изображения шириной 512 пикселей, вставляются в содержимое изображения провайдер. на устройствах без ошибка, все работает как документ, вы получите большую нормальную картину.

  2. вы должны вести список. как написано, можно для устройств быть прошит версией android (скажем cyanogenmod's builds ), в которой исправлена ​​ошибка. если это произойдет, ваш код будет авария. исправление состоит в том, чтобы использовать весь отпечаток устройства.

144
ответ дан 23 November 2019 в 21:26
поделиться

Описываемый вами рабочий процесс должен работать так, как вы его описали. Может помочь, если вы покажете нам код вокруг создания Замысла. В общем, следующий шаблон должен позволить вам сделать то, что вы пытаетесь сделать.

private void saveFullImage() {
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  File file = new File(Environment.getExternalStorageDirectory(), "test.jpg");
  outputFileUri = Uri.fromFile(file);
  intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
  startActivityForResult(intent, TAKE_PICTURE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if ((requestCode == TAKE_PICTURE) && (resultCode == Activity.RESULT_OK)) {
    // Check if the result includes a thumbnail Bitmap
    if (data == null) {    
      // TODO Do something with the full image stored
      // in outputFileUri. Perhaps copying it to the app folder
    }
  }
}

Обратите внимание, что именно работа Camera будет создавать и сохранять файл, и на самом деле он не является частью вашего приложения, поэтому у него не будет разрешения на запись в папку вашего приложения. Чтобы сохранить файл в папку приложения, создайте временный файл на SD-карте и переместите его в папку приложения в обработчике onActivityResult.

.
28
ответ дан 23 November 2019 в 21:26
поделиться

, чтобы камера записывала на SD-карту, но оставалась в новом альбоме в приложении галереи. Я использую это:

 File imageDirectory = new File("/sdcard/signifio");
          String path = imageDirectory.toString().toLowerCase();
           String name = imageDirectory.getName().toLowerCase();


            ContentValues values = new ContentValues(); 
            values.put(Media.TITLE, "Image"); 
            values.put(Images.Media.BUCKET_ID, path.hashCode());
            values.put(Images.Media.BUCKET_DISPLAY_NAME,name);

            values.put(Images.Media.MIME_TYPE, "image/jpeg");
            values.put(Media.DESCRIPTION, "Image capture by camera");
           values.put("_data", "/sdcard/signifio/1111.jpg");
         uri = getContentResolver().insert( Media.EXTERNAL_CONTENT_URI , values);
            Intent i = new Intent("android.media.action.IMAGE_CAPTURE"); 

            i.putExtra(MediaStore.EXTRA_OUTPUT, uri);

            startActivityForResult(i, 0); 

Обратите внимание, что вам нужно будет каждый раз генерировать уникальное имя файла и заменять 1111.jpg, который я написал. Это было протестировано с nexus one. uri объявлен в частном классе, поэтому в результате действия я могу загрузить изображение из uri в imageView для предварительного просмотра, если это необходимо.

4
ответ дан 23 November 2019 в 21:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: