12

onPause()onResume()カメラのライブサイクルに問題があります。プレビュー付きのカメラで、写真の撮影はまったく問題なく機能します。1つの例外を除いて:

アプリを起動し、ホームボタンをクリックして、アプリに戻り、別のショットを撮ります。

結果:shuttercallbackは引き続き実行されます(コードを参照)が、jpegコールバックは実行されなくなりました!次に、私のギャラクシーSが振動し、jpegCallbackの後にstartPreview()が再トリガーされないため、画面が黒のままになります。スタックトレースは私にとって有用とはほど遠いです。奇妙なことに、これは私のGalaxy Sでのみ発生し、エミュレータでは発生しません。先に進む方法が本当にわかりません:/誰もが何が役立つか考えていますか?

10-28 18:59:40.649:ERROR / SecCamera(4291):SetRotate(angle(0))
10-28 18:59:40.649:ERROR / CameraHardwareSec(4291):==== setParametersprocessingmethod =(null)
10-28 18:59:40.649:ERROR / SecCamera(4291):setRecordingSize(width(800)、height(480))
10-28 18:59:40.673:ERROR / SecCamera(4291):SetRotate(angle(0))
10-28 18:59:40.673:ERROR / CameraHardwareSec(4291):==== setParametersprocessingmethod =(null)
10-28 18:59:40.673:ERROR / SecCamera(4291):setRecordingSize(width(800)、height(480))
10-28 18:59:40.692:ERROR / SecCamera(4291):SetRotate(angle(0))
10-28 18:59:40.692:ERROR / CameraHardwareSec(4291):==== setParametersprocessingmethod =(null)
10-28 18:59:40.692:ERROR / SecCamera(4291):setRecordingSize(width(800)、height(480))
10-28 18:59:40.712:ERROR / SecCamera(4291):SetRotate(angle(0))
10-28 18:59:40.712:ERROR / CameraHardwareSec(4291):==== setParametersprocessingmethod =(null)
10-28 18:59:40.712:ERROR / SecCamera(4291):setRecordingSize(width(800)、height(480))
10-28 18:59:40.751:ERROR / CameraHardwareSec(4291):stopPreview()
10-28 18:59:40.751:ERROR / SecCamera(4291):cancelAutofocus()
10-28 18:59:40.751:ERROR / SecCamera(4291):cancelAutofocus()end、0、4
10-28 18:59:40.768:ERROR / SecCamera(4291):stopPreview()
10-28 18:59:40.768:ERROR / SecCamera(4291):fimc_v4l2_streamoff()
10-28 18:59:40.797:ERROR / CameraHardwareSec(4291):stopPreview()終了
10-28 18:59:41.622:ERROR / SecCamera(4291):fimc_v4l2_streamoff()
10-28 18:59:46.536:エラー/ dalvikvm(2993):スタックトレースを/data/anr/traces.txtに書き込めませんでした(2970年の2775):不明なエラー:0
10-28 18:59:46.540:エラー/ dalvikvm(2919):スタックトレースを/data/anr/traces.txtに書き込めませんでした(-3414の-1):数学の結果を表現できません
10-28 18:59:46.610:エラー/ dalvikvm(3044):スタックトレースを/data/anr/traces.txtに書き込めませんでした(7154の3354):数学の結果を表現できません
..。

これが私の(短縮された)コードです:

