Как использовать Camera и MediaRecorder в одном действии?

Я новичок в разработке Android, и я пытаюсь сделать собственную камеру, которая делает фотографии, а также записывает видео. Мне удалось успешно захватить изображения, но когда я пытаюсь переключить камеру на медиа-рекордер, я получаю исключение NullPointerException, в котором говорится: «java.lang.RuntimeException: не удалось подключиться к службе камеры». Прежде чем я попытаюсь переключиться на медиа, я отпускаю камеру, и у меня есть правильные разрешения в моем манифесте, поэтому я не могу понять, почему она падает. Любая помощь приветствуется.

МОЙ КОД:

//Starting Camera
@Override
public void onResume(){
    super.onResume();
    if(is_photo_mode){ //8/4/2014
        setSurface();
    }
}

private void setSurface() {
    SurfaceView previewSurfaceView = (SurfaceView)findViewById(R.id.preview_surface);
    previewSurfaceView.getHolder().addCallback(shCallback);
}

private SurfaceHolder.Callback shCallback = new SurfaceHolder.Callback() {

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.i(LOG_TAG, "surfaceDestroyed callback");
        if (camera != null) {
            camera.stopPreview();
            camera.release();
        }
        camera = null;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.i(LOG_TAG, "surfaceCreated callback"); 
        startCamera(1-cameraId);            
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        Log.i(LOG_TAG, "surfaceChanged callback " + width + "x" + height);
        if(is_photo_mode){   //8/4/2014
            restartPreview();
        }
    }
  };

  protected void startCamera(final int id) {

    releaseCamera();

    new AsyncTask<Integer, Void, Camera>() {

        @Override
        protected Camera doInBackground(Integer... ids) {
            return openCamera(ids[0]);
        }

        @Override
        protected void onPostExecute(Camera c) {
            if(is_photo_mode){
                startPreview(id, c);
            }else{
                prepareMediaRecorder();
            }
        }

    }.execute(id);
}

private static Camera openCamera(int id) {
    Log.d(LOG_TAG, "opening camera " + id);
    Camera camera = null;
    try {
        camera = Camera.open(id);
        Log.d(LOG_TAG, "opened camera " + id);
    } catch (Exception e) {
        e.printStackTrace();
        camera.release();
        camera = null;
    }
    return camera;
}

private void startPreview(int id, Camera c) {
    if (c != null) {
        try {
            SurfaceView previewSurfaceView = (SurfaceView)findViewById(R.id.preview_surface);
            SurfaceHolder holder = previewSurfaceView.getHolder();
            c.setPreviewDisplay(holder);
            camera = c; 
            cameraId = id;
            restartPreview();
        } catch (IOException e) {
            e.printStackTrace();
            c.release();
        }
    }
}


private void restartPreview() {
    if (camera == null) {
        return;
    }
    int degrees = 0;
    switch (getWindowManager().getDefaultDisplay().getRotation()) {
    case Surface.ROTATION_0: 
        degrees = 0;
        break;
    case Surface.ROTATION_90: 
        degrees = 90;
        break;
    case Surface.ROTATION_180:
        degrees = 180;
        break;
    case Surface.ROTATION_270:
        degrees = 270;
        break;
    }
    Camera.CameraInfo ci = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, ci);
    if (ci.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        degrees += ci.orientation;
        degrees %= 360;
        degrees = 360 - degrees;
        front_facing_camera = true;

    }else {
        degrees = 360 - degrees;
        degrees += ci.orientation;
        front_facing_camera = false;

    }
    camera.setDisplayOrientation(degrees%360);
    camera.startPreview();

    Camera.Parameters params = camera.getParameters();
    if(params.isZoomSupported()){
        Log.e("ZOOM", "Enabled");
    }else{
        Log.e("ZOOM", "Disabled");
        zoom_in.setVisibility(View.GONE);
        zoom_out.setVisibility(View.GONE);
    }

}

//SWITCHING FROM CAMERA TO VIDEO
else if (v.getId() == R.id.mode_button) {
        if(is_photo_mode){
            is_photo_mode = false;
            mode_select.setText("VID");
            Log.e("MODE", "video");
        }else{
            is_photo_mode = true;
            mode_select.setText("CAM");
            Log.e("MODE", "photo");
        }
        switchMode();
    }

 public void switchMode() {
    startCamera( cameraId);
}

private boolean prepareMediaRecorder(){
    camera = getCameraInstance();

     Parameters parameters = camera.getParameters(); //<--NullPointerException here
     //parameters.setFlashMode(getFlashModeSetting());
     camera.setParameters(parameters);

     mediaRecorder = new MediaRecorder();

     camera.unlock();
     mediaRecorder.setCamera(camera);

     mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
     mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

     mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

     mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
     mediaRecorder.setMaxDuration(20000); // Set max duration 60 sec.
     mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M

     mediaRecorder.setPreviewDisplay(camera_lens.getHolder().getSurface());

     try {
         mediaRecorder.prepare();
     } catch (IllegalStateException e) {
         releaseMediaRecorder();
         return false;
     } catch (IOException e) {
         releaseMediaRecorder();
         return false;
     }
     return true;

 }

private Camera getCameraInstance(){
      // TODO Auto-generated method stub
           Camera c = null;
           try {
               c = Camera.open(); // attempt to get a Camera instance <--This fails
           }
           catch (Exception e){
               // Camera is not available (in use or does not exist)
               e.printStackTrace();
               Log.e("CAMERA FAIL", e.toString()); //<-- java.lang.RuntimeException: Fail to connect to camera service

           }
           return c; // returns null if camera is unavailable
     }

person DollaBill    schedule 04.08.2014    source источник


Ответы (2)


Вы пытались освободить камеру от вида поверхности в методе onDestroy?

person TheChef    schedule 04.08.2014
comment
Благодарю за ваш ответ. Я выпускаю камеру в OnDestroy, но она все еще падает. - person DollaBill; 04.08.2014

Я мог бы быть "немного" поздно, но я только что боролся с подобной проблемой. На самом деле у меня был такой же сбой, когда я пытался переключиться с MediaRecorder обратно в фоторежим. Я только что поэкспериментировал с методами камеры stopPreview() , release() и lock()\unlock(), и некоторые говорят, что это помогает установить нулевые экземпляры вашей камеры/рекордера в нужном месте, хотя я понятия не имею, почему и работает ли это на самом деле... В любом случае - жизненный цикл камеры не простой процесс, особенно если вы хотите использовать его как для видео, так и для фото одновременно — убедитесь, что вы получили эти методы там, где они должны быть.

MediaRecorder API has nice chart of its state machine - might help https://developer.android.com/reference/android/media/MediaRecorder.html

person TheJudge    schedule 21.03.2017