Я хочу реализовать предварительный просмотр камеры. Для этого у меня есть пользовательский вид 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/камерами, и у них, похоже, нет этой проблемы. Поэтому буду признателен за любые подсказки или советы по этому поводу.