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/
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 trying to record video using a Vivo X20 (7.1.1) and the camera2 api without using a preview and without recording sound (Strictly recording HD Video only).
I'm currently stuck because I cannot figure out how to successfully call MediaRecorder.setVideoSize() and record a video in HD. Currently when I run the app the log shows the error: Surface with size (w=1920, h=1080) and format 0x1 is not valid, size not in valid set: [1440x1080, 1280x960, 1280x720, 960x540, 800x480, 720x480, 768x432, 640x480, 384x288, 352x288, 320x240, 176x144]
The phone's stock camera app can record video up to 4K so I'm definitely missing something here. There are a total of two camera devices identified by CameraManager. When I use getOutPutFormats() from CameraCharacteristics it shows the same valid set of resolutions for both cameras and it is the same range as the above error message.
The below is the code I am using to initialize MediaRecorder and initiate a capture session:
public void StartRecordingVideo() {
Initialize();
recordingVideo = true;
cameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
String[] cameraIDs = cameraManager.getCameraIdList();
//LogAllCameraInfo();
if (cameraIDs != null)
{
for(int x = 0; x < cameraIDs.length; x++)
{
Log.d(LOG_ID, "ID: " + cameraIDs[x]);
}
}
cameraManager.openCamera(deviceCameraID, cameraStateCallback, handler);
Log.d(LOG_ID, "Successfully opened camera");
}
else
{
throw new IllegalAccessException();
}
}
catch (Exception e)
{
recordingVideo = false;
Log.e(LOG_ID, "Error during record video start: " + e.getMessage());
}
}
private void Initialize()
{
videoRecordThread = new HandlerThread("video_capture");
videoRecordThread.start();
handler = new Handler((videoRecordThread.getLooper()));
try
{
vidRecorder = new MediaRecorder();
vidRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
vidRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
vidRecorder.setVideoFrameRate(30);
vidRecorder.setCaptureRate(30);
vidRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
vidRecorder.setVideoEncodingBitRate(10000000);
vidRecorder.setVideoSize(1920, 1080);
String videoFilename = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + System.currentTimeMillis() + ".mp4";
vidRecorder.setOutputFile(videoFilename);
Log.d(LOG_ID, "Starting video: " + videoFilename);
vidRecorder.prepare();
}
catch (Exception e)
{
Log.e(LOG_ID, "Error during Initialize: " + e.getMessage());
}
}
And the onReady/onSurfacePrepared/Camera onOpened callbacks:
#Override
public void onReady(CameraCaptureSession session) {
Log.d(LOG_ID, "onReady: ");
super.onReady(session);
try {
CaptureRequest.Builder builder = deviceCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
builder.addTarget(vidRecorder.getSurface());
CaptureRequest request = builder.build();
session.setRepeatingRequest(request, null, handler);
vidRecorder.start();
} catch (CameraAccessException e) {
Log.d(LOG_ID, "Error on Ready: " + e.getMessage());
}
}
#Override
public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
Log.d(LOG_ID, "onSurfacePrepared: ");
super.onSurfacePrepared(session, surface);
}
#Override
public void onOpened(CameraDevice camera) {
Log.d(LOG_ID, "onOpened: ");
deviceCamera = camera;
try {
camera.createCaptureSession(Arrays.asList(vidRecorder.getSurface()), recordSessionStateCallback, handler);
} catch (CameraAccessException e) {
Log.d(LOG_ID, "onOpened: " + e.getMessage());
}
}
I've tried messing with the order of calls and the output format/encoder with no luck. I am sure that I have all the required permissions. Thanks in advance for your time!
This device most likely supports camera2 at the LEGACY level; check what the output of INFO_SUPPORTED_HARDWARE_LEVEL is.
LEGACY devices are effectively running camera2 on top of the legacy android.hardware.Camera API (more complex than that, but roughly true); as a result, their capabilities via camera2 are restricted.
The maximum recording resolution is one significant problem; android.hardware.Camera records videos via a magic path that the LEGACY mapping layer cannot directly use (there's no Surface involved). As a result, camera2 LEGACY can only record at the maximum preview resolution supported by android.hardware.Camera, not at the maximum recording resolution.
Sounds like this device has no support for 1:1 1080p preview, which is pretty unusual for a device launched so recently.
You can verify if the set of supported preview sizes in the deprecated Camera API matches the list you get in your error; if it doesn't then there may be a OS bug in generating the list so it'd be good to know.
But in general, you can't request sizes that aren't enumerated in the CameraCharacteristics StreamConfiguraitonMap for the camera, no matter what the feature list on the side of the box says. Sometimes the OEM camera app has magic hooks to enable features that normal apps can't get to; often because the feature only works in some very very specific set of circumstances, which normal apps wouldn't know how to replicate.
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.
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);