使用 Android camera2 API 转动 on/off 闪光灯不工作
Turning on/off flash with Android camera2 API not working
我正在创建一个带有自定义相机的 Android 应用程序,我正在切换到新的相机 2 API。我有一个按钮,允许在后置摄像头打开时打开和关闭闪光灯(无需停止相机,就像任何经典相机应用程序一样)。
当我点击 flash 图标时,没有任何反应,这就是 logcat returns:
D/ViewRootImpl: ViewPostImeInputStage processPointer 0
D/ViewRootImpl: ViewPostImeInputStage processPointer 1
我不知道为什么它不起作用。这是代码:
我有一个 RecordVideoActivity
使用 RecordVideoFragment
。这是片段的 XML 部分,其中包含 Flash 按钮代码:
<ImageButton
android:id="@+id/button_flash"
android:src="@drawable/ic_flash_off"
android:layout_alignParentLeft="true"
style="@style/actions_icons_camera"
android:onClick="actionFlash"/>
和 Java 代码:
ImageButton flashButton;
private boolean hasFlash;
private boolean isFlashOn = false;
在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();
}
});
这里是 actionFlash()
函数定义:
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();
}
}
}
知道哪里出了问题吗?
(我已经看过 但它没有解决我的问题)
非常感谢您的帮助。这让我发疯。
创建这些变量:
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;
然后添加这些方法:
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);
}
}
在此 line 之后添加此代码:
Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
isFlashSupported = available == null ? false : available;
setupFlashButton();
最后在您想要的点击侦听器中调用 switchFlash()。
瞧瞧!
PS。这可能会有帮助 -
您的代码的问题是“mCameraManager.setTorchMode(mCameraId, true);”
此通话需要 API 23+。因此,您不能从低于 API 23 的 API 调用此本地方法。
你可以做的是使用 Depricated Camera API。它适用于所有设备,并将在不久的将来继续工作一段时间。
这是您可以执行的操作,使用 if-else 语句添加此代码。如果设备是 API23+,则使用 Camera2,否则使用 Camera。我就是这么做的。
在导入中添加 hardware.Camera
import android.hardware.Camera;
初始化变量
Camera camera;
Camera.Parameters params;
现在,拿起相机并打开闪光灯
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mCameraManager.setTorchMode(CameraId, true);
}
else {
camera = Camera.open();
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
}
catch (Exception e)
{
e.printStackTrace();
}
你很高兴。
@MrOnyszko 的回答是正确的,但需要更新为
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();
}
您使用的逻辑不向后兼容,我还验证了它甚至在某些 23+ 设备上也不起作用,最好使用相机管理器 api(支持 21 + 以后)
mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
有关详细信息,请参阅已接受的答案
我看到对于 cameraX,ImageCapture.flashMode 仅在我们使用初始配置构建期间有效,ImageCapture.Builder() 等。
但是如果你想enable/disable动态闪烁,就得用下面的
camera?.cameraControl?.enableTorch(enableFlash)
如果你想知道相机是什么?从文档中捕获它。
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
我正在创建一个带有自定义相机的 Android 应用程序,我正在切换到新的相机 2 API。我有一个按钮,允许在后置摄像头打开时打开和关闭闪光灯(无需停止相机,就像任何经典相机应用程序一样)。
当我点击 flash 图标时,没有任何反应,这就是 logcat returns:
D/ViewRootImpl: ViewPostImeInputStage processPointer 0
D/ViewRootImpl: ViewPostImeInputStage processPointer 1
我不知道为什么它不起作用。这是代码:
我有一个 RecordVideoActivity
使用 RecordVideoFragment
。这是片段的 XML 部分,其中包含 Flash 按钮代码:
<ImageButton
android:id="@+id/button_flash"
android:src="@drawable/ic_flash_off"
android:layout_alignParentLeft="true"
style="@style/actions_icons_camera"
android:onClick="actionFlash"/>
和 Java 代码:
ImageButton flashButton;
private boolean hasFlash;
private boolean isFlashOn = false;
在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();
}
});
这里是 actionFlash()
函数定义:
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();
}
}
}
知道哪里出了问题吗?
(我已经看过
非常感谢您的帮助。这让我发疯。
创建这些变量:
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;
然后添加这些方法:
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);
}
}
在此 line 之后添加此代码:
Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
isFlashSupported = available == null ? false : available;
setupFlashButton();
最后在您想要的点击侦听器中调用 switchFlash()。
瞧瞧!
PS。这可能会有帮助 -
您的代码的问题是“mCameraManager.setTorchMode(mCameraId, true);” 此通话需要 API 23+。因此,您不能从低于 API 23 的 API 调用此本地方法。 你可以做的是使用 Depricated Camera API。它适用于所有设备,并将在不久的将来继续工作一段时间。 这是您可以执行的操作,使用 if-else 语句添加此代码。如果设备是 API23+,则使用 Camera2,否则使用 Camera。我就是这么做的。
在导入中添加 hardware.Camera
import android.hardware.Camera;
初始化变量
Camera camera;
Camera.Parameters params;
现在,拿起相机并打开闪光灯
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mCameraManager.setTorchMode(CameraId, true);
}
else {
camera = Camera.open();
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
}
catch (Exception e)
{
e.printStackTrace();
}
你很高兴。
@MrOnyszko 的回答是正确的,但需要更新为
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();
}
您使用的逻辑不向后兼容,我还验证了它甚至在某些 23+ 设备上也不起作用,最好使用相机管理器 api(支持 21 + 以后)
mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
有关详细信息,请参阅已接受的答案
我看到对于 cameraX,ImageCapture.flashMode 仅在我们使用初始配置构建期间有效,ImageCapture.Builder() 等。 但是如果你想enable/disable动态闪烁,就得用下面的
camera?.cameraControl?.enableTorch(enableFlash)
如果你想知道相机是什么?从文档中捕获它。
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)