I want to implement a camera preview. For that I have a custom View CameraView extends ViewGroup that in the constructor programatically creates an surfaceView.
I have the following components (higly simplified for beverity):
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 extends 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);
}
fragment_scanner.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>
I think I have set the lifecycle correct (getting resources onResume(), releasing it onPause() roughly said) and the following works just fine:
pressing home and returning
pressing Taskswitcher and returning
rotation
But one thing doesn't work and that is when I press the power-button on the device and then return to the camera-preview. The result is: the preview is stuck with the image that was last captured before button was pressed. If I rotate it works fine again, since it will get through the lifecycle.
After some research I found out that this is probably due to the fact that surfaceView won't get destroyed when the power-button is pressed, i.e. SurfaceHolder.Callback.surfaceDestroyed(SurfaceHolder holder) won't be called. And in fact when I compare the (very verbose) log output of the home-button-case and the power-button-case it's the same except that 'surfaceDestroyed' won't get called.
So far I found no solution whatsoever to work around it. I purposely avoid any resource cleaning code in my surfaceDestroyed(), but this does not help. My idea was to manually destroy the surfaceView like asked in this question but this seems not possible. I also tested other applications with surfaceViews/cameras and they don't seem to have this issue. So I would appreciate any hints or tips on that.