4

カメラプレビューを実装したい。そのため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);
}

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>

私はライフサイクルを正しく設定したと思います(リソースを取得する onResume()、それを解放する onPause() 大まかに言った)、次のようにうまく動作します:

  • ホームを押して戻る
  • タスクスイッチャーを押して戻る
  • 回転
  • 押し返す(もちろん)

しかし、うまくいかないことが 1 つあります。それは、デバイスの電源ボタンを押してからカメラ プレビューに戻ったときです。結果は次のとおりです。プレビューは、ボタンが押される前に最後にキャプチャされた画像でスタックします。ローテーションすると、ライフサイクルを通過するため、再び正常に動作します。

いくつかの調査の結果、これはおそらく、電源ボタンが押されたときに surfaceView が破棄されない、つまり呼び出されないという事実が原因であることがわかりましたSurfaceHolder.Callback.surfaceDestroyed(SurfaceHolder holder)。実際、ホームボタンの場合と電源ボタンの場合の (非常に詳細な) ログ出力を比較すると、「surfaceDestroyed」が呼び出されないことを除いて同じです。

これまでのところ、それを回避するための解決策はまったく見つかりませんでした。のリソース クリーニング コードを意図的に避けてsurfaceDestroyed()いますが、これは役に立ちません。私の考えは、この質問で尋ねられたように surfaceView を手動で破棄することでしたが、これは不可能のようです。SurfaceViews/cameras を使用して他のアプリケーションもテストしましたが、この問題はないようです。そのため、それに関するヒントやヒントをいただければ幸いです。

4

2 に答える 2

1

追加してみてください

 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) を切り離します。そしてカメラを完全に破壊します。

于 2014-02-18T15:20:58.237 に答える