2011-10-28 20 views
8

Tengo algunos problemas con el ciclo en vivo de la cámara onPause() onResume(): La cámara con vista previa, y tomar fotos funciona totalmente bien. Con una excepción:android: cámara onPause/onResume problema

Comienzo la aplicación, hago clic en el botón de inicio, vuelvo a la aplicación y hago otra foto.

Resultado: shuttercallback se sigue ejecutando (ver código), pero la devolución de llamada jpeg ya no existe. Entonces mi Galaxy S vibra, y la pantalla se queda en negro, ya que startPreview() no se vuelve a activar después de jpegCallback. El rastro de la pila no me sirve. Lo extraño es que esto solo ocurre en mi Galaxy S, no en el emulador. Realmente no tengo idea de cómo avanzar:/ ¿Alguien tiene una idea de lo que podría ser útil?

 
10-28 18:59:40.649: ERROR/SecCamera(4291): SetRotate(angle(0)) 
10-28 18:59:40.649: ERROR/CameraHardwareSec(4291): ====setParameters processingmethod = (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): ====setParameters processingmethod = (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): ====setParameters processingmethod = (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): ====setParameters processingmethod = (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() end 
10-28 18:59:41.622: ERROR/SecCamera(4291): fimc_v4l2_streamoff() 
10-28 18:59:46.536: ERROR/dalvikvm(2993): Failed to write stack traces to /data/anr/traces.txt (2775 of 2970): Unknown error: 0 
10-28 18:59:46.540: ERROR/dalvikvm(2919): Failed to write stack traces to /data/anr/traces.txt (-1 of 3414): Math result not representable 
10-28 18:59:46.610: ERROR/dalvikvm(3044): Failed to write stack traces to /data/anr/traces.txt (3354 of 7154): Math result not representable 
... 

Aquí está mi (abreviado) Código:

 
public class CameraActivity extends Activity implements MenuViewCallback, CutoutPathManagerCallback { 
    public static final String TAG = "CutoutCamera"; 
    Preview preview; 
    OverlayView overlay; 
    static MenuView menuView; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Hide the window title. 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     ... 

     preview = (Preview) this.findViewById(R.id.preview); 
     ... 
    } 

    ... 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     this.log("onResume()"); 
     preview.openCamera(); 
    } 


    @Override 
    protected void onPause() { 
     super.onPause(); 
     this.log("onPause()"); 
     if (preview.camera != null) { 
      preview.camera.release(); 
      preview.camera = null; 
     } 
    } 

    // Called when shutter is opened 
    ShutterCallback shutterCallback = new ShutterCallback() { // 
     public void onShutter() { 
      Log.d(TAG, "onShutter'd"); 
     } 
    }; 

    // Handles data for raw picture 
    PictureCallback rawCallback = new PictureCallback() { // 
     public void onPictureTaken(byte[] data, Camera camera) { 
      Log.d(TAG, "onPictureTaken - raw"); 
     } 
    }; 

    // Handles data for jpeg picture 
    PictureCallback jpegCallback = new PictureCallback() { // 
     public void onPictureTaken(byte[] data, Camera camera) { 
      Log.d(TAG, "onPictureTaken - jpeg"); 
      ... 
     } 
    }; 

    @Override 
    public void shootButtonClicked() { 
     preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback); 
    } 

    @Override 
    public void focusButtonClicked() { 
     preview.camera.autoFocus(new Camera.AutoFocusCallback() { 
      public void onAutoFocus(boolean success, Camera camera) { 

      } 
     }); 
    } 
} 
 
/** 
* order of execution: 
* openCamera() 
* onMeasure() 
* onLayout() 
* onMeasure() 
* onLayout() 
* surfaceCreated() 
* surfaceChanged() 
* onMeasure() 
* onLayout() 
* onMeasure() 
* @author stephan 
* 
*/ 
class Preview extends ViewGroup implements SurfaceHolder.Callback { // 
    private static final String TAG = "Preview"; 

