2011-10-28 19 views
8

Ho alcuni problemi con il ciclo live onPause() onResume() camera: Fotocamera con anteprima, e scattare foto funziona perfettamente. Con una eccezione:android: camera onPause/onRisume problema

Avvio l'app, fare clic sul pulsante Home, tornare all'app e riprendere un'altra volta.

Risultato: shuttercallback è ancora eseguito (vedere codice), ma jpeg callback non è più disponibile! Quindi la mia galassia S vibra e lo schermo rimane nero, poiché startPreview() non viene riattivato dopo jpegCallback. La traccia dello stack è tutt'altro che utile per me. Stranamente, questo accade solo sul mio Galaxy S, non sull'emulatore. Non ho davvero idea di come andare avanti:/ Qualcuno ha un'idea di cosa potrebbe essere utile?

 
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 
... 

Ecco il mio codice (abbreviato):

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

risposta

4

Ecco come ho riparato 100%, infine (lavorando su ogni dispositivo ho provato su, compreso Galaxy S):

Ho distrutto l'oggetto di anteprima delle camere onResume e reintegrato tutti insieme (come all'avvio). Maggiori dettagli qui:

android: I get no stacktrace, phone just hangs

2

La mia ipotesi è che tutto quello che dovete fare, è quello di creare un metodo setter in anteprima per il ripristino della fotocamera (l'oggetto telecamera locale in Anteprima non è più valido dopo onPause() in quanto fotocamera è rilasciato, ma il resto dello stato di Anteprima è ancora mantenuto).

3

È un po 'tardi per raggiungere questo post ma ho avuto il problema simile. Prima di tutto, se si utilizza la rom del cliente, potrebbe essere il problema del driver della fotocamera (il mio uno X8 runniing 4.0.4). Il problema esiste anche se si preme il pulsante di accensione per mettere il telefono in modalità standby e riportarlo indietro in breve tempo (con o senza blocco dello schermo di casa). Dopo il tentativo e l'errore, ho scoperto che mettere un breve ritardo dopo aver spento la fotocamera prima che super.onPause sia il migliore. Il mio codice come di seguito.

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

e closeCamera();

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

Perché ha aggiunto un ritardo in onPause risolvere questo problema Mi chiedo :) –