web-dev-qa-db-ja.com

Androidカメラで再開できないrelease()例外の後に呼び出されたメソッド

カメラアプリの開発中に、他のアプリに切り替えたときにのみ発生する例外が発生しました(アプリのonPause())。

_01-15 17:22:15.017: E/AndroidRuntime(14336): FATAL EXCEPTION: main
01-15 17:22:15.017: E/AndroidRuntime(14336): Java.lang.RuntimeException: Method called after release()
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.hardware.Camera.setPreviewDisplay(Native Method)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.hardware.Camera.setPreviewDisplay(Camera.Java:357)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at com.sora.cbir.yuki.image.leaf.CameraPreview.surfaceCreated(CameraPreview.Java:32)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.SurfaceView.updateWindow(SurfaceView.Java:551)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.Java:213)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.View.dispatchWindowVisibilityChanged(View.Java:4075)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.ViewRoot.performTraversals(ViewRoot.Java:858)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.view.ViewRoot.handleMessage(ViewRoot.Java:1995)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.os.Looper.loop(Looper.Java:150)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Android.app.ActivityThread.main(ActivityThread.Java:4389)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Java.lang.reflect.Method.invokeNative(Native Method)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at Java.lang.reflect.Method.invoke(Method.Java:507)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:849)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:607)
01-15 17:22:15.017: E/AndroidRuntime(14336):    at dalvik.system.NativeStart.main(Native Method)
_

私はいくつかの研究を行い、追加する必要があることがわかりました

_mCamera.setPreviewCallback(null);
_

androidのカメラスタックの回避策として

onPause()は次のようになります。

_@Override
protected void onPause() {
    super.onPause();
    try
    {    
        // release the camera immediately on pause event   
        //releaseCamera();
         mCamera.stopPreview(); 
         mCamera.setPreviewCallback(null);
         mCamera.release();
         mCamera = null;

    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}
_

そして私のonResume()

_@Override
protected void onResume()
{
    super.onResume();
    try
    {
        mCamera.setPreviewCallback(null);
        mCamera = getCameraInstance();
        //mCamera.setPreviewCallback(null);
        mPreview = new CameraPreview(Imageupload.this, mCamera);//set preview
        preview.addView(mPreview);
    } catch (Exception e){
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}   
}
_

そして最後に私のgetCameraInstance()メソッド:

_public Camera getCameraInstance(){
    Camera camera = null;
    try {
        camera = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    Camera.Parameters parameters = camera.getParameters();
    //mPreviewSize = getBestPreviewSize(parameters, wt, ht);
    //mPictureSize = getBestPictureSize(parameters, wt, ht);
    //Shift W & H => if camera rotates 90 deg

    mPreviewSize = getOptimalPreviewSize(parameters, wt, ht); //original => wt,ht
    mPictureSize = getOptimalPictureSize(parameters, wt, ht); //original => wt,ht

    Log.d("CAMERA", "SCREEN RESOLUTION H: "+ht);
    Log.d("CAMERA", "SCREEN RESOLUTION W: "+wt);

    Log.d("CAMERA", "PREVIEW RESOLUTION H: "+mPreviewSize.height);
    Log.d("CAMERA", "PREVIEW RESOLUTION W: "+mPreviewSize.width);

    Log.d("CAMERA", "PICTURE RESOLUTION H: "+mPictureSize.height);
    Log.d("CAMERA", "PICTURE RESOLUTION W: "+mPictureSize.width);
    //set preview size based on device screen
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    //set picture size based on device screen
    parameters.setPictureSize(mPictureSize.width, mPictureSize.height);
    //set output camera mode
    parameters.setPictureFormat(PixelFormat.JPEG);
    //set focous mode
    parameters.setFocusMode(FOCUS_MODE_AUTO);
    //set flash mode
    parameters.setFlashMode("auto");
    List<int[]> fps = parameters.getSupportedPreviewFpsRange();
    //System.out.println("FPS size: " +fps.size());
    //System.out.println("MAX FPS:"+(fps.get(fps.size()-1)[1])/1000);
    //log min and max camera supported fps
    Log.d("CAMERA", "CAMERA MAX FPS: "+(fps.get(fps.size()-1)[1])/1000);
    Log.d("CAMERA", "CAMERA MIN FPS: "+(fps.get(fps.size()-1)[0])/1000);
    if(camera_fps)
    {
        parameters.setPreviewFpsRange(fps.get(fps.size()-1)[1], fps.get(fps.size()-1)[1]);
    }
    //set camera parameters
    camera.setParameters(parameters);

    Toast.makeText(getApplicationContext(), "Your device are capable of previewing @" + fps.get(fps.size()-1)[1]/1000+"fps!",Toast.LENGTH_SHORT).show();
    return camera; // returns null if camera is unavailable
}
_

これを修正する方法についてのアイデアはありますか?

59
tom91136

私は同じ問題を抱えています。 mCamera.setPreviewCallback(null);は役に立ちませんでした。私の活動では、これをreleaseCameraに追加しました:

mPreview.getHolder().removeCallback(mPreview);

そして、それは今動作します。

144
ookami.kb

@ ookami.kbソリューションも私のために機能し、@ srunniもコメントしました。

public void onPause() {
    super.onPause();

    if (mCamera != null) {
        mCamera.setPreviewCallback(null);
        mPreview.getHolder().removeCallback(mPreview);
        mCamera.release();
    }
}

OnDestroyメソッドも削除しました。

20
Neonigma

ドキュメントでは、 camera.release() はすべてのカメラリソースを解放することを明確に述べています。この呼び出しの後、カメラ参照は使用できなくなります。

カメラを再度使用する場合は、open(int)メソッドを使用してカメラを取得する必要があります。

それはすべて camera docs で説明されています。

10
Peter Knego

正しく再開するには、これを行う必要があります。

@Override
public void onResume() {
    super.onResume();  

    // Get the Camera instance as the activity achieves full user focus
    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera initialization
    }
}



protected void initializeCamera(){
    // Get an instance of Camera Object
    mCamera = getCameraInstance();

   // create a basic camera preview class that can be included in a View layout.
    mPreview=new CameraPreview(this,mCamera);

    //add your preview class to the FrameLayout element.
    preview.addView(mPreview);

   //Trigger capturing an image by calling the Camera.takePicture() method.
    captureButton.setOnClickListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // get an image from the camera
                    mCamera.takePicture(null, null, mPicture);
                }
            }
        );
}

