Android: камера на паузу / на возобновить проблему - PullRequest
12 голосов
/ 29 октября 2011

У меня есть некоторые проблемы с циклом включения камеры onPause () onResume (): камера с предварительным просмотром и фотосъемкой работает совершенно нормально.За одним исключением:

Я запускаю приложение, нажимаю кнопку «Домой», переключаюсь обратно в приложение и делаю еще один снимок.

Результат: обратный вызов shutter все еще выполняется (см. Код), но обратный вызов jpegбольше нет!Тогда моя галактика S вибрирует, и экран остается черным, так как startPreview () не запускается повторно после jpegCallback.Трассировка стека для меня далеко не полезна.Странно то, что это происходит только на моем Galaxy S, а не на эмуляторе.Я действительно понятия не имею, как двигаться дальше: / У кого-нибудь есть идея, что может быть полезным?

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

Вот мой (сокращенный) код:

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

Ответы [ 3 ]

6 голосов
/ 10 января 2012

Вот как я исправил это на 100%, наконец (работая на каждом устройстве, которое я пробовал, включая Galaxy S):

Я уничтожил объект предварительного просмотра camere onResume и заново создал все вместе (как при запуске). Подробнее здесь:

android: я не получаю трассировку стека, телефон просто зависает

4 голосов
/ 21 июля 2012

Уже немного поздно, чтобы добраться до этого поста, но у меня была похожая проблема.Прежде всего, если вы используете клиентскую систему, это может быть проблемой с драйвером камеры (у меня один X8 работает с 4.0.4).Проблема также существует, если вы нажмете кнопку питания, чтобы перевести телефон в режим ожидания и вернуть его за короткое время (с блокировкой домашнего экрана или без нее).После попытки и ошибки я обнаружил, что после выключения камеры перед запуском super.onPause лучше поставить небольшую задержку.Мой код, как показано ниже.

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

и closeCamera ();

   public void closeCamera() {
      if (mCamera != null) {
          mCamera.stopPreview();
          mCamera.setPreviewCallback(null);
          mCamera.lock();
          mCamera.release();
          mCamera=null;
          requestLayout();
        }
    }
2 голосов
/ 27 мая 2012

Я предполагаю, что все, что вам нужно сделать, это создать метод установки в Preview для сброса камеры (объект локальной камеры в Preview становится недействительным после onPause (), так как камера выпущена, но остальная часть состояния Preview -все еще поддерживается).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...