Reputation: 239
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
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.
Upvotes: 1
Reputation: 17
Have you tried to release the camera from the surface view in your onDestroy method?
Upvotes: 1