This error shows "java.lang.RuntimeException:
Camera is being used after Camera.release()
was called" when me switching camera. Is my way to release the camera is not the correct way? Can someone suggest me the best way to implement this?
This is my CameraActivity.java:
private Camera mCamera;
private CameraPreviewActivity mPreview;
private int cameraId = 0;
private static final int MY_PERMISSIONS_REQUEST_CAMERA = 1;
/**
* Check if this device has a camera
*/
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
/**
* A safe way to get an instance of the Camera object.
*/
// attempt to get a Camera instance
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
System.out.println("Camera not working.");
}
return c; // returns null if camera is unavailable
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camerapreview_activity);
// Create our Preview view and set it as the content of our activity.
// Create an instance of Camera
switchCamera();
showCamera();
}
public void switchCamera() {
ToggleButton facingSwitch = (ToggleButton) findViewById(R.id.facingSwitch);
facingSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
onDestroy();
preview.removeAllViews();
if (isChecked) {
// The toggle is enabled
preview.addView(mPreview);
Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} else {
// The toggle is disabled
preview.addView(mPreview);
Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}
}
});
}
protected void onDestroy () {
super.onDestroy();
if (mCamera != null){
mCamera.stopPreview();
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
public void showCamera() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
Toast.makeText(this, "Camera permission is needed to show the camera preview", Toast.LENGTH_SHORT).show();
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST_CAMERA);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
else {
// Permission has already been granted
mCamera = getCameraInstance();
mPreview = new CameraPreviewActivity(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
}
// Here, thisActivity is the current activity
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CAMERA: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Create our Preview view and set it as the content of our activity.
// permission was granted, yay! Do the
// contacts-related task you need to do.
showCamera();
} else {
Toast.makeText(this, "Permission was not granted", Toast.LENGTH_SHORT).show();
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
// other 'case' lines to check for other
// permissions this app might request.
And this is my CameraPreviewActivity.java
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreviewActivity(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}