如何在所有Android设备上实现闪光灯控制?
我正在用Camera包开发Android应用来实现闪光灯开启功能,代码如下:
Camera mCamera = Camera.open(); List<String> flashModes = mCamera.getParameters().getSupportedFlashModes(); if(flashModes != null && flashModes.contains(Parameters.FLASH_MODE_TORCH)){ parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); mCamera.setParameters(parameters); } else if (flashModes != null && flashModes.contains(Parameters.FLASH_MODE_ON)){ parameters.setFlashMode(Parameters.FLASH_MODE_ON); mCamera.setParameters(parameters); }
请问这段代码能否适配所有Android设备实现闪光灯控制?
回答:
很遗憾,这段代码没办法适配所有Android设备,这里有几个关键的兼容性问题需要注意:
权限与相机资源处理缺失
Android 6.0(API 23)及以上版本需要动态申请CAMERA权限,你现在的代码完全没处理权限申请逻辑,会直接崩溃。另外,Camera.open()可能因为其他应用占用相机而抛出RuntimeException,而且使用完相机后没有调用mCamera.release()释放资源,会导致后续相机调用失败。未指定相机ID的问题
Camera.open()默认打开后置相机,但有些设备存在多相机(比如前置+后置+超广角),部分相机可能没有闪光灯模块。你应该遍历所有可用相机,检查每个相机的参数是否支持闪光灯,再选择合适的相机实例。闪光灯激活的前置条件
不少设备的硬件要求必须启动相机预览才能激活闪光灯——也就是说,你需要先调用mCamera.setPreviewDisplay()绑定一个SurfaceView,再调用mCamera.startPreview(),之后才能设置闪光灯模式,否则闪光灯可能无法正常亮起。代码本身的语法问题
你代码里的parameters变量没有初始化,应该先获取相机参数:Camera.Parameters parameters = mCamera.getParameters();,不然会直接抛出空指针异常。
改进后的示例代码:
private Camera mCamera; private boolean isFlashOn = false; private void toggleFlash() { // 检查权限(Android 6.0+) if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 100); return; } if (isFlashOn) { // 关闭闪光灯 turnOffFlash(); } else { // 打开闪光灯 turnOnFlash(); } } private void turnOnFlash() { if (mCamera == null) { // 遍历相机,找到支持闪光灯的相机 for (int i = 0; i < Camera.getNumberOfCameras(); i++) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(i, info); // 优先选择后置相机(有闪光灯的概率更高) if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { try { mCamera = Camera.open(i); break; } catch (RuntimeException e) { e.printStackTrace(); } } } } if (mCamera != null) { try { Camera.Parameters parameters = mCamera.getParameters(); List<String> supportedFlashModes = parameters.getSupportedFlashModes(); if (supportedFlashModes != null) { // 先启动预览(部分设备要求必须有预览才能开闪光灯) SurfaceView dummySurface = new SurfaceView(this); mCamera.setPreviewDisplay(dummySurface.getHolder()); mCamera.startPreview(); if (supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) { parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); } else if (supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_ON)) { parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON); } else { // 设备不支持闪光灯 Toast.makeText(this, "设备不支持闪光灯", Toast.LENGTH_SHORT).show(); return; } mCamera.setParameters(parameters); isFlashOn = true; } } catch (IOException e) { e.printStackTrace(); } } else { Toast.makeText(this, "无法打开相机", Toast.LENGTH_SHORT).show(); } } private void turnOffFlash() { if (mCamera != null) { Camera.Parameters parameters = mCamera.getParameters(); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); mCamera.setParameters(parameters); mCamera.stopPreview(); mCamera.release(); mCamera = null; isFlashOn = false; } } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 100) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { toggleFlash(); } else { Toast.makeText(this, "需要相机权限才能使用闪光灯", Toast.LENGTH_SHORT).show(); } } }
另外还要注意,Camera类在API 21之后已经被弃用,推荐使用CameraX库来实现闪光灯功能,它的兼容性更好,不需要处理复杂的设备差异。
内容的提问来源于stack exchange,提问作者JoonSoo Park

