DollaBill
DollaBill

Reputation: 239

How do I use Camera and MediaRecorder in same Activity?

I'm a noob to android development and I am trying to make a custom camera that takes photos and also records video. I have been able successfully capture images but when I try to switch the camera to media recorder I get an NullPointerException that says "java.lang.RuntimeException: Fail to connect to camera service ". Before I try to switch to media I release the camera and I have the correct permissions in my manifest, so I can't figure out why it is crashing. Any help is greatly appreciated.

MY CODE:

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

Upvotes: 2

Views: 704

Answers (2)

TheJudge
TheJudge

Reputation: 606

I might be a "bit" late but I have just been struggling with similar problem. I actually had same crash when I tried to switch from MediaRecorder back to photo mode. I just played around with camera methods stopPreview() , release() and lock()\unlock() and some say it helps to set your camera/recorder instances to null in right place though I have no idea why or if it really works ... Anyway - camera lifecycle is not a straightforward process, especially if you want to use it for both video and photo simultaneously - make sure you got these method where they should be.

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

Upvotes: 1

TheChef
TheChef

Reputation: 17

Have you tried to release the camera from the surface view in your onDestroy method?

Upvotes: 1

Related Questions