camera2 api output black image - java

I am using camera 2 api am using this code
private void createCameraPreviewSession() {
try {
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
mPreviewCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewCaptureRequestBuilder.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
if(mCameraDevice == null) {
return;
}
try {
mPreviewCaptureRequest = mPreviewCaptureRequestBuilder.build();
mCameraCaptureSession = session;
mCameraCaptureSession.setRepeatingRequest(
mPreviewCaptureRequest,
mSessionCaptureCallback,
mBackgroundHandler
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
Toast.makeText(
getApplicationContext(),
"create camera session failed!",
Toast.LENGTH_SHORT
).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
this is the lockfocus methods, I noticed that it produce black image with zero size file after shutting the image
if(getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")){
photoButton.setEnabled(true);
mState = STATE__WAIT_LOCK;
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_START);
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),
mSessionCaptureCallback, mBackgroundHandler);
this is my capturing an image
CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureStillBuilder.addTarget(mImageReader.getSurface());
if (isAutoFocusSupported())
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_AUTO);
else
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION,
ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
try {
mImageFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
mCaptureResult = result;
unLockFocus();
}
};
mCameraCaptureSession.stopRepeating();
mCameraCaptureSession.capture(
captureStillBuilder.build(), captureCallback, null
);
does anyone experience this and how did you fix this issue?

Related

Android Development: Camera2 takes videos fine, but can't take still images as the camera device has been disconnected

