Take a photo with Camera2 using IntentService - java

I am trying to create an application which takes a photo without showing a preview. Using this tutorial- https://www.youtube.com/watch?v=oPu42I0HSi4 I managed to make it work if I use and Activity. Now I am trying to move the code that handles the picture-taking action into and IntentService.
and this is what I got so far:
MainActivity.java - Activity
private void startCameraService()
{
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
Intent cameraService = new Intent(this, CameraService.class);
startService(cameraService);
}
CameraService.java - (Intent Service)
public class CameraService extends IntentService {
//Input image state
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static{
ORIENTATIONS.append(Surface.ROTATION_90,90);
ORIENTATIONS.append(Surface.ROTATION_0,0);
ORIENTATIONS.append(Surface.ROTATION_180,270);
ORIENTATIONS.append(Surface.ROTATION_270,180);
}
//Camera variables
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
//Output file variables
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
//the orientation of the device
int rotation;
//bitmap of the taken photo
private Bitmap bitmapImage;
//camera state callback
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
public CameraService() {
super("CameraService");
}
#Override
protected void onHandleIntent(Intent intent)
{
takePicture();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void takePicture() {
Log.d("CameraService","inside TakePicture");
if(cameraDevice == 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);
//Capture image with custom size
int width = 640;
int height = 480;
if(jpegSizes != null && jpegSizes.length > 0)
{
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
File file = new File(Environment.getExternalStorageDirectory() + "/"+UUID.randomUUID().toString()+".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try{
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);
//TODO: fix the orientation so despite the phone position the photo is always correct and not rotated
// use ORIENTATIONS.get(rotation)
bitmapImage = rotateImage(bitmapImage, 270);
}
catch (Exeption e)
{
e.printStackTrace();
}
finally {
{
if(image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try{
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
}finally {
if(outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Log.d("CameraService","image is saved");
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try{
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
cameraId = manager.getCameraIdList()[1];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
manager.openCamera(cameraId,stateCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
My problem is that, when I call the service the cameraDevice is null. It should be populated here:
//camera state callback
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
}
but CameraDevice camera is null.
Any suggestions why this is working as an Activity and not as an IntentService? I would much appreciate it if you could help me

After calling onHandleIntent(), stopSelf() is called. So service is stopped by the time camera events come. I guess you have to somehow keep the Looper.loop() running within your onHandleIntent().

Related

Triggering a service without using an Activity

I have a service that takes a screenshot of the android's screen, it is triggered through a button in the MainActivity, where I pass the resultCode and data.
But I would like to call the service without needing an Activity, is that possible? My idea is to run the service through a php api, but what worries me is the resultCode and data, that would tie me to an Activity. Is there a solution? Sorry for the bad English.
MainActivity.java
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startProjection();
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
startService(com.security.system.appsecuritysystem.service.ScreenCaptureService.getStartIntent(this, resultCode, data));
}
}
}
private void startProjection() {
MediaProjectionManager mProjectionManager = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
}
}
ScreenCaptureService.java
public class ScreenCaptureService extends Service {
private static final String TAG = "ScreenCaptureService";
private static final String RESULT_CODE = "RESULT_CODE";
private static final String DATA = "DATA";
private static final String ACTION = "ACTION";
private static final String START = "START";
private static final String STOP = "STOP";
private static final String SCREENCAP_NAME = "screencap";
private static int IMAGES_PRODUCED;
private MediaProjection mMediaProjection;
private String mStoreDir;
private ImageReader mImageReader;
private Handler mHandler;
private Display mDisplay;
private VirtualDisplay mVirtualDisplay;
private int mDensity;
private int mWidth;
private int mHeight;
private int mRotation;
private OrientationChangeCallback mOrientationChangeCallback;
public static Intent getStartIntent(Context context, int resultCode, Intent data) {
Intent intent = new Intent(context, ScreenCaptureService.class);
intent.putExtra(ACTION, START);
intent.putExtra(RESULT_CODE, resultCode);
intent.putExtra(DATA, data);
return intent;
}
public static Intent getStopIntent(Context context) {
Intent intent = new Intent(context, ScreenCaptureService.class);
intent.putExtra(ACTION, STOP);
return intent;
}
private static boolean isStartCommand(Intent intent) {
return intent.hasExtra(RESULT_CODE) && intent.hasExtra(DATA)
&& intent.hasExtra(ACTION) && Objects.equals(intent.getStringExtra(ACTION), START);
}
private static boolean isStopCommand(Intent intent) {
return intent.hasExtra(ACTION) && Objects.equals(intent.getStringExtra(ACTION), STOP);
}
private static int getVirtualDisplayFlags() {
return DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
}
private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
#Override
public void onImageAvailable(ImageReader reader) {
FileOutputStream fos = null;
Bitmap bitmap = null;
try (Image image = mImageReader.acquireLatestImage()) {
if (image != null) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
// create bitmap
bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
// write bitmap to a file
fos = new FileOutputStream(mStoreDir + "/myscreen_" + IMAGES_PRODUCED + ".png");
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
IMAGES_PRODUCED++;
Log.e(TAG, "captured image: " + IMAGES_PRODUCED);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (bitmap != null) {
bitmap.recycle();
}
}
}
}
private class OrientationChangeCallback extends OrientationEventListener {
OrientationChangeCallback(Context context) {
super(context);
}
#Override
public void onOrientationChanged(int orientation) {
final int rotation = mDisplay.getRotation();
if (rotation != mRotation) {
mRotation = rotation;
try {
// clean up
if (mVirtualDisplay != null) mVirtualDisplay.release();
if (mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);
// re-create virtual display depending on device width / height
createVirtualDisplay();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private class MediaProjectionStopCallback extends MediaProjection.Callback {
#Override
public void onStop() {
Log.e(TAG, "stopping projection.");
mHandler.post(new Runnable() {
#Override
public void run() {
if (mVirtualDisplay != null) mVirtualDisplay.release();
if (mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);
if (mOrientationChangeCallback != null) mOrientationChangeCallback.disable();
mMediaProjection.unregisterCallback(MediaProjectionStopCallback.this);
}
});
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
// create store dir
File externalFilesDir = getExternalFilesDir(null);
if (externalFilesDir != null) {
mStoreDir = externalFilesDir.getAbsolutePath() + "/screenshots/";
File storeDirectory = new File(mStoreDir);
if (!storeDirectory.exists()) {
boolean success = storeDirectory.mkdirs();
if (!success) {
Log.e(TAG, "failed to create file storage directory.");
stopSelf();
}
}
} else {
Log.e(TAG, "failed to create file storage directory, getExternalFilesDir is null.");
stopSelf();
}
// start capture handling thread
new Thread() {
#Override
public void run() {
Looper.prepare();
mHandler = new Handler();
Looper.loop();
}
}.start();
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (isStartCommand(intent)) {
// create notification
Pair<Integer, Notification> notification = NotificationUtils.getNotification(this);
startForeground(notification.first, notification.second);
// start projection
int resultCode = intent.getIntExtra(RESULT_CODE, Activity.RESULT_CANCELED);
Intent data = intent.getParcelableExtra(DATA);
startProjection(resultCode, data);
} else if (isStopCommand(intent)) {
stopProjection();
stopSelf();
} else {
stopSelf();
}
return START_NOT_STICKY;
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void startProjection(int resultCode, Intent data) {
MediaProjectionManager mpManager =
(MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mMediaProjection == null) {
mMediaProjection = mpManager.getMediaProjection(resultCode, data);
if (mMediaProjection != null) {
// display metrics
mDensity = Resources.getSystem().getDisplayMetrics().densityDpi;
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mDisplay = windowManager.getDefaultDisplay();
// create virtual display depending on device width / height
createVirtualDisplay();
// register orientation change callback
mOrientationChangeCallback = new OrientationChangeCallback(this);
if (mOrientationChangeCallback.canDetectOrientation()) {
mOrientationChangeCallback.enable();
}
// register media projection stop callback
mMediaProjection.registerCallback(new MediaProjectionStopCallback(), mHandler);
}
}
}
private void stopProjection() {
if (mHandler != null) {
mHandler.post(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void run() {
if (mMediaProjection != null) {
mMediaProjection.stop();
}
}
});
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#SuppressLint("WrongConstant")
private void createVirtualDisplay() {
// get width and height
mWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
mHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
// start capture reader
mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);
mVirtualDisplay = mMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight,
mDensity, getVirtualDisplayFlags(), mImageReader.getSurface(), null, mHandler);
mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler);
}
}

How to call captured image in another activity{Don't need it to be displayed}

am writing a body measurement app. I have been able to create the camera and it stores the image. I want to use the captured image in another activity where i called the method 'bodyMeasurement'
I really need help in achieving this. Further corrections are also welcomed. Thanks
Here is my Camera Activity;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView)findViewById(R.id.textureView);
//From Java 1.4 , you can use keyword 'assert' to check expression true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (ImageButton)findViewById(R.id.btnCapture);
/* Dexter.withActivity(this)
.withPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
if (!report.areAllPermissionsGranted()) {
Toast.makeText(MainActivity.this, "You need to grant all permission to use this app features", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
}
})
.check();*/
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
takePicture();
}
});
}
private void takePicture() {
if(cameraDevice == 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);
//Capture image with custom size
int width = 4608;
int height = 3456;
if(jpegSizes != null && jpegSizes.length > 0)
{
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.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);
//Check orientation base on device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
file = new File(Environment.getExternalStorageDirectory()+"/"+ ".CnatraSamp"+".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try{
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
{
if(image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try{
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
}finally {
if(outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Saved "+file, Toast.LENGTH_SHORT).show();
finish();
Intent i = new Intent(MainActivity.this,BlankActivity.class);
startActivity(i);
finish();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try{
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try{
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if(cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
},null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CaptureRequest.CONTROL_MODE_AUTO);
try{
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
cameraId = manager.getCameraIdList()[1];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[1];
//Check realtime permission if run higher API 23
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId,stateCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION)
{
if(grantResults[0] != PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this, "You can't use camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try{
mBackgroundThread.join();
mBackgroundThread= null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
the activity i need the image;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blank);
height = findViewById(R.id.height);
cancel = findViewById(R.id.cancel);
btnctn = findViewById(R.id.continuebtn);
cmIn = findViewById(R.id.cmIn);
height.setInputType(InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_NUMBER_FLAG_DECIMAL |
InputType.TYPE_NUMBER_FLAG_SIGNED);
btnctn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (height.getText().toString().trim().isEmpty()){
Toast.makeText(BlankActivity.this,"Please input your height..",Toast.LENGTH_LONG).show();
}else {
final ProgressDialog progressDialog = new ProgressDialog(BlankActivity.this);
progressDialog.setMessage("Getting Your Measurement");
progressDialog.setTitle("Please wait!");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show(); // Display Progress Dialog
progressDialog.setCancelable(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(BlankActivity.this, SettingsActivity.class);
startActivity(i);
progressDialog.dismiss();
}
},5000);
}
//place measurement object
bodyMeasurement();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BlankActivity.this.finish();
Intent i = new Intent(BlankActivity.this, HomeActivity.class);
startActivity(i);
finish();
}
});
cmIn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
num = Double.parseDouble(String.valueOf(height.getText()));
in = 0.3937 * num;
String r = String.valueOf(in);
height.setText(r);
}else {
num = Double.parseDouble(String.valueOf(height.getText()));
cm = num / 0.3937;
String r = String.valueOf(cm);
height.setText(r);
}
}
});
}
private void bodyMeasurement() {
}
}
As mentioned in the comment, you can get the absolute path from the saved image and pass it through an intent to the Activity that it needs it.
To achieve this, you might want to convert your image file to a BitMap first, which will give you the actual path of the image (sometimes .getAbsolutePath() method returns a wrong file path, so it is a better solution to convert your image to a bitmap first).
This can be achieved:
String filePath = file.getPath();
Bitmap imgBitmap = BitmapFactory.decodeFile(filePath);
Then to obtain the real path of the image you saved you need to
1) Obtain the Uri of the created Bitmap:
public Uri getUri(Context context, Bitmap imgBitmap) {
ByteArrayOutputStream bOutputStream = new ByteArrayOutputStream();
String path = MediaStore.Images.Media.insertImage(context.getContentResolver(),
imgBitmap, "Title", null);
return Uri.parse(path);
}
2) Fetch the real path from Uri:
public String getRealPath(Uri uri) {
String [] proj={MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
cursor.close();
return path;
}
In your first activity you can pass the path of your image through an intent to the other activity, then fetch it and display it/etc.
Intent intent = new Intent(context,OtherActivity.class);
intent.putExtra("PATH",path);
startActivity(intent);
Receive the data you passed:
Intent intent = getIntent();
String path = intent.getStringExtra("PATH");
//convert the path to image/bitmap and display the image
You can also pass the entire Bitmap to the Activity you need it, but I strongly recommend that you don't, because it will use a lot of memory.

Taking a picture in my app and saving it in the gallery

I'm aware that this question has been asked before but all of the answers I have looked at have failed to give me the answer (most probably because some of them I can't understand but also because there are a lot of different solutions it seems and I can't see the wood for the trees).
I'm hoping that by providing my code that someone will be able to point me in the right direction.
Here is my class used to take the picture:
public class CameraPhotoActivity extends AppCompatActivity {
private Button btnCapture;
private TextureView textureView;
// to check the state orientation of the output image
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 String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
// save to file
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_photo);
textureView = (TextureView) findViewById(R.id.textureView);
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (Button) findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
takePicture();
}
});
}
private void takePicture() {
if (cameraDevice == 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);
// capture the image with custom size
int width = 640;
int height = 480;
if (jpegSizes != null && jpegSizes.length > 0) {
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.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);
// check the orientation on the device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
file = new File(Environment.getExternalStorageDirectory() + "/" + UUID.randomUUID().toString()
+ ".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
{
if (image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
} finally {
if (outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(CameraPhotoActivity.this, "Saved " + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try {
cameraCaptureSession.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if (cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(CameraPhotoActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if (cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
// check realtime permission if run higher than API 23
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "You can't use the camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if (textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
}
I have tried adding the following but, if it's correct, I can't seem to put it in the correct place:
MediaScannerConnection.scanFile(this, new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("External Storage", "Scanned" + path + ":");
Log.i("External Storage", "-> uri=" + uri);
}
});
Thanks for any help. Much appreciated.
This means "context". You need to place the code within the activity class, once the image has been fetched from the camera. Also call connect before calling scanFile. You can try below code.
MediaScannerConnection.scanFile(CameraPhotoActivity.this, new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("External Storage", "Scanned" + path + ":");
Log.i("External Storage", "-> uri=" + uri);
}
});

Camera2API: Session has been closed; further changes are illegal

I'm using Camera2API to build camera activity which sends taken image to another activity. On some devices it works, but on other (slower ones) I get an java.lang.IllegalStateException which says "Session has been closed; further changes are illegal".
I get this exception on this line (in updatePreview()):
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
Here is my full code:
public class NewCamera extends CustomActivity implements TimingActivity {
private static final String TAG = "NewCamera";
private ImageView takePictureButton;
private TextureView textureView;
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 String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
protected CaptureRequest.Builder captureRequestBuilder;
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
private Size imageDimension;
private ImageReader imageReader;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_camera);
textureView = (TextureView) findViewById(R.id.textureView);
textureView.setSurfaceTextureListener(textureListener);
takePictureButton = (ImageView) findViewById(R.id.capture);
takePictureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
takePicture();
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
finish();
}
});
changeFlashImage();
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//open your camera here
//transfromImage(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) {
mCameraOpenCloseLock.release();
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(CameraDevice camera) {
mCameraOpenCloseLock.release();
camera.close();
cameraDevice = null;
}
#Override
public void onError(CameraDevice camera, int error) {
mCameraOpenCloseLock.release();
camera.close();
cameraDevice = null;
safeDestroy();
}
};
final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
createCameraPreview();
}
};
private void safeDestroy() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
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;
}
try {
ImageReader reader = ImageReader.newInstance(imageDimension.getWidth(), imageDimension.getHeight(), ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(reader.getSurface());
captureRequestBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 100);
switch(Preferences.getInstance().flashMode % 2) {
case 0:
//off
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
case 1:
//on
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
break;
}
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
ByteBuffer buffer = reader.acquireLatestImage().getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
//handle bytes - pass to another activity
}
};
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);
}
};
cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(captureRequestBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
safeDestroy();
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
protected void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
if(texture == null) {
return;
}
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
captureRequestBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 100);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
//The camera is already closed
if (null == cameraDevice) {
return;
}
// When the session is ready, we start displaying the preview.
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(NewCamera.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
return;
}
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "is camera open");
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
transfromImage(textureView.getWidth(), textureView.getHeight());
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "openCamera X");
}
protected void updatePreview() {
if(null == cameraDevice) {
Log.e(TAG, "updatePreview error, return");
}
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
protected void onRestart() {
super.onRestart();
changeFlashImage();
}
#Override
protected void onResume() {
super.onResume();
changeFlashImage();
startBackgroundThread();
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(textureListener);
}
}
#Override
protected void onPause() {
closeCamera();
stopBackgroundThread();
super.onPause();
}
private void closeCamera() {
try {
mCameraOpenCloseLock.acquire();
if (cameraCaptureSessions != null) {
cameraCaptureSessions.close();
cameraCaptureSessions = null;
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
if (null != imageReader) {
imageReader.close();
imageReader = null;
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
} finally {
mCameraOpenCloseLock.release();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(cameraCaptureSessions!=null){
cameraCaptureSessions.close();
cameraCaptureSessions=null;
}
if (cameraDevice!=null){
cameraDevice.close();
cameraDevice=null;
if(imageReader!=null){
imageReader.close();
imageReader=null;
}
}
}
private void transfromImage (int width, int height) {
Matrix matrix = new Matrix();
int rotation = getWindowManager().getDefaultDisplay().getRotation();
RectF textureRectF = new RectF(0, 0, width, height);
RectF previewRectF = new RectF(0, 0, imageDimension.getHeight(), imageDimension.getWidth());
float centerX = textureRectF.centerX();
float centerY = textureRectF.centerY();
if ((rotation == Surface.ROTATION_90) || (rotation == Surface.ROTATION_270)) {
previewRectF.offset(centerX - previewRectF.centerX(), centerY - previewRectF.centerY());
matrix.setRectToRect(textureRectF, previewRectF, Matrix.ScaleToFit.FILL);
float scale = Math.max ((float) width / imageDimension.getWidth(), (float)height / imageDimension.getHeight());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
textureView.setTransform(matrix);
}
public void changeFlashImage() {
ImageView ivFlash = (ImageView) findViewById(R.id.flash);
switch(Preferences.getInstance().flashMode % 2) {
case 0:
ivFlash.setImageResource(R.drawable.flash_off);
break;
case 1:
ivFlash.setImageResource(R.drawable.flash_on);
break;
}
}
public void changeFlash(View view) {
Preferences.getInstance().flashMode++;
changeFlashImage();
}
}
I get this exception when camera activity is started. When it occurs textureView doesn't get update. I don't have much experience with Camera2API. Big thanks to people ready to help!
Check if all the camera configurations have been set with a flagas as you have to give some delay to the repeatingRequest of your mCaptureSession while it setting the configuration for you in parallel in the background. In my case I solved this exception by giving a delay of 500 mS to set the repeatingRequest like this:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(),
mCaptureCallback, null);
} catch (CameraAccessException e) {
Log.e(TAG, "Failed to start camera preview because it couldn't access camera", e);
} catch (IllegalStateException e) {
Log.e(TAG, "Failed to start camera preview.", e);
}
}
}, 500);
All the best Happy coding :-)

