I have the some of the following code to use the camera:
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (mCamera == null) {
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void resetCamera() {
if (!videoReset) {
if (videoStarted && !videoStopped) {
mMediaRecorder.stop();
}
MediaScannerConnection.scanFile(TherapistActivity.this, new String[]{videoFile.getAbsolutePath()}, null, null);
mMediaRecorder.reset();
mMediaRecorder.release();
mCamera.release();
mCamera = null;
mMediaRecorder = null;
videoReset = true;
initSuccess = false;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
surfaceWidth = width;
surfaceHeight = height;
try {
if (!initSuccess)
startPreview(mHolder.getSurface());
} catch (IOException e) {
e.printStackTrace();
}
}
private void initRecorder(Surface surface) throws IOException {
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size previewSize = getOptimalPreviewSize(surfaceWidth, surfaceHeight);
if (previewSize != null) {
parameters.setPreviewSize(previewSize.width, previewSize.height);
}
parameters.setVideoStabilization(false);
mCamera.setParameters(parameters);
mCamera.startPreview();
mCamera.unlock();
if (mMediaRecorder == null) mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setVideoEncodingBitRate(3072 * 1000);
mMediaRecorder.setVideoFrameRate(60);
mMediaRecorder.setVideoSize(1280, 720);
mMediaRecorder.setOutputFile(videoFile.getAbsolutePath());
if (!mApp.videoTime) {
mMediaRecorder.setMaxDuration(30000);
} else {
mMediaRecorder.setMaxDuration(Integer.MAX_VALUE);
}
mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
mCameraWrapper.setBackgroundColor(Color.TRANSPARENT);
try {
mCamera.stopPreview();
videoRecorded = true;
} catch (RuntimeException re) {
Log.e("Error", "Could not stop camera!");
} finally {
videoPreviewStarted = false;
}
btRecord.setTag("stop");
btRecord.setBackgroundResource(R.drawable.stop_nobkgrnd_gray);
tvVideoCountdown.setVisibility(View.GONE);
initSuccess = false;
}
}
});
try {
mMediaRecorder.prepare();
videoPreviewStarted = true;
} catch (IllegalStateException e) {
e.printStackTrace();
}
initSuccess = true;
}
}
private Camera.Size getOptimalPreviewSize(int w, int h) {
Camera.Size result = null;
Camera.Parameters p = mCamera.getParameters();
for (Camera.Size size : p.getSupportedPreviewSizes()) {
if (size.width <= w && size.height <= h) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) {
result = size;
}
}
}
}
return result;
}
On the Astro Tab A10 running Marshmallow, apparently the Camera isn't being released properly when being run the second time, since the camera fails to open until the device is rebooted. I am pretty sure this isn't a permissions problem, since I granted the app permissions to the camera at runtime as well as including camera permissions in the manifest.
Does anyone know what might be the problem?
EDIT: Here is the stack trace:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mobilityresearch.treadmill3, PID: 4144
java.lang.RuntimeException: Fail to connect to camera service
at android.hardware.Camera.<init>(Camera.java:495)
at android.hardware.Camera.open(Camera.java:341)
at com.mobilityresearch.treadmill3.TherapistActivity.surfaceCreated(TherapistActivity.java:8260)
at android.view.SurfaceView.updateWindow(SurfaceView.java:583)
at android.view.SurfaceView.setVisibility(SurfaceView.java:257)
at com.mobilityresearch.treadmill3.TherapistActivity$26.onClick(TherapistActivity.java:1701)
at android.view.View.performClick(View.java:5204)
at android.view.View$PerformClick.run(View.java:21153)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:742)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:632)
This doesn't happen on any of our other tablets. In fact, it doesn't happen on the older version of the Astro Tab A10 running Android 5.1 Lollipop. I tried calling resetCamera
the camera both in surfaceCreated
before opening the preview, and surfacedDestroyed
after closing the preview, and it doesn't work.
EDIT 2: I just found out that if I actually record video, it works fine, but if I don't record video and only display the preview, it doesn't work.
EDIT 3: Added surfaceChanged and initRecorder. Updated resetCamera.