2012-01-15 10 views
56

Durante el desarrollo de una aplicación de cámara que he encontrado una excepción que sólo sucedió cuando me cambio a otra aplicación (onPause() para mi aplicación).método llamado después de la liberación excepción() no puede reanudar con la cámara androide

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) 

me hizo una investigación y descubrió que tengo que añadir

mCamera.setPreviewCallback(null); 

como una solución para la pila de la cámara de Android

mi onPause() ahora se ve así:

@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(); 
    } 
} 

y mi 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()); 
    } 
} 
} 

y finalmente mi getCameraInstance() método:

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 
} 

alguna idea sobre cómo solucionar este problema?

Respuesta

137

Tengo el mismo problema. mCamera.setPreviewCallback(null); no ayudó. En mi actividad he añadido esto a releaseCamera:

mPreview.getHolder().removeCallback(mPreview); 

y funciona ahora.

+23

Esto funcionó para mí. Lo puse en 'onPause' entre' mCamera.setPreviewCallback (null) 'y' mCamera.release() '. – srunni

+0

Funcionó para mí también. Gracias. –

+2

Trabajos. Sería una buena adición a los documentos oficiales. –

10

Los documentos dicen claramente que camera.release() libera todos los recursos de la cámara. Después de esta llamada, la referencia de la cámara ya no se puede usar.

Si desea utilizar la cámara de nuevo que tienen que adquirirla a través de un método open(int).

Es todo descrito en el camera docs.

+0

Todavía no funciona, he agregado la parte abierta(), pero todavía FC – tom91136

+0

¿puede verificar el código otra vez? He agregado su consejo y ha arreglado el resto de acuerdo con la guía del desarrollador de Android, pero todavía no hay resultados. – tom91136

+0

¿Sigue el mismo error? Claramente dice 'Método llamado después del lanzamiento()' y la siguiente línea 'en android.hardware.Camera.setPreviewDisplay (..)'. Entonces debe llamar 'setPreviewDisplay()' después de 'release()' –

2
@Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 

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

} 

Y reinicialice la cámara en la función Reanudar.

20

@ ookami.kb la solución funcionó para mí también, así como @srunni comentó.

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

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

Eliminé también el método Destroy.

+0

¿Por qué eliminarías también de OnDestroy? ¡No tiene ningún sentido! – slott

5

para reanudar correctamente, es necesario hacer esto:

@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); 
       } 
      } 
     ); 
} 

Y también sólo para recordar que en alcrear() no hacen más que la definición de vista previa FrameLayout y Button captureButton.

1

Agregando a la respuesta de okambi.

Ésta es la función de jugar todo lo que hasta cuando se reanude:

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()); 
     } 
    } 

El try {} no se captura la excepción de ser lanzado. A saber, que mCamera no existe, y luego, cuando intenta llamar a setPreviewDisplay (holder), se produce un bloqueo.

Al eliminar la devolución de llamada, esta superficie creada no recibe una llamada y evita el bloqueo.

DOCUMENTACIÓN MUY POBRE DE Google.

0

Enfrenté el mismo problema, lo arreglé por - Añadiendo mCamera = null; en surfaceDestroyed (SurfaceHolder holder) método de Vista previa clase.

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; 
    } 
} 

y - Adición de

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

en onResume() método de mi CameraActivity.

0

Si tienes:

intento de invocar método virtual 'vacío android.hardware.Camera.setPreviewCallback (android.hardware.Camera $ PreviewCallback)' en una referencia de objeto nulo

Estoy de acuerdo con @ ookami.kb - mCamera.setPreviewCallback(null); no es suficiente, detrás de él también añadir lo siguiente:

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

He puesto

mPreview.getHolder().removeCallback(mPreview); 

entre.

mCamera.setPreviewCallback(null); 

y

mCamera.release(); 

y funcionó para mí.

@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){ 

       } 
      } 
Cuestiones relacionadas