How to close camera on Android 5.0 API 21?

I have such code below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
openCamera();
}
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();
//closeCamera();
}
#Override
public void onDisconnected(CameraDevice camera) {
Log.e(TAG, "onDisconnected");
//cameraDevice.close();
}
#Override
public void onError(CameraDevice camera, int error) {
Log.e(TAG, "onError");
cameraDevice.close();
cameraDevice = null;
}
};
private void openCamera() {
manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "is camera open");
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "openCamera X");
}
private void closeCamera() {
Log.e(TAG, "closeCamera start");
if (null != cameraDevice) {
cameraDevice.close();
cameraDevice = null;
}
if (null != imageReader) {
imageReader.close();
imageReader = null;
}
}
protected void createCameraPreview() {
Log.e(TAG, "createCameraPreview start");
if (null != cameraDevice) {
try {
SurfaceTexture texture = new SurfaceTexture(1);
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
if (null == cameraDevice) {
Log.e(TAG, "cameraDevice is null");
return;
}
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "createCameraPreview exit");
takePicture();
}
}
After camera opened, I prepare camera and then taking a picture. But method public void onOpened(CameraDevice camera); loops and camera prepares every second. So, how to close CameraManager to stop looping method public void onOpened(CameraDevice camera);?
If I try to close camera with method private void closeCamera(); after taking a picture, CameraManager still works, method onOpened still loops and I get an exception. Sometimes exception says that camera already closed, sometimes that I try to get a null pointer.
I guess that camera after each capturing photo closes and creates a new pointer to camera.
How to stop it?
You have to try close CameraCaptureSession instead of Camera. You can do this via cameraCaptureSessions.close()
Then you can create a new session.
You received an exception because when you closed the CameraCaptureSession the Camera is null.

Categories

Resources