パブリッククラスCameraActivityはActivityを拡張し、MenuViewCallback、CutoutPathManagerCallbackを実装します{
    public static final String TAG = "CutoutCamera";
    プレビュープレビュー;
    OverlayViewオーバーレイ;
    static MenuView menuView;

    @オーバーライド
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        //ウィンドウのタイトルを非表示にします。
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow()。addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        ..。

        プレビュー=(プレビュー)this.findViewById(R.id.preview);
        ..。
    }

    ..。

    @オーバーライド
    保護されたvoidonResume(){
        super.onResume();
        this.log( "onResume()");
        Preview.openCamera();
    }


    @オーバーライド
    保護されたvoidonPause(){
        super.onPause();
        this.log( "onPause()");
        if(preview.camera!= null){
            Preview.camera.release();
            Preview.camera = null;
        }
    }

    //シャッターが開いたときに呼び出されます
    ShutterCallback shutdownCallback = new ShutterCallback(){//
        public void onShutter(){
            Log.d(TAG、 "onShutter'd");
        }
    };

    //生画像のデータを処理します
    PictureCallback rawCallback = new PictureCallback(){//
        public void onPictureTaken(byte [] data、Camera camera){
            Log.d(TAG、 "onPictureTaken --raw");
        }
    };

    //jpeg画像のデータを処理します
    PictureCallback jpegCallback = new PictureCallback(){//
        public void onPictureTaken(byte [] data、Camera camera){
            Log.d(TAG、 "onPictureTaken --jpeg");
            ..。
        }
    };

    @オーバーライド
    public void shootButtonClicked(){
        Preview.camera.takePicture(shutterCallback、rawCallback、jpegCallback);
    }

    @オーバーライド
    public void focusButtonClicked(){
        Preview.camera.autoFocus(new Camera.AutoFocusCallback(){   
            public void onAutoFocus(boolean success、Camera camera){

            }
        });
    }
}
/ **
 *実行順序:
 * オープンカメラ()
 * onMeasure()
 * onLayout()
 * onMeasure()
 * onLayout()
 * surfaceCreated()
 * surfaceChanged()
 * onMeasure()
 * onLayout()
 * onMeasure()
 * @author stephan
 *
 * /
クラスプレビューはViewGroupを拡張しSurfaceHolder.Callbackを実装します{//
    private static final String TAG = "Preview";

    SurfaceHolder mHolder; //
    公共カメラカメラ; //
    プライベートリストsupportedPreviewSizes;
    プライベートサイズpreviewSize;
    SurfaceView mSurfaceView;
    CameraActivity cameraActivity;
    int l2 = 0、t2 = 0、r2 = 0、b2 = 0;
    intパディング=20;
    サイズoptimalPreviewSize、optimalPictureSize;
    //このビューのサイズ。onMeasure()で設定されます
    int fullWidth、fullHeight;



    public Preview(コンテキストコンテキスト){
        スーパー(コンテキスト);
        init(context);
    }

    public Preview(Context context、AttributeSet attrs){
        super(context、attrs);
        init(context);
    }

    public Preview(Context context、AttributeSet attrs、int defStyle){
        super(context、attrs、defStyle);
        init(context);
    }

    private void init(Context context){
        setKeepScreenOn(true);
        cameraActivity =(CameraActivity)コンテキスト;
        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);

        mHolder = mSurfaceView.getHolder(); //
        mHolder.addCallback(this); //
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //
    }
    ..。

    public void openCamera(){
        cameraActivity.log( "openCamera()");
        if(this.camera == null){
            cameraActivity.log( "Camera.open()");
            this.camera = Camera.open();

            //supportedPreviewSizes = camera.getParameters()。getSupportedPreviewSizes();
            requestLayout(); //-> onMeassure()-> onLayout()
        }
    }


    @オーバーライド
    保護されたvoidonMeasure(int widthMeasureSpec、int heightMeasureSpec){
        cameraActivity.log( "onMeasure()");

        //子の測定値は、
        //代わりにカメラプレビューを中央に配置するSurfaceViewへのラッパー
        //それを伸ばす。
        fullWidth = resolveSize(getSuggestedMinimumWidth()、widthMeasureSpec);
        fullHeight = resolveSize(getSuggestedMinimumHeight()、heightMeasureSpec);
        setMeasuredDimension(fullWidth、fullHeight);

        if(this.camera!= null){
            cameraActivity.log( "fullSize:" + fullWidth + "x" + fullHeight);
            this.setCameraPreviewSize();
            this.setCameraPictureSize();
        }
    }

    private void calcScaledPreviewSize(){
        ..。
    }

    ..。

    private void setCameraPreviewSize(){
        Camera.Parametersパラメーター=camera.getParameters();
        if(parameters.getPreviewSize()!= this.getOptimalPreviewSize()){
            parameters.setPreviewSize(this.getOptimalPreviewSize()。width、this.getOptimalPreviewSize()。height);
            this.camera.setParameters(parameters);
        }
    }

    private void setCameraPictureSize(){
        Camera.Parametersパラメータ=this.camera.getParameters();
        if(parameters.getPictureSize()!= this.getOptimalCameraPictureSize()){
            parameters.setPictureSize(getOptimalCameraPictureSize()。width、getOptimalCameraPictureSize()。height);
            this.camera.setParameters(parameters);
        }
    }

    @オーバーライド
    protected void onLayout(boolean changed、int l、int t、int r、int b){
        cameraActivity.log( "onLayout()");
        if(changed && getChildCount()> 0 && this.camera!= null){
            最終ビューの子=getChildAt(0);
            cameraActivity.log( "r:" + this.getPreviewRight()+ "l:" + this.getPreviewLeft()+ "b:" + this.getPreviewBottom()+ "t:" + this.getPreviewTop());
            child.layout(this.getPreviewLeft()、this.getPreviewTop()、this.getPreviewRight()、this.getPreviewBottom());
            cameraActivity.initOverlay(this.getPreviewLeft()、this.getPreviewTop()、this.getPreviewRight()、this.getPreviewBottom());
        }
    }
    プライベートサイズgetOptimalPreviewSize(){

        if(optimalPreviewSize == null){
            //最適なプレビューサイズを計算します
        }
        optimalPreviewSizeを返します。
    }

    プライベートサイズgetOptimalCameraPictureSize(){

        if(optimalPictureSize == null){
            //最適な画像サイズを計算します
        }
        optimalPictureSizeを返します。
    }


    //所有者の準備ができたら呼び出されます
    public void surfaceCreated(SurfaceHolderホルダー){//
        //サーフェスが作成されました。カメラを取得し、場所を伝えます
        // 描く。
        cameraActivity.log( "surfaceCreated()");
        試す {
            if(this.camera!= null){
                this.camera.setPreviewDisplay(holder);
            }
        } catch(IOException例外){
            Log.e(TAG、 "setPreviewDisplay()によって引き起こされたIOException"、例外);

        }
    }

    public void surfaceChanged(SurfaceHolderホルダー、int形式、int w、int h){
        cameraActivity.log( "surfaceChanged()");
        if(camera!= null){

            Camera.Parametersパラメーター=camera.getParameters();
            parameters.setPreviewSize(getOptimalPreviewSize()。width、getOptimalPreviewSize()。height);
            requestLayout();

            camera.setParameters(parameters);
            camera.startPreview();
        }
    }

    public void surfaceDestroyed(SurfaceHolderホルダー){//
        cameraActivity.log( "surfaceDestroyed()");
        if(this.camera!= null){
            camera.stopPreview();
        }
    }

    public void releaseCamera(){
        cameraActivity.log( "releaseCamera()");
        if(camera!= null){
            camera.stopPreview();
            camera.setPreviewCallback(null);
            camera.release();
            カメラ=null;
        }
    }
}

