I'm trying to create an Android app which supports both Camera and Camera2, and I have done that by using if statements which check the API level for appropriate sections of code. However, I'm having trouble coping with the CameraAccessException in that I'm getting a lint error, but I'm not sure how to get rid of it. If I surround the try/catch with an if statement which checks the API level, the lint error doesn't go away. Is there any other way of getting rid of the lint error? I'd rather not suppress inspections. Here is an example of what I'm talking about:
private String getFrontCamera2() {
if (Build.VERSION.SDK_INT >= 21) {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String[] cameraIdList;
try {
cameraIdList = cameraManager.getCameraIdList();
} catch (CameraAccessException e) {
return null;
}
for (String cameraId : cameraIdList) {
CameraCharacteristics cameraCharacteristics = null;
try {
cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
} catch (CameraAccessException e) {
return null;
}
Integer lensFacing = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
if (lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_FRONT) {
return cameraId;
}
}
}
return null;
}
Both catch statements in that piece of code are generating the lint error "Class requires API level 21".
I just learned about the #TargetApi annotation, which solves my problem.
Related
How to identify that the CameraDevice is front or back. Now I'am trying to find some field that could differentiate between front and back camera in CameraCharacteristics. Is this the right way? I don't want to open and switch between CameraDevices before knowing which one is right.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
String[] cameraList = cameraManager.getCameraIdList();
for (String cameraId : cameraList) {
CameraCharacteristics cameraProps = cameraManager.getCameraCharacteristics(cameraId);
// Help here
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Todo
}
} catch (CameraAccessException cameraAccessException) {
}
}
CameraCharacteristics has an integer variable named LENS_FACING which gives the direction the camera faces relative to device screen.
See official documentation here -
https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#LENS_FACING
I am developing a flashlight app that switch on/off the system tourch.
I have a crash that shown on Android M (v6.0) on
Crashlytics
Here is the Issue details and stacktrace:
Fatal Exception: java.lang.IllegalArgumentException: Receiver not registered: android.hardware.camera2.CameraManager$1#49e5f1b
at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:789)
at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1222)
at android.hardware.camera2.CameraManager$3.run(CameraManager.java:1266)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5728)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
I have the following Manifest permissions and hardware features:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.flash" />
and
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
****EDIT:****
Here is the code I am using to access the camera:
// Here, I am checking if SDK >= M
if (VersionUtils.isMarshmallowOrGreater()) {
cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
if (cameraManager != null) {
try {
cameraId = cameraManager.getCameraIdList()[0];
} catch (CameraAccessException | ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
} else {
if (camera == null || camera.getParameters() == null) {
try {
camera = Camera.open();
params = camera.getParameters();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
Here is the code to switch on the flash/tourch:
if (VersionUtils.isMarshmallowOrGreater()) {
try {
cameraManager.setTorchMode(cameraId, true);
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (camera == null || params == null || camera.getParameters() == null) {
getCamera();
return;
}
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
startCameraPreview();
}
Also, here is the code of switching off the camera flash:
if (VersionUtils.isMarshmallowOrGreater()) {
try {
cameraManager.setTorchMode(cameraId, false);
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (camera == null || params == null || camera.getParameters() == null) {
return;
}
try {
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
stopCameraPreview();
camera.release();
camera = null;
} catch (Exception e) {
e.printStackTrace();
}
}
Code of startCameraPreview() method:
private void startCameraPreview() {
try {
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
I don't have any receiver in my app except the widget provider class but I don't have any line of code the do (register/unregister) a receiver!!
I searched and read many links resources regarding this issue but I could not find any clue to exactly know the line which causing it.
Anyone faced this issue, your help is appreciated.
I had the same issue (or similar). My stacktrace was exactly as yours. I've solved my problem by ensuring (in the code of my application) that I don't try to switch torch Off if the torch was not turned ON by my application previously.
Crash occurred when I was calling cameraManager.setTorchMode(cameraId, false) two times sequentially.
So I just maintain boolean flag in my application which shows exact torch state at the moment. Set it to true right after cameraManager.setTorchMode(cameraId, true) call and don't do cameraManager.setTorchMode(cameraId, false) if the flag in not true. Set the flag to false after successful cameraManager.setTorchMode(cameraId, false).
Hope this helps...
Camera.Parameters is deprecated in API level 21. Use CameraManager instead.
For setFlashMode (String value) in Camera.Parameters, there is an equivalent method setTorchMode (String cameraId, boolean enabled) in CameraManager
I think this post (When trying turn off camera led, app crash) is helpful.
In short,
f you try to disable flashlight again (even if flashlight is already disabled), then app is crashed.
I'm working with the new Camera2 API on a Samsung S5. The supported hardware level this device is reporting is LEGACY, which is fine.
However, I cannot seem to be able to auto-focus on this device. The request to trigger auto-focus looks like this:
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
state = STATE_PREVIEW;
try {
captureSession.setRepeatingRequest(previewRequestBuilder.build(), captureCallback, backgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
After the request is sent, the result of the request is always CONTROL_AF_STATE_ACTIVE_SCAN and occasionally CONTROL_AF_STATE_NOT_FOCUSED_LOCKED.
The strange thing is that, when the state is CONTROL_AF_STATE_NOT_FOCUSED_LOCKED, the auto-focus goes back into the CONTROL_AF_STATE_ACTIVE_SCAN state for a while and then back to CONTROL_AF_STATE_NOT_FOCUSED_LOCKED, resulting in a infinite focus loop. According to the docs, when state is CONTROL_AF_STATE_NOT_FOCUSED_LOCKED...
The lens will remain stationary until the AF mode (android.control.afMode) is changed or a new AF trigger is sent to the camera device (android.control.afTrigger).
I'm wondering if this discrepancy is because of the fact that the hardware level is LEGACY and that I should go back to using the deprecated Camera API, but that seems crazy for such a prevalent feature such as auto focus.
Is there any reccomendations how how to treat devices that are reporting LEGACY?
I branched form google's Camera2Basic example and changed it to use CaptureRequest.CONTROL_AF_MODE_AUTO instead of CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
You can take the project from git and test it - https://github.com/pinhassi/android-Camera2Basic
Or just add this to Camera2BasicFragment:
private static final long LOCK_FOCUS_DELAY_ON_FOCUSED = 5000;
private static final long LOCK_FOCUS_DELAY_ON_UNFOCUSED = 1000;
private Integer mLastAfState = null;
private Handler mUiHandler = new Handler(); // UI handler
private Runnable mLockAutoFocusRunnable = new Runnable() {
#Override
public void run() {
lockAutoFocus();
}
};
public void lockAutoFocus() {
try {
// This is how to tell the camera to lock focus.
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
CaptureRequest captureRequest = mPreviewRequestBuilder.build();
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, null); // prevent CONTROL_AF_TRIGGER_START from calling over and over again
mCaptureSession.capture(captureRequest, mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
/**
*
* #return
*/
private float getMinimumFocusDistance() {
if (mCameraId == null)
return 0;
Float minimumLens = null;
try {
CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics c = manager.getCameraCharacteristics(mCameraId);
minimumLens = c.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
} catch (Exception e) {
Log.e(TAG, "isHardwareLevelSupported Error", e);
}
if (minimumLens != null)
return minimumLens;
return 0;
}
/**
*
* #return
*/
private boolean isAutoFocusSupported() {
return isHardwareLevelSupported(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) || getMinimumFocusDistance() > 0;
}
// Returns true if the device supports the required hardware level, or better.
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private boolean isHardwareLevelSupported(int requiredLevel) {
boolean res = false;
if (mCameraId == null)
return res;
try {
CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(mCameraId);
int deviceLevel = cameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
switch (deviceLevel) {
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_3");
break;
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_FULL");
break;
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY");
break;
case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED:
Log.d(TAG, "Camera support level: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED");
break;
default:
Log.d(TAG, "Unknown INFO_SUPPORTED_HARDWARE_LEVEL: " + deviceLevel);
break;
}
if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
res = requiredLevel == deviceLevel;
} else {
// deviceLevel is not LEGACY, can use numerical sort
res = requiredLevel <= deviceLevel;
}
} catch (Exception e) {
Log.e(TAG, "isHardwareLevelSupported Error", e);
}
return res;
}
Then, add to STATE_PREVIEW block:
case STATE_PREVIEW: {
// We have nothing to do when the camera preview is working normally.
// TODO: handle auto focus
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState != null && !afState.equals(mLastAfState)) {
switch (afState) {
case CaptureResult.CONTROL_AF_STATE_INACTIVE:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_INACTIVE");
lockAutoFocus();
break;
case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN");
break;
case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED");
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_FOCUSED);
break;
case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_UNFOCUSED);
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED");
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
//mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_UNFOCUSED);
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED");
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN");
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
mUiHandler.removeCallbacks(mLockAutoFocusRunnable);
//mUiHandler.postDelayed(mLockAutoFocusRunnable, LOCK_FOCUS_DELAY_ON_FOCUSED);
Log.d(TAG, "CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED");
break;
}
}
mLastAfState = afState;
break;
}
And replace all occurrences of:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
With:
if (isAutoFocusSupported())
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_AUTO);
else
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
I think the issue is with your setRepeatingRequest. As far as I know, CaptureRequest.CONTROL_AF_MODE_AUTO should only cause an autofocus to occur once, but setRepeatingRequest will send continuous requests. Try using capture instead:
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
state = STATE_PREVIEW;
try {
mCaptureSession.capture(mPreviewRequestBuilder.build(), mPreCaptureCallback, mBackgroundHandler);
} catch (Exception e) {e.printStackTrace();}
I experience the same issue with a Galaxy Note 4 running Android 5.1.1 - while the same code works fine on a variety of other Android devices. There have been reports of similar issues with Galaxy-S4/S5/S6.
http://developer.samsung.com/forum/board/thread/view.do?boardName=SDK&messageId=289824&startId=zzzzz~
https://www.youtube.com/watch?v=lnMoYZwVaFM
So to anwer you question: This is most likely a bug in Samsung's implementation of the Camera-2 implementation - which seems to be of very low quality, unfourtunately.
The Samsung S5 with autofocus returned INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, which means it does not support Camera2 api.
I have the below filter for using camera in my application.
if (Build.VERSION.SDK_INT >= 21 && isDeviceCompatibleOfCamera2()) {
// Use camera2
} else {
// Use old camera
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean isDeviceCompatibleOfCamera2() {
try {
CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
String backCameraId = manager.getCameraIdList()[0];
CameraCharacteristics backCameraInfo = manager.getCameraCharacteristics(backCameraId);
int level = backCameraInfo.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
return level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
} catch (CameraAccessException e) {
ETLog.d(TAG, "Device not compatible of camera2 api" + e);
}
return false;
}
I have a problem regarding the camera in the most recent Marshmallow build, more specifically the flashlight.
On any pre-Marshmallow version all I need to do to turn the flash on/off was the following:
private void turnFlashOn(final Camera camera, int flashLightDurationMs) {
if (!isFlashOn()) {
final List<String> supportedFlashModes = camera.getParameters().getSupportedFlashModes();
if (supportedFlashModes != null && supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(mParams);
}
}
}
and
private void turnFlashOff(Camera camera) {
if (camera != null) {
final List<String> supportedFlashModes = camera.getParameters().getSupportedFlashModes();
if (supportedFlashModes != null && supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(mParams);
}
}
}
Unfortunately, Marshmallow devices began to crash in the wild. Somehow camera.getParameters() and camera.setParameters() began to fail with messages such as:
RuntimeException: getParameters failed (empty parameters)
RuntimeException: setParameters failed
I tried starting and stopping the preview before getting the parameters, which no longer throws errors. However the preview is not resumed when I call camera.startPreview().
I fear releasing the camera and reopening it is out of the question as this takes some seconds and would produce a bad experience.
Any suggestions on how to turn the flashlight on/off in Marshmallow reliably?
Google has introduced torchmode in OS 6 (Android M).
if your purpose is only to turn on/off the flash, below code can help you with that:
private static void handleActionTurnOnFlashLight(Context context){
try{
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
String[] list = manager.getCameraIdList();
manager.setTorchMode(list[0], true);
}
catch (CameraAccessException cae){
Log.e(TAG, cae.getMessage());
cae.printStackTrace();
}
}
private static void handleActionTurnOffFlashLight(Context context){
try{
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
manager.setTorchMode(manager.getCameraIdList()[0], false);
}
catch (CameraAccessException cae){
Log.e(TAG, cae.getMessage());
cae.printStackTrace();
}
}
All you have to do is: Get cameraid's list out of which camera ID zero(0) is your primary camera for which you want to turn flash on/off. Simply pass the cameraID to setTochMode API with boolean value for turning it on or off.
Do note that this piece of code will work only with OS 6, so you need to check for device OS and based upon that you need to select which API's to call for pre-marshmallow devices.
Kindly mark this as solution if it solves your problem.
As Saurabh7474 has responded, to check the version of Android and use setTorchMode API it's very correct.
Although you can also use params.setFlashMode (...) in marshmallow using
mCamera.setPreviewTexture (new SurfaceTexture (100))
after Camera.open (...) and before calling mCamera.startPreview();
try {
Log.i(TAG, "getCamera");
int requestedCameraId = getIdForRequestedCamera(mFacing);
if (requestedCameraId == -1) {
throw new RuntimeException("Could not find requested camera.");
}
mCamera = Camera.open(requestedCameraId);
mCamera.setPreviewTexture(new SurfaceTexture(DUMMY_TEXTURE_NAME));
params = mCamera.getParameters();
} catch (RuntimeException e) {
Log.e("Failed to Open. Error:", e.getMessage());
} catch (IOException e) {
Log.e("Failed to Open. can't setPreviewTexture:", e.getMessage());
}
then when you want, you can use
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(mParams);
My answer is based on CameraSource examples of Vision API that uses params.setFlashMode (...) and works in Api 23 and above.
If you decide to inspect CameraSource, the key method that has solved the same problem is "start ()", in the line 312 ...
https://github.com/googlesamples/android-vision/blob/master/visionSamples/barcode-reader/app/src/main/java/com/google/android/gms/samples/vision/barcodereader/ui/camera/CameraSource.java
The reason you can find here
https://stackoverflow.com/a/33333046/4114846
Update your app to check for permissions at runtime. You have to have android.permission.CAMERA granted. Including it in the manifest of your app is not going to grant it to you on Marshmallow. You'll need to detect whether or not it has been granted and request it.
Building off of Saurabh7474's answer, you can toggle Marshmallow's torchMode by registering a torchCallback:
final CameraManager mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
CameraManager.TorchCallback torchCallback = new CameraManager.TorchCallback() {
#Override
public void onTorchModeUnavailable(String cameraId) {
super.onTorchModeUnavailable(cameraId);
}
#Override
public void onTorchModeChanged(String cameraId, boolean enabled) {
super.onTorchModeChanged(cameraId, enabled);
boolean currentTorchState = enabled;
try {
mCameraManager.setTorchMode(cameraId, !currentTorchState);
} catch (CameraAccessException e){}
}
};
mCameraManager.registerTorchCallback(torchCallback, null);//fires onTorchModeChanged upon register
mCameraManager.unregisterTorchCallback(torchCallback);
I recently noticed that the Camera API is deprecated and I found the new API called Camera2.
I have read the documentation but I don't really understand it.
So my question is: how do I preview the front camera with the new camera api?
Just a preview, not recording.
I want to use this new API because in the future I'm guessing the current Camera API will be replaced and stop working.
So I want to be prepared and just sit and watch while everyone panics. XD
First of all, find out the id of your front camera (if it has one of course)
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
return manager.getCameraIdList();
} catch (CameraAccessException e) {
return null;
}
Then find the faceCamera like this:
CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(cameraId);
if (cameraCharacteristics == null)
throw new NullPointerException("No camera with id " + cameraId);
return cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
Lastly, you have to set the camera with that id:
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
characteristics = manager.getCameraCharacteristics(mCameraId);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Note, these are just tips on how to do what you wanna do.
For details on how to start a preview and more, refer to:
http://developer.android.com/samples/Camera2Basic/index.html
0 for Back
1 for Front
For Back Camera, we have to do this inside openCamera method:
cameraId = manager.getCameraIdList()[0];
For Facing Front camera, we have to add this below line inside openCamera method:
cameraId = manager.getCameraIdList()[1];
I have added all the codes and screenshot here
We can get the Characteristics of the cameras in our device
private void getCameraCharacteristics (){
try {
CameraManager manager=(CameraManager)getSystemService(Context.CAMERA_SERVICE);
for(String id : manager.getCameraIdList()){
Log.e(TAG, "Camara: Id " + id );
CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(id);
List<CameraCharacteristics.Key<?>> listaCaracteristicas = cameraCharacteristics.getKeys();
for(CameraCharacteristics.Key<?> caracteristica : listaCaracteristicas){
Log.i(TAG, "caracteristic: " + caracteristica.getName() + " : " + cameraCharacteristics.get(caracteristica));
}
Log.i(TAG, listaCaracteristicas.toString());
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
one of this characteristics is android.lens.facing, so based on this value we can get the Frontal camera:
if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT){
//Frontal camera
}
This is a method to get this value:
private String getIdFrontalCamera () {
try {
CameraManager manager=(CameraManager)getSystemService(Context.CAMERA_SERVICE);
for(String id : manager.getCameraIdList()){
CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(id);
//Seek frontal camera.
if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT){
Log.i(TAG, "Camara frontal id " + id);
return id;
}
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
return "0";
}
most of the times the id of the frontal camera is 1.
I used the code from the Google Camera2 API sample with some changes to get the front and back cameras working including saving the images locally and changing the shape of the TextureView by using an overlay.
I dealt with image rotation using exif interface too.
There is quite a bit of code so I'm going to post a link to my GitHub repo:
https://github.com/craigspicer/Camera2API
https://nullparams.com/camera-2-api-tutorial/