また、oncreate()でFrameLayoutプレビューとButton captureButtonを定義する以外に何もしないことを思い出してください。

5
Richa
@Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

    this.getHolder().removeCallback(this);
    mCamera.stopPreview();
    mCamera.release();
    mCamera = null;
  Log.e("surfaceDestroyed", "surfaceDestroyed");

}

そして、再開機能でカメラを再初期化します。

2
Bala

私は置きました

mPreview.getHolder().removeCallback(mPreview);  

の間に。

mCamera.setPreviewCallback(null);

そして

mCamera.release();

そしてそれは私のために働いた。

 @Override
            protected void onPause() {
                super.onPause();

                this.saveTextEdits();
                try {
                    mCamera.stopPreview();
                    mCamera.setPreviewCallback(null);
                    **mPreview.getHolder().removeCallback(mPreview);**
                    mCamera.release();
                    mCamera = null;
                }catch (Exception e){

                }
            }
1
radhason power

オカンビの答えに追加。

これは、再開時にすべてを台無しにする機能です。

 public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

Try {}は、スローされている例外をキャッチしていません。つまり、そのmCameraは存在せず、setPreviewDisplay(holder)を呼び出そうとするとクラッシュします。

したがって、コールバックを削除することにより、このsurfaceCreatedは呼び出されず、クラッシュを回避します。

これは、Googleによって非常に不十分に文書化されています。

1
Aggressor

あなたが得た場合:

Nullオブジェクト参照で仮想メソッド「void Android.hardware.Camera.setPreviewCallback(Android.hardware.Camera $ PreviewCallback)」を呼び出そうとしました

私は@ ookami.kbに同意します-mCamera.setPreviewCallback(null);は十分ではありません。その後ろにこれも追加します:

mCameraView.getHolder().removeCallback(mCameraView);
0

私は同じ問題に直面しました-mCamera = null; in surfaceDestroyed(SurfaceHolder holder)Previewクラスの追加.

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
}

および-追加

camera = Camera.open();
    camera.startPreview();
    params = camera.getParameters();
    preview.setCamera(camera);

in OnResume()私のCameraActivityのメソッド。

0
Rahul Sharma