    SurfaceHolder mHolder; // 
    public Camera camera; // 
    private List supportedPreviewSizes; 
    private Size previewSize; 
    SurfaceView mSurfaceView; 
    CameraActivity cameraActivity; 
    int l2 = 0, t2 = 0, r2 = 0, b2 = 0; 
    int padding = 20; 
    Size optimalPreviewSize, optimalPictureSize; 
    // the size of this view. gets set in onMeasure() 
    int fullWidth, fullHeight; 



    public Preview(Context context) { 
     super(context); 
     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) context; 
     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() 
     } 
    } 


    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     cameraActivity.log("onMeasure()"); 

     // We purposely disregard child measurements because act as a 
     // wrapper to a SurfaceView that centers the camera preview instead 
     // of stretching it. 
     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 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 parameters = this.camera.getParameters(); 
     if(parameters.getPictureSize() != this.getOptimalCameraPictureSize()){ 
      parameters.setPictureSize(getOptimalCameraPictureSize().width, getOptimalCameraPictureSize().height); 
      this.camera.setParameters(parameters); 
     } 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     cameraActivity.log("onLayout()"); 
     if (changed && getChildCount() > 0 && this.camera != null) { 
      final View child = 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()); 
     } 
    } 
    private Size getOptimalPreviewSize() { 

     if(optimalPreviewSize == null){ 
      //calculate optimal preview size 
     } 
     return optimalPreviewSize; 
    } 

    private Size getOptimalCameraPictureSize() { 

     if(optimalPictureSize == null){ 
      //calculate optimal image size 
     } 
     return optimalPictureSize; 
    } 


    // Called once the holder is ready 
    public void surfaceCreated(SurfaceHolder holder) { // 
     // The Surface has been created, acquire the camera and tell it where 
     // to draw. 
     cameraActivity.log("surfaceCreated()"); 
     try { 
      if (this.camera != null) { 
       this.camera.setPreviewDisplay(holder); 
      } 
     } catch (IOException exception) { 
      Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 

     } 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     cameraActivity.log("surfaceChanged()"); 
     if (camera != null) { 

      Camera.Parameters parameters = camera.getParameters(); 
      parameters.setPreviewSize(getOptimalPreviewSize().width, getOptimalPreviewSize().height); 
      requestLayout(); 

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

    public void surfaceDestroyed(SurfaceHolder holder) { // 
     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(); 
      camera = null; 
     } 
    } 
} 

Respuesta

4

Esto es cómo lo arreglé 100% y, finalmente (trabajando en todos los dispositivos que lo probé en adelante, incluyendo Galaxy S):

Destruí el objeto de vista previa camere en Resume y reinstalé todos juntos (como en el inicio). Más detalles aquí:

android: I get no stacktrace, phone just hangs

2

Mi conjetura es que todo lo que tiene que hacer, es crear un método de selección en la vista previa para restablecer la cámara (el objeto local de la cámara en la vista previa de ser válida después onPause(), ya que la cámara está liberado, pero el resto del estado de Vista previa aún se mantiene).

3

Es un poco tarde para llegar a esta publicación, pero tuve el problema similar. En primer lugar, si usa rom del cliente, podría ser el problema del controlador de la cámara (el mío es un X8 runniing 4.0.4). El problema también existe si presiona el botón de encendido para poner el teléfono en modo de espera y traerlo de vuelta en poco tiempo (con o sin bloqueo de pantalla de inicio). Después de probar y error encontré que poner un pequeño retraso después de apagar la cámara antes de super.onPause es el mejor. Mi código como a continuación.

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

y closeCamera();

public void closeCamera() { 
     if (mCamera != null) { 
      mCamera.stopPreview(); 
      mCamera.setPreviewCallback(null); 
      mCamera.lock(); 
      mCamera.release(); 
      mCamera=null; 
      requestLayout(); 
     } 
    } 
+0

¿Por qué agregar un retraso en onPause soluciona este problema? Me pregunto :) –

Cuestiones relacionadas