SurfaceView для предварительного просмотра камеры не будет уничтожен при нажатии кнопки питания

Я хочу реализовать предварительный просмотр камеры. Для этого у меня есть пользовательский вид CameraView extends ViewGroup, который в конструкторе программно создает SurfaceView.

У меня есть следующие компоненты (сильно упрощенные для Беверити):

ScannerFragment.java

public View onCreateView(..) {
   //inflate view and get cameraView
}

public void onResume() {
   //open camera -> set rotation -> startPreview (in a thread) -> 
   //set preview callback -> start decoding worker
}

public void onPause() {
   // stop decoding worker -> stop Preview -> release camera
}

CameraView.java расширяет ViewGroup

public void setUpCalledInConstructor(Context context) {
   //create a surfaceview and add it to this viewgroup ->
   //get SurfaceHolder and set callback
}

/* SurfaceHolder.Callback */
public void surfaceCreated(SurfaceHolder holder) {
   camera.setPreviewDisplay(holder);
}

public void surfaceDestroyed(SurfaceHolder holder) {
    //NOTHING is done here
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    camera.getParameters().setPreviewSize(previewSize.width, previewSize.height);
}

фрагмент_сканер.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.myapp.camera.CameraView
        android:id="@+id/cameraPreview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

Я думаю, что правильно установил жизненный цикл (получение ресурсов onResume(), грубо говоря, освобождение onPause()), и следующее работает отлично:

  • нажать домой и вернуться
  • нажав Taskswitcher и вернувшись
  • вращение
  • отжиматься (конечно)

Но одна вещь не работает, и это когда я нажимаю кнопку питания на устройстве, а затем возвращаюсь к предварительному просмотру камеры. Результат: предварительный просмотр застрял на изображении, которое было последним захвачено до нажатия кнопки. Если я поверну, он снова будет работать нормально, так как он пройдет через жизненный цикл.

После некоторых исследований я обнаружил, что это, вероятно, из-за того, что SurfaceView не будет уничтожен при нажатии кнопки питания, т.е. SurfaceHolder.Callback.surfaceDestroyed(SurfaceHolder holder) не будет вызываться. И на самом деле, когда я сравниваю (очень подробный) вывод журнала для случая домашней кнопки и случая кнопки питания, это то же самое, за исключением того, что «surfaceDestroyed» не вызывается.

Пока я не нашел никакого решения, чтобы обойти это. Я намеренно избегаю кода очистки ресурсов в моем surfaceDestroyed(), но это не помогает. Моя идея заключалась в том, чтобы вручную уничтожить SurfaceView, как задано в этом вопросе, но это кажется невозможным. Я также протестировал другие приложения с SurfaceViews/камерами, и у них, похоже, нет этой проблемы. Поэтому буду признателен за любые подсказки или советы по этому поводу.


person Patrick Favre    schedule 03.11.2013    source источник
comment
Напомним: проблема заключалась в ошибке в жизненном цикле приложения. В основном некоторые onCreate/onResume пропустили некоторые настройки, необходимые в конкретных случаях.   -  person Patrick Favre    schedule 18.11.2018


Ответы (2)


Просто попробуйте добавить

 public void onDestroy() {
 // stop decoding worker -> stop Preview -> release camera
}

как это сделано для onPause(), потому что он может вызываться до тех пор, пока метод паузы.

В моем releaseCamera() это то, что я делаю

    private void releaseCamera() {
    if (myCamera != null) {
        FrameLayout preview = (FrameLayout) findViewById(R.id.cameraPreview);
        preview.removeView(myPreview);
        myCamera.setPreviewCallback(null);
        myCamera.release();
        myCamera = null;

    }
}

Я отсоединяю CameraPreview (myPreview), который содержит текущую картинку. И полностью уничтожить камеру.

person MonkeyDroid    schedule 18.02.2014
comment
Проблема не в том, что мой код остановки/уничтожения не вызывается, а в том, что у меня нет возможности вручную уничтожить представление поверхности, потому что оно должно уничтожить себя. - person Patrick Favre; 19.02.2014

mPreview.getHolder().removeCallback(mPreview); должно помочь?

person Shri    schedule 18.02.2014