2011-10-28 34 views
8

Tôi gặp một số trục trặc với chu kỳ sống onPause() onResume(): Máy ảnh xem trước và chụp ảnh hoạt động hoàn toàn tốt. Với một ngoại lệ:android: camera onPause/onResume issue

Tôi khởi động ứng dụng, nhấp vào nút trang chủ, quay lại ứng dụng và chụp một lần nữa.

Kết quả: shuttercallback vẫn được thực hiện (xem mã), nhưng gọi lại jpeg không còn nữa! Sau đó, thiên hà S của tôi rung và màn hình vẫn đen, vì startPreview() không được kích hoạt lại sau jpegCallback. Theo dõi ngăn xếp là xa hữu ích cho tôi. Điều lạ lùng là điều này chỉ xảy ra trên Galaxy S của tôi chứ không phải trên trình giả lập. Tôi thực sự không có đầu mối làm thế nào để di chuyển trên:/ Bất cứ ai cũng có một ý tưởng những gì có thể hữu ích?

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

Sau đây là tôi (rút ngắn) mã:

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

Trả lời

4

Đây là cách tôi cố định nó 100%, cuối cùng (làm việc trên mọi thiết bị Tôi đã thử nó trên, bao gồm Galaxy S):

Tôi đã hủy đối tượng xem trước camere trênResume và được khôi phục lại tất cả cùng nhau (như khi khởi động). Xem thêm chi tiết ở đây:

android: I get no stacktrace, phone just hangs

2

Tôi đoán được rằng tất cả các bạn phải làm là để tạo ra một phương pháp setter trong Preview để đặt máy ảnh (đối tượng máy ảnh địa phương trong Preview trở nên không hợp lệ sau onPause() kể từ camera được phát hành, nhưng phần còn lại của trạng thái Xem trước vẫn được duy trì).

3

Hơi muộn để tiếp cận bài đăng này nhưng tôi đã gặp sự cố tương tự. Trước hết, nếu bạn sử dụng rom khách hàng, nó có thể là vấn đề của trình điều khiển máy ảnh (của tôi một X8 runniing 4.0.4). Vấn đề cũng tồn tại nếu bạn nhấn nút nguồn để đặt điện thoại ở chế độ chờ và mang nó trở lại trong một thời gian ngắn (có hoặc không có khóa màn hình chính). Sau khi thử và lỗi tôi thấy rằng đặt một sự chậm trễ ngắn sau khi tắt máy ảnh trước khi super.onPause là tốt nhất. Mã của tôi như sau.

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

và closeCamera();

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

Tại sao thêm một sự chậm trễ trong onPause khắc phục sự cố này, tôi tự hỏi :) –

Các vấn đề liên quan