4

3 に答える 3

6

これが私がそれを100%修正した方法です(Galaxy Sを含む私が試したすべてのデバイスで動作します):

キャメアプレビューオブジェクトをResumeで破棄し、(起動時のように)すべて一緒に再インスタンス化しました。詳細はこちら:

android:スタックトレースが表示されない、電話がハングするだけ

于 2012-01-10T14:56:51.680 に答える
4

この投稿に到達するのは少し遅いですが、私は同様の問題を抱えていました。まず、カスタマーROMを使用している場合は、カメラドライバーの問題である可能性があります(1つのX8が4.0.4を実行している場合)。この問題は、電源ボタンを押して電話機をスタンバイモードにし、短時間(ホーム画面ロックの有無にかかわらず)に戻す場合にも発生します。試行錯誤の末、カメラをシャットダウンしてからsuper.onPauseが最適になるまで少し遅れることがわかりました。以下の私のコード。

  @Override
  public void onPause() {
      // Log.d(TAG,"ccp_onPause");
      closeCamera();
      try {
          Thread.sleep(500);
      } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
      }
      super.onPause();
  }

およびcloseCamera();

   public void closeCamera() {
      if (mCamera != null) {
          mCamera.stopPreview();
          mCamera.setPreviewCallback(null);
          mCamera.lock();
          mCamera.release();
          mCamera=null;
          requestLayout();
        }
    }
于 2012-07-21T04:23:29.423 に答える
2

私の推測では、カメラをリセットするためにプレビューでセッターメソッドを作成するだけです(カメラが解放されたため、プレビューのローカルカメラオブジェクトはonPause()後に無効になりますが、プレビューの残りの状態は維持されます) 。

于 2012-05-26T21:43:47.523 に答える