I have been trying to use this tutorial to create an app that can take pictures and videos with camera2 specifically as I need access to more technical aspects such as focus and exposure. As the title of this post states, I can get the code to save a video properly, but when I press the button to take a still image, it gives the following error message repeatedly:
Handler (android.os.Handler) {302c85a} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.os.Handler) {302c85a} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:560)
at android.os.Handler.enqueueMessage(Handler.java:778)
at android.os.Handler.sendMessageAtTime(Handler.java:727)
at android.os.Handler.sendMessageDelayed(Handler.java:697)
at android.os.Handler.post(Handler.java:427)
at android.hardware.camera2.impl.CameraDeviceImpl$CameraHandlerExecutor.execute(CameraDeviceImpl.java:2353)
at android.hardware.camera2.impl.CallbackProxies$SessionStateCallbackProxy.onCaptureQueueEmpty(CallbackProxies.java:94)
at android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onRequestQueueEmpty(CameraCaptureSessionImpl.java:864)
at android.hardware.camera2.impl.CameraDeviceImpl$CameraDeviceCallbacks.onRequestQueueEmpty(CameraDeviceImpl.java:2331)
at android.hardware.camera2.ICameraDeviceCallbacks$Stub.onTransact(ICameraDeviceCallbacks.java:187)
at android.os.Binder.execTransactInternal(Binder.java:1285)
at android.os.Binder.execTransact(Binder.java:1244)
This may be related to this error that occurs when the startPreview method is called (see code at the bottom of post):
android.hardware.camera2.CameraAccessException: CAMERA_DISCONNECTED (2): checkPidStatus:2085: The camera device has been disconnected
at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:1390)
...
at com.[example].androidcamera2api.MainActivity$10.onConfigured(MainActivity.java:986)
The code, which I have modified slightly from the original github example to use non-deprecated API, is as follows. (I have also commented out lines related to getting audio. They kept causing app crashes, but they are unnecessary for my use case so it shouldn't matter. Also omitted imports for brevity.)
public class MainActivity extends AppCompatActivity {
private static final String TAG = "Camera2VideoImageActivi";
private static final int REQUEST_CAMERA_PERMISSION_RESULT = 0;
private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT = 1;
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAIT_LOCK = 1;
private int mCaptureState = STATE_PREVIEW;
private TextureView mTextureView;
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
setupCamera(width, height);
connectCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
};
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
mMediaRecorder = new MediaRecorder();
if(mIsRecording){
try{
createVideoFileName();
} catch(IOException e){
e.printStackTrace();
}
startRecord();
mMediaRecorder.start();
runOnUiThread(new Runnable() {
#Override
public void run() {
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.setVisibility(View.VISIBLE);
mChronometer.start();
}
});
} else {
startPreview();
}
}
#Override
public void onDisconnected(CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
#Override
public void onError(CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
};
private HandlerThread mBackgroundHandlerThread;
private Handler mBackgroundHandler;
private String mCameraId;
private Size mPreviewSize;
private Size mVideoSize;
private Size mImageSize;
private ImageReader mImageReader;
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
mBackgroundHandler.post(new ImageSaver(reader.acquireLatestImage()));
}
};
private class ImageSaver implements Runnable {
private final Image mImage;
public ImageSaver(Image image) {
mImage = image;
}
#Override
public void run() {
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFileName);
fileOutputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaStoreUpdateIntent.setData(Uri.fromFile(new File(mImageFileName)));
sendBroadcast(mediaStoreUpdateIntent);
if(fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private MediaRecorder mMediaRecorder;
private Chronometer mChronometer;
private int mTotalRotation;
private CameraCaptureSession mPreviewCaptureSession;
private CameraCaptureSession.CaptureCallback mPreviewCaptureCallback = new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult captureResult) {
switch (mCaptureState) {
case STATE_PREVIEW:
break;
case STATE_WAIT_LOCK:
mCaptureState = STATE_PREVIEW;
Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
if(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show();
startStillCaptureRequest();
}
break;
}
}
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
process(result);
}
};
private CameraCaptureSession mRecordCaptureSession;
private CameraCaptureSession.CaptureCallback mRecordCaptureCallback = new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult captureResult) {
switch (mCaptureState) {
case STATE_PREVIEW:
break;
case STATE_WAIT_LOCK:
mCaptureState = STATE_PREVIEW;
Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
if(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show();
startStillCaptureRequest();
}
break;
}
}
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
process(result);
}
};
private CaptureRequest.Builder mCaptureRequestBuilder;
private ImageButton mRecordImageButton;
private ImageButton mStillImageButton;
private boolean mIsRecording = false;
private boolean mIsTimelapse = false;
private File mVideoFolder;
private String mVideoFileName;
private File mImageFolder;
private String mImageFileName;
private static SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 0);
ORIENTATIONS.append(Surface.ROTATION_90, 90);
ORIENTATIONS.append(Surface.ROTATION_180, 180);
ORIENTATIONS.append(Surface.ROTATION_270, 270);
}
private static class CompareSizeByArea implements Comparator<Size> {
#Override
public int compare(Size lhs, Size rhs) {
return Long.signum( (long)(lhs.getWidth() * lhs.getHeight()) -
(long)(rhs.getWidth() * rhs.getHeight()));
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermissions(new String[]{"android.permission.CAMERA","android.permission.WRITE_EXTERNAL_STORAGE","android.permission.READ_EXTERNAL_STORAGE"}, 1);
createVideoFolder();
createImageFolder();
mChronometer = (Chronometer) findViewById(R.id.chronometer);
mTextureView = (TextureView) findViewById(R.id.textureView);
mStillImageButton = (ImageButton) findViewById(R.id.cameraImageButton2);
mStillImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!(mIsTimelapse || mIsRecording)) {
checkWriteStoragePermission();
}
lockFocus();
}
});
mRecordImageButton = (ImageButton) findViewById(R.id.videoOnlineImageButton);
mRecordImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mIsRecording || mIsTimelapse) {
mChronometer.stop();
mChronometer.setVisibility(View.INVISIBLE);
mIsRecording = false;
mIsTimelapse = false;
mRecordImageButton.setImageResource(R.mipmap.btn_video_online);
// Starting the preview prior to stopping recording which should hopefully
// resolve issues being seen in Samsung devices.
startPreview();
mMediaRecorder.stop();
mMediaRecorder.reset();
Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaStoreUpdateIntent.setData(Uri.fromFile(new File(mVideoFileName)));
sendBroadcast(mediaStoreUpdateIntent);
} else {
mIsRecording = true;
mRecordImageButton.setImageResource(R.mipmap.btn_video_busy);
checkWriteStoragePermission();
}
}
});
mRecordImageButton.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mIsTimelapse =true;
mRecordImageButton.setImageResource(R.mipmap.btn_timelapse);
checkWriteStoragePermission();
return true;
}
});
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(mTextureView.isAvailable()) {
setupCamera(mTextureView.getWidth(), mTextureView.getHeight());
connectCamera();
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == REQUEST_CAMERA_PERMISSION_RESULT) {
if(grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(),
"Application will not run without camera services", Toast.LENGTH_SHORT).show();
}
if(grantResults[1] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(),
"Application will not have audio on record", Toast.LENGTH_SHORT).show();
}
}
if(requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if(mIsRecording || mIsTimelapse) {
mIsRecording = true;
mRecordImageButton.setImageResource(R.mipmap.btn_video_busy);
}
Toast.makeText(this,
"Permission successfully granted!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,
"App needs to save video to run", Toast.LENGTH_SHORT).show();
}
}
}
#Override
protected void onPause() {
closeCamera();
stopBackgroundThread();
super.onPause();
}
#Override
public void onWindowFocusChanged(boolean hasFocas) {
super.onWindowFocusChanged(hasFocas);
View decorView = getWindow().getDecorView();
if(hasFocas) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
private void setupCamera(int width, int height) {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for(String cameraId : cameraManager.getCameraIdList()){
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
CameraCharacteristics.LENS_FACING_FRONT){
continue;
}
StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
int deviceOrientation = getWindowManager().getDefaultDisplay().getRotation();
mTotalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation);
boolean swapRotation = mTotalRotation == 90 || mTotalRotation == 270;
int rotatedWidth = width;
int rotatedHeight = height;
if(swapRotation) {
rotatedWidth = height;
rotatedHeight = width;
}
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight);
mVideoSize = chooseOptimalSize(map.getOutputSizes(MediaRecorder.class), rotatedWidth, rotatedHeight);
mImageSize = chooseOptimalSize(map.getOutputSizes(ImageFormat.JPEG), rotatedWidth, rotatedHeight);
mImageReader = ImageReader.newInstance(mImageSize.getWidth(), mImageSize.getHeight(), ImageFormat.JPEG, 1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
mCameraId = cameraId;
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void connectCamera() {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED) {
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
} else {
if(shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA)) {
Toast.makeText(this,
"Video app required access to camera", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[] {android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO
}, REQUEST_CAMERA_PERMISSION_RESULT);
}
} else {
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
System.out.println("Opened camera " + mCameraId);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void startRecord() {
try {
if(mIsRecording) {
setupMediaRecorder();
} else if(mIsTimelapse) {
setupTimelapse();
}
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
Surface recordSurface = mMediaRecorder.getSurface();
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
mCaptureRequestBuilder.addTarget(previewSurface);
mCaptureRequestBuilder.addTarget(recordSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
mRecordCaptureSession = session;
try {
mRecordCaptureSession.setRepeatingRequest(
mCaptureRequestBuilder.build(), null, null
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.d(TAG, "onConfigureFailed: startRecord");
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void startPreview() {
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
try {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mCaptureRequestBuilder.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
Log.d(TAG, "onConfigured: startPreview");
mPreviewCaptureSession = session;
try {
mPreviewCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(),
null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.d(TAG, "onConfigureFailed: startPreview");
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void startStillCaptureRequest() {
try {
if(mIsRecording) {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
} else {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
//mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL);
Debug.logStack("Debug","Building still capture request",1);
}
mCaptureRequestBuilder.addTarget(mImageReader.getSurface());
mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, mTotalRotation);
CameraCaptureSession.CaptureCallback stillCaptureCallback = new
CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
try {
createImageFileName();
} catch (IOException e) {
e.printStackTrace();
}
}
};
if(mIsRecording) {
mRecordCaptureSession.capture(mCaptureRequestBuilder.build(), stillCaptureCallback, null);
} else {
mPreviewCaptureSession.capture(mCaptureRequestBuilder.build(), stillCaptureCallback, null);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void closeCamera() {
if(mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
if(mMediaRecorder != null) {
mMediaRecorder.release();
mMediaRecorder = null;
}
}
private void startBackgroundThread() {
mBackgroundHandlerThread = new HandlerThread("Camera2VideoImage");
mBackgroundHandlerThread.start();
mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper());
}
private void stopBackgroundThread() {
mBackgroundHandlerThread.quitSafely();
try {
mBackgroundHandlerThread.join();
mBackgroundHandlerThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation) {
int sensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
deviceOrientation = ORIENTATIONS.get(deviceOrientation);
return (sensorOrientation + deviceOrientation + 360) % 360;
}
private static Size chooseOptimalSize(Size[] choices, int width, int height) {
List<Size> bigEnough = new ArrayList<Size>();
for(Size option : choices) {
if(option.getHeight() == option.getWidth() * height / width &&
option.getWidth() >= width && option.getHeight() >= height) {
bigEnough.add(option);
}
}
if(bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizeByArea());
} else {
return choices[0];
}
}
private void createVideoFolder() {
File movieFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
mVideoFolder = new File(movieFile, "camera2VideoImage");
if(!mVideoFolder.exists()) {
mVideoFolder.mkdirs();
}
}
private File createVideoFileName() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "VIDEO_" + timestamp + "_";
File videoFile = File.createTempFile(prepend, ".mp4", mVideoFolder);
mVideoFileName = videoFile.getAbsolutePath();
return videoFile;
}
private void createImageFolder() {
File imageFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
mImageFolder = new File(imageFile, "camera2VideoImage");
if(!mImageFolder.exists()) {
mImageFolder.mkdirs();
}
}
private File createImageFileName() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "IMAGE_" + timestamp + "_";
File imageFile = File.createTempFile(prepend, ".jpg", mImageFolder);
mImageFileName = imageFile.getAbsolutePath();
return imageFile;
}
private void checkWriteStoragePermission() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
try {
createVideoFileName();
} catch (IOException e) {
e.printStackTrace();
}
if(mIsTimelapse || mIsRecording) {
startRecord();
mMediaRecorder.start();
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.setVisibility(View.VISIBLE);
mChronometer.start();
}
} else {
if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(this, "app needs to be able to save videos", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT);
}
} else {
try {
createVideoFileName();
} catch (IOException e) {
e.printStackTrace();
}
if(mIsRecording || mIsTimelapse) {
startRecord();
mMediaRecorder.start();
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.setVisibility(View.VISIBLE);
mChronometer.start();
}
}
}
private void setupMediaRecorder() throws IOException {
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
//mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile(mVideoFileName);
mMediaRecorder.setVideoEncodingBitRate(1000000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
//mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setOrientationHint(mTotalRotation);
mMediaRecorder.prepare();
}
private void setupTimelapse() throws IOException {
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
mMediaRecorder.setOutputFile(mVideoFileName);
mMediaRecorder.setCaptureRate(2);
mMediaRecorder.setOrientationHint(mTotalRotation);
mMediaRecorder.prepare();
}
private void lockFocus() {
mCaptureState = STATE_WAIT_LOCK;
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
try {
if(mIsRecording) {
mRecordCaptureSession.capture(mCaptureRequestBuilder.build(), mRecordCaptureCallback, mBackgroundHandler);
} else {
mPreviewCaptureSession.capture(mCaptureRequestBuilder.build(), mPreviewCaptureCallback, mBackgroundHandler);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
I would be grateful if anyone could identify why I am having this error and help me to get the app to properly take pictures.

How I Can Send Image I capture Using Camera 2 Api android to Server using Retrofit

I Build A camera 2 On Android And I Save the Image Once the Activity Open After 3 Second I take a Picture a save it on Device I try to Send the Image to server Below is my Code for Camera and API ,
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//open your camera here
transformImage(width,height);
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Transform you image captured size according to the surface width and height
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
//This is called when the camera is open
Log.e(TAG, "onOpened");
cameraDevice = camera;
createCameraPreview();
transformImage(textureView.getWidth(),textureView.getHeight());
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
takePicture();
}
},3000);
}
#Override
public void onDisconnected(CameraDevice camera) {
cameraDevice.close();
}
#Override
public void onError(CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(CameraActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
protected void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
protected void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
protected void takePicture() {
if(null == cameraDevice) {
Log.e(TAG, "cameraDevice is null");
return;
}
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if (characteristics != null) {
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
}
int width = 640;
int height = 480;
if (jpegSizes != null && 0 < jpegSizes.length) {
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
// captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, 0);
Date date = new Date();
final File file = new File(Environment.getExternalStorageDirectory()+"/"+date.getMinutes()
+date.getSeconds()+"pic.jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
System.out.println("Image Object File" + image);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (image != null) {
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream output = null;
try {
output = new FileOutputStream(file);
output.write(bytes);
} finally {
if (null != output) {
output.close();
}
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(CameraActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
UploadImage uploadImage = new UploadImage();
uploadImage.setFile(file);
RequestBody requestFile =
RequestBody.create(
MediaType.parse("image/jpg"),
file
);
MultipartBody.Part body =
MultipartBody.Part.createFormData("files[0]", file.getName(), requestFile);
Call<UploadImage> call = RetrofitClient.getmInstance().getApi().upload(body,
SharedPrefManger.getInstance(getApplication()).getToken());
call.enqueue(new Callback<UploadImage>() {
#Override
public void onResponse(Call<UploadImage> call, Response<UploadImage> response) {
if (response.code() == 204){
Toast.makeText(CameraActivity.this, response.body().toString(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(CameraActivity.this, "Upload Error: " + response.message(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<UploadImage> call, Throwable t) {
System.out.println("Error F: " + t.getMessage());
Toast.makeText(CameraActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
}
});
//Intent x = new Intent(CameraActivity.this,MainActivity.class);
//startActivity(x);
createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}

Camera 2 Api Error - the error that does not take pictures

I am having an issue with the Camera 2 Api.
When I try to take a picture it would not function. The system would not crash. The error only occurs when I try to take a picture.
Furthermore, I took all the permissions that I need in another activity.
The following error occurs.
Access denied finding property "persist.vendor.camera.privapp.list"
I do not know if it has a relation with the error. Please use it as a reference.
I know that there are similar questions, but neither worked.
I deleted some codes. If you have any inconvenience please let me know.
Thank you in advance.
public class Camera extends AppCompatActivity implements TextureView.SurfaceTextureListener,
ActivityCompat.OnRequestPermissionsResultCallback {
private AutoFitTextureView mTextureView;
private static final int REQUEST_CAMERA_PERMISSION = 1;
private static final int REQUEST_WRITE_STORAGE = 2;
private static final int REQUEST_SAVE_IMAGE = 1002;
private static final int MAX_PREVIEW_WIDTH = 2220;
private static final int MAX_PREVIEW_HEIGHT = 1080;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
private String mCameraId;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
private CaptureRequest.Builder mPreviewRequestBuilder;
private CaptureRequest mPreviewRequest;
private int mSensorOrientation;
private ImageReader mImageReader;
private Size mPreviewSize;
private File mImageFolder;
private Byte bytes;
private Bitmap bitmap;
private File mFile;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextureView = (AutoFitTextureView) findViewById(R.id.texture);
Button button02 = (Button)findViewById(R.id.button_take_picture);
button02.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick (View view){
takePicture();
}
}
);
}
}
private void setUpCameraOutputs ( int width, int height){
Activity activity = this;
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
mCameraId = cameraId;
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
continue;
}
Size largest = Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
new CompareSizesByArea());
int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
boolean swappedDimensions = false;
switch (displayRotation) {
case Surface.ROTATION_0:
case Surface.ROTATION_180:
if (mSensorOrientation == 90 || mSensorOrientation == 270) {
swappedDimensions = true;
}
break;
case Surface.ROTATION_90:
case Surface.ROTATION_270:
if (mSensorOrientation == 0 || mSensorOrientation == 180) {
swappedDimensions = true;
}
break;
}
Point displaySize = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
int rotatedPreviewWidth = width;
int rotatedPreviewHeight = height;
int maxPreviewWidth = displaySize.x;
int maxPreviewHeight = displaySize.y;
if (swappedDimensions) {
rotatedPreviewWidth = height;
rotatedPreviewHeight = width;
maxPreviewWidth = displaySize.y;
maxPreviewHeight = displaySize.x;
}
if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
maxPreviewWidth = MAX_PREVIEW_WIDTH;
}
if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
}
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
maxPreviewHeight, largest);
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(
mPreviewSize.getWidth(), mPreviewSize.getHeight());
} else {
mTextureView.setAspectRatio(
mPreviewSize.getHeight(), mPreviewSize.getWidth());
}
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (NullPointerException e) {
}
}
protected void takePicture () {
if (null == mCameraDevice) {
Log.e("Camera", "cameraDevice is null");
return;
}
if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
return;
}else{
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(this,"We need your permission to record and save image",Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_WRITE_STORAGE);
}
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraDevice.getId());
Size[] jpegSizes = null;
if (characteristics != null) {
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
}
int width = 640;
int height = 480;
if (jpegSizes != null && 0 < jpegSizes.length) {
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 2);
List<Surface> outputSurfaces = new ArrayList<>(2);
outputSurfaces.add(mImageReader.getSurface());
outputSurfaces.add(new Surface(mTextureView.getSurfaceTexture()));
int rotation = getWindowManager().getDefaultDisplay().getRotation();
//Callback that is called when a new image is available from ImageReader
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
//try {
mFile = new File(getExternalFilesDir(null), "sample.jpg");
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mFile);
fileOutputStream.write(bytes);
} catch (Exception e) {
e.printStackTrace();
}finally {
mImageReader.close();
if (null != fileOutputStream){
try {
fileOutputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
};
mImageReader.setOnImageAvailableListener(readerListener, null);
final CameraCaptureSession.CaptureCallback captureListener =
new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(Camera.this, "Saved:" + mImageReader, Toast.LENGTH_SHORT).show();
createCameraPreviewSession();
}
};
mCameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(mPreviewRequestBuilder.build(), captureListener, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreviewSession () {
try {
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
Surface surface = new Surface(texture);
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if (null == mCameraDevice) {
return;
}
mCaptureSession = cameraCaptureSession;
try {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest,
null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(
#NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
mCameraDevice = cameraDevice;
createCameraPreviewSession();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int error) {
Log.d("debug","Camera error");
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
};
#RequiresApi(api = Build.VERSION_CODES.M)
private void openCamera ( int width, int height){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"No permission to open camera",Toast.LENGTH_SHORT).show();
requestPermissions(new String[]{Manifest.permission.CAMERA},REQUEST_CAMERA_PERMISSION);
return;
}
setUpCameraOutputs(width, height);
CameraManager manager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
try {
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Time out waiting to lock camera opening.");
}
manager.openCamera(mCameraId, mStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
}
}
}
Could you try to request for the camera permission as the first thing before trying to take the actual picture? Maybe this is the reason it's crashing.
Remove this permission part from your method "take picture"
if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
return;
}else{
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(this,"We need your permission to record and save image",Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_WRITE_STORAGE);
}
You could execute it first before calling take picture

android.hardware.camera2.CameraAccessException: CAMERA_DISCONNECTED (2): The camera device has been disconnected

I've been struggling for a bit with Android Camera2 APIs.
When I rotate my device I'm getting
android.hardware.camera2.CameraAccessException: CAMERA_DISCONNECTED (2): checkPidStatus:1795: The camera device has been disconnected
During debugging I found out that it happens on this part of code
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
and than goes to catch section which handle CameraAccessException. Sometimes background is getting white and I cannot see camera preview. Here is a part of code:
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull final CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
mCameraDevice = cameraDevice;
createCameraPreviewSession();
}
#Override
public void onDisconnected(#NonNull final CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
#Override
public void onError(#NonNull final CameraDevice cameraDevice, final int error) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
final Activity activity = getActivity();
if (null != activity) {
activity.finish();
}
}
};
private void createCameraPreviewSession() {
try {
final SurfaceTexture texture = mAutoFitTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
final Surface surface = new Surface(texture);
mPreviewRequestBuilder
= mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface),
getStateCallback(), null
);
} catch (CameraAccessException e) {
e.printStackTrace();
Log.e("CameraAccessException: createCameraPreviewSession()", e.toString());
}
}
#NonNull
private CameraCaptureSession.StateCallback getStateCallback() {
return new CameraCaptureSession.StateCallback() {
#Override
public void onReady(#NonNull CameraCaptureSession session) {
super.onReady(session);
Log.d("getStateCallback: onReady()", "");
}
#Override
public void onClosed(#NonNull CameraCaptureSession session) {
super.onClosed(session);
Log.d("getStateCallback: onClosed()", "");
}
#Override
public void onConfigured(#NonNull final CameraCaptureSession cameraCaptureSession) {
if (null == mCameraDevice) {
return;
}
mCaptureSession = cameraCaptureSession;
try {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest,
mCaptureCallback, mBackgroundHandler);
} catch (final CameraAccessException e) {
e.printStackTrace();
Log.e("CameraAccessException: onConfigured()", e.toString());
}
}
#Override
public void onConfigureFailed(
#NonNull final CameraCaptureSession cameraCaptureSession) {
Log.d("getStateCallback: onConfigureFailed()", "failed");
showToast();
}
};
}
private void openCamera(final int width, final int height) {
if (ContextCompat.checkSelfPermission(Objects.requireNonNull(getActivity()), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestCameraPermission();
return;
}
setUpCameraOutputs(width, height);
configureTransform(width, height);
final CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
Objects.requireNonNull(manager).openCamera(mCameraId, mStateCallback, mBackgroundHandler);
} catch (final CameraAccessException e) {
e.printStackTrace();
Log.e("CameraAccessException: openCamera()", e.toString());
}
initAROverlayView();
}
#MainThread
private void closeCamera() {
try {
try {
mCameraOpenCloseLock.acquire();
} catch (InterruptedException e) {
Log.e("InterruptedException", e.toString());
}
if (null != mCaptureSession) {
mCaptureSession.close();
mCaptureSession = null;
}
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
} finally {
mCameraOpenCloseLock.release();
}
}
#Override
public void onResume() {
super.onResume();
startBackgroundThread();
registerSensors();
if (mAutoFitTextureView.isAvailable()) {
openCamera(mAutoFitTextureView.getWidth(), mAutoFitTextureView.getHeight());
} else {
mAutoFitTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
#Override
public void onPause() {
try {
closeCamera();
stopBackgroundThread();
} catch (InterruptedException e) {
Log.e("InterruptedException", e.toString());
}
super.onPause();
}

Taking pictures at regular intervals (Android Camera API)

So I'm trying to take multiple pictures at regular time intervals, however I get a "takePicture Failed" Exception after the first picture is previewed on the surfaceView.
Here's my takePictures() method which is called when a button is pressed:
public void takePictures() {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
camera = Camera.open();
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
camera.takePicture(null, null, new CustomPictureCallbcak(this, cacheDir, imageView, 3, 5000));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
else {
Toast.makeText(this, "No camera found.", Toast.LENGTH_SHORT).show();
}
}
And here's the onPictureTaken() method of CustomPictureCallback :
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//get date info for file name
SimpleDateFormat sdf = new SimpleDateFormat("ddmmyyyyhhmmss");
String date = sdf.format(new Date());
String fileDir = createImageFileName(date);
//write the image to cache
writeImageToCache(fileDir, data);
//display file name in a toast notification
Toast.makeText(c, fileDir, Toast.LENGTH_SHORT).show();
//show picture on imageview
imageView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
//retake images
this.camera = camera;
while (numOfImagesAlreadyTaken <= numOfImages) {
Thread thread = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
numOfImagesAlreadyTaken++;
CustomPictureCallbcak.this.camera.stopPreview();
sleep(delay);
CustomPictureCallbcak.this.camera.takePicture(null, null, CustomPictureCallbcak.this);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
Toast.makeText(c, "Total images taken: " + numOfImagesAlreadyTaken, Toast.LENGTH_SHORT).show();
//release camera
camera.release();
camera = null;
}
As Aleksander Lidtke suggested, I created a single thread inside my takePictures() method and put a while loop inside it:
public void takePictures(final int numOfPictures, final int delay) {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Thread thread = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
while (numOfPicturesAlreadyTaken <= numOfPictures) {
try {
camera = Camera.open();
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
camera.takePicture(null, null, new CustomPictureCallbcak(MainActivity.this, cacheDir, imageView));
numOfPicturesAlreadyTaken++;
sleep(delay);
}
catch (Exception e) {
e.printStackTrace();
Log.d("TEST", e.getMessage());
}
}
}
};
thread.start();
}
else {
Toast.makeText(this, "No camera found.", Toast.LENGTH_SHORT).show();
}
}

Categories