2

Я работаю над модификацией примера Camera2 API от Google для Android, здесь: https://github.com/googlesamples/android-Camera2BasicHandlerThread блоки UI андроид

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

Проблема, с которой я столкнулся, заключается в том, что пользовательский интерфейс фактически блокируется, когда изображение загружается, хотя из того, что я понимаю, это не должно быть, потому что обработчик создается с помощью Looper из фона нить так:

private void startBackgroundThread() { 
    mBackgroundThread = new HandlerThread("CameraBackground"); 
    mBackgroundThread.start(); 
    mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); 
} 

класс ImageSaver, который отвечает за запись образа на диск, выглядит следующим образом:

private static class ImageSaver implements Runnable { 
    /** 
    * The JPEG image 
    */ 
    private final Image mImage; 
    /** 
    * The file we save the image into. 
    */ 
    private final File mFile; 

    public ImageSaver(Image image, File file) { 
     mImage = image; 
     mFile = file; 
    } 

    @Override 
    public void run() { 
     ByteBuffer buffer = mImage.getPlanes()[0].getBuffer(); 
     byte[] bytes = new byte[buffer.remaining()]; 
     buffer.get(bytes); 
     FileOutputStream output = null; 
     try { 
      output = new FileOutputStream(mFile); 
      output.write(bytes); 
      InputStream is = new ByteArrayInputStream(bytes); 
      Map uploadResult = CloudinaryManager.getInstance().uploader().upload(is, ObjectUtils.asMap(
        "api_key", CloudinaryManager.CLOUDINARY_API_KEY, 
        "api_secret", CloudinaryManager.CLOUDINARY_SECRET_KEY 
      )); 
      System.out.println("result"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      mImage.close(); 
      if (null != output) { 
       try { 
        output.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

ImageSaver добавляется к обработчику здесь:

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener 
     = new ImageReader.OnImageAvailableListener() { 

    @Override 
    public void onImageAvailable(ImageReader reader) { 
     mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile)); 
    } 
}; 

Я хотел бы получить любую помощь или совет, чтобы указать мне в правильном направлении.

+0

Вы, кажется, правильно использовать HandlerThread, ошибка может быть где-то еще ...? –

+0

показать стопку, пожалуйста, журнал ошибок. Мы здесь не в гадании. –

ответ

0

Я считаю, что это потому, что камера используется в фоновом режиме ... Поскольку вы приобретаете изображение с ImageReader, я подозреваю, что он удерживает блокировку, пока вы не закончите с ресурсом ... Итак, в качестве предложения, я бы заполнил массив байтов внутри onImageAvailable, закройте полученное изображение и отправлю байт-массив в AsyncTask для выполнения сохранения.

0

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

Если вы посмотрите на метод unLockFocus(), вы можете увидеть, что камера вернет нормальное состояние предварительного просмотра.

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

  . 
      . 
      . 
      CameraCaptureSession.CaptureCallback CaptureCallback 
        = new CameraCaptureSession.CaptureCallback() { 

       @Override 
       public void onCaptureCompleted(@NonNull CameraCaptureSession session, 
               @NonNull CaptureRequest request, 
               @NonNull TotalCaptureResult result) { 
        showToast("Saved: " + mFile); 
        Log.d(TAG, mFile.toString()); 
        unlockFocus(); 
       } 
      }; 

Называя это на более раннем этапе в камере сохранить последовательность предварительный просмотр и пользовательский интерфейс снова разблокирован намного раньше.

Я экспериментировал и работает, если он вызван сразу после получения изображения и перед его сохранением. Я также удалил исходный вызов unLockFocus в captureCallback. Обратите внимание, что я не сделал никакого надлежащего тестирования гоночных условий и т.д., поэтому я настоятельно советую экспериментировать самостоятельно, чтобы убедиться, что ваш случай работает (я буду обновлять это, если я проверить его больше):

/** 
    * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a 
    * still image is ready to be saved. 
    */ 
    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener 
      = new ImageReader.OnImageAvailableListener() { 

     @Override 
     public void onImageAvailable(ImageReader reader) { 
      Log.d(TAG,"onImageAvailable"); 

      //Get the image 
      Image cameraImage = reader.acquireNextImage(); 

      //Now unlock the focus so the UI does not look locked - note that this is a much earlier point than in the 
      //original Camera2Basic example from google as the original place was causing the preview to lock during any 
      //image manipulation and saving. 
      unlockFocus(); 

      //Save the image file in the background - note check you have permissions granted by user or this will cause an exception. 
      mBackgroundHandler.post(new ImageSaver(getActivity().getApplicationContext(), cameraImage, outputPicFile); 

     } 

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