android: camera onPause / onResume problem

Mam pewne problemy z onpause () onresume () camera live cycle: Aparat z podglądem i robienie zdjęć działa całkowicie dobrze. Z jednym wyjątkiem:

Uruchamiam aplikację, klikam przycisk home, przełączam się z powrotem do aplikacji i wykonuję kolejny strzał.

Wynik: shuttercallback jest nadal wykonywany (patrz kod), ale JPEG callback już nie jest! Następnie mój galaxy S wibruje, a ekran pozostaje czarny, ponieważ startPreview() nie jest ponownie uruchamiany po jpegCallback. Ślad stosu jest daleki od przydatne dla mnie. Dziwne jest to, że dzieje się to tylko na moim Galaxy S, a nie na emulatorze. Nie mam pojęcia, jak ruszyć dalej. :/ Ktoś ma pomysł, co może być przydatne?

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

Oto mój (skrócony) kod:

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

Author: stoefln, 2011-10-29

3 answers

Tak to naprawiłem na 100%, W końcu (pracując na każdym urządzeniu, na którym próbowałem, w tym na Galaxy S):

Zniszczyłem obiekt podglądu camere onResume i ponownie zainstalowałem wszystkie razem(jak przy starcie). Więcej szczegółów tutaj:

Android: nie dostaję stacktrace, telefon po prostu się zawiesza

 5
Author: stoefln,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:45:22

Jest trochę późno, aby dotrzeć do tego postu, ale miałem podobny problem. Przede wszystkim, jeśli używasz ROM klienta, może to być problem ze sterownikiem kamery (mój jeden X8 działa 4.0.4). Problem występuje również, jeśli naciśniesz przycisk zasilania, aby umieścić telefon w trybie gotowości i przywrócić go w krótkim czasie(z blokadą ekranu głównego lub bez). Po próbie i błędzie odkryłem, że po wyłączeniu kamery przed super nastąpiło krótkie opóźnienie.onpauza jest najlepsza. Mój kod jak poniżej.

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

Oraz closeCamera ();

   public void closeCamera() {
      if (mCamera != null) {
          mCamera.stopPreview();
          mCamera.setPreviewCallback(null);
          mCamera.lock();
          mCamera.release();
          mCamera=null;
          requestLayout();
        }
    }
 4
Author: babyromeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-21 04:23:29

Domyślam się, że wszystko, co musisz zrobić, to utworzyć metodę setter w Podglądzie do resetowania kamery (lokalny obiekt kamery w Podglądzie staje się nieważny po onpause (), ponieważ kamera jest zwolniona, ale reszta stanu podglądu jest nadal zachowana).

 2
Author: user1419516,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-26 21:43:47