I'm creating an Android app with a custom camera and I'm switching to the new camera2 API. I have a button allowing to turn ON and OFF the flash when the back camera is on (without stopping the camera, like any classic camera app).
When I tap the flash icon, nothing happens and this is what the logcat returns:
D/ViewRootImpl: ViewPostImeInputStage processPointer 0
D/ViewRootImpl: ViewPostImeInputStage processPointer 1
I don't know why it's not working. Here is the code:
I have a RecordVideoActivity
using a RecordVideoFragment
. Here is the fragment's XML part that contains the flash button code:
<ImageButton
android:id="@+id/button_flash"
android:src="@drawable/ic_flash_off"
android:layout_alignParentLeft="true"
style="@style/actions_icons_camera"
android:onClick="actionFlash"/>
And the Java code:
ImageButton flashButton;
private boolean hasFlash;
private boolean isFlashOn = false;
With in the onViewCreated
:
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
...
[some code]
...
// Flash on/off button
flashButton = (ImageButton) view.findViewById(R.id.button_flash);
// Listener for Flash on/off button
flashButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
actionFlash();
}
});
And here is the actionFlash()
function definition:
private void actionFlash() {
/* First check if device is supporting flashlight or not */
hasFlash = getActivity().getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (!hasFlash) {
// device doesn't support flash
// Show alert message and close the application
AlertDialog alert = new AlertDialog.Builder(this.getActivity())
.create();
alert.setMessage("Sorry, your device doesn't support flash light!");
alert.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.show();
return;
}
else { // the device support flash
CameraManager mCameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
String mCameraId = mCameraManager.getCameraIdList()[0];
if (mCameraId.equals("1")) { // currently on back camera
if (!isFlashOn) { // if flash light was OFF
// Turn ON flash light
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mCameraManager.setTorchMode(mCameraId, true);
}
} catch (Exception e) {
e.printStackTrace();
}
// Change isFlashOn boolean value
isFlashOn = true;
// Change button icon
flashButton.setImageResource(R.drawable.ic_flash_off);
} else { // if flash light was ON
// Turn OFF flash light
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mCameraManager.setTorchMode(mCameraId, false);
}
} catch (Exception e) {
e.printStackTrace();
}
// Change isFlashOn boolean value
isFlashOn = false;
// Change button icon
flashButton.setImageResource(R.drawable.ic_flash_on);
}
}
} catch (CameraAccessException e) {
Toast.makeText(getActivity(), "Cannot access the camera.", Toast.LENGTH_SHORT).show();
getActivity().finish();
}
}
}
Any idea what could be wrong?
(I already looked at this question but it doesn't address my problem)
Thank you very much for your help. This is driving me crazy.
Create these variables:
public static final String CAMERA_FRONT = "1";
public static final String CAMERA_BACK = "0";
private String cameraId = CAMERA_BACK;
private boolean isFlashSupported;
private boolean isTorchOn;
then add these methods:
public void switchFlash() {
try {
if (cameraId.equals(CAMERA_BACK)) {
if (isFlashSupported) {
if (isTorchOn) {
mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
flashButton.setImageResource(R.drawable.ic_flash_off);
isTorchOn = false;
} else {
mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
flashButton.setImageResource(R.drawable.ic_flash_on);
isTorchOn = true;
}
}
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
public void setupFlashButton() {
if (cameraId.equals(CAMERA_BACK) && isFlashSupported) {
flashButton.setVisibility(View.VISIBLE);
if (isTorchOn) {
flashButton.setImageResource(R.drawable.ic_flash_off);
} else {
flashButton.setImageResource(R.drawable.ic_flash_on);
}
} else {
flashButton.setVisibility(View.GONE);
}
}
after this line add this code:
Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
isFlashSupported = available == null ? false : available;
setupFlashButton();
at the end call switchFlash() in your desired click listener.
et voilà!
PS. This might be helpful - front/back camera switcher
I see for cameraX, ImageCapture.flashMode only has effect during we build with initial configuration, ImageCapture.Builder() etc. But if you want to enable/disable flash dynamically, you will have to use the following.
camera?.cameraControl?.enableTorch(enableFlash)
If you are wondering what camera is? Captured it from documentation.
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
The answer by @MrOnyszko is correct, but it needs to be updated to
isTorchAvailable = camChars.get(CameraCharacteristics.FLASH_INFO_AVAILABLE).booleanValue();
CameraManager camManager = (CameraManager).context.getSystemService(Context.CAMERA_SERVICE);
try {
String cameraId cameraId = camManager.getCameraIdList()[0];
CameraCharacteristics camChars = camManager.getCameraCharacteristics(cameraId);
boolean isTorchAvailable = camChars.get(CameraCharacteristics.FLASH_INFO_AVAILABLE).booleanValue();
if(isTorchAvailable) {
camManager.setTorchMode(cameraId, true); //Turn ON
camManager.setTorchMode(cameraId, false);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With