API21中如何使用cameraManager.setTorchMode?求Android5.0适配替代方案
Hey there, let's tackle this problem head-on. The cameraManager.setTorchMode() method was introduced in API 23 (Android 6.0), so we need a backward-compatible approach to control the torch on Android 5.0 (API 21) and 5.1 (API 22). Here's how to make it work:
Core Idea
We'll branch our code based on the Android API level:
- For API 23+: Use the modern
CameraManagerAPI you're already familiar with - For API 21-22: Fall back to the older
Cameraframework to control the flash
Step-by-Step Implementation
1. Set Up Permissions
First, make sure you have the necessary permissions in your AndroidManifest.xml—this applies to all API levels:
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.flash" android:required="false" />
Note: For API 23+, you'll need to request the
CAMERApermission dynamically. It's a good practice to handle this uniformly across all API levels to avoid crashes.
2. Implement Torch Control for Each API Range
API 23+ (Android 6.0+)
Stick with the CameraManager implementation you know:
private void activateTorchApi23(String cameraId) { CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { cameraManager.setTorchMode(cameraId, true); } catch (CameraAccessException e) { Log.e("TorchControl", "Failed to turn on torch", e); } } private void deactivateTorchApi23(String cameraId) { CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { cameraManager.setTorchMode(cameraId, false); } catch (CameraAccessException e) { Log.e("TorchControl", "Failed to turn off torch", e); } }
API 21-22 (Android 5.0-5.1)
Use the legacy Camera class to control the flash:
private Camera legacyCamera; private void activateTorchApi21() { if (legacyCamera == null) { try { // Open the default camera (usually rear-facing) legacyCamera = Camera.open(); Camera.Parameters params = legacyCamera.getParameters(); params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); legacyCamera.setParameters(params); legacyCamera.startPreview(); // Required to activate the flash } catch (Exception e) { Log.e("TorchControl", "Failed to turn on torch (legacy API)", e); } } } private void deactivateTorchApi21() { if (legacyCamera != null) { try { Camera.Parameters params = legacyCamera.getParameters(); params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); legacyCamera.setParameters(params); legacyCamera.stopPreview(); legacyCamera.release(); // Critical: Release the camera resource legacyCamera = null; } catch (Exception e) { Log.e("TorchControl", "Failed to turn off torch (legacy API)", e); } } }
Important: Always release the legacy
Camerainstance when you're done with it—failing to do so will lock the camera and prevent other apps from using it. Add a check in your activity'sonPause()oronDestroy()method to ensure this happens.
3. Unified Entry Point
Wrap everything in a single method that automatically picks the right implementation based on the device's API level:
public void setTorchEnabled(boolean enabled) { if (!hasFlashSupport()) { Toast.makeText(this, "This device doesn't support flash", Toast.LENGTH_SHORT).show(); return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { String rearCameraId = getRearCameraId(); if (enabled) { activateTorchApi23(rearCameraId); } else { deactivateTorchApi23(rearCameraId); } } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (enabled) { activateTorchApi21(); } else { deactivateTorchApi21(); } } else { Toast.makeText(this, "Torch control not supported on this Android version", Toast.LENGTH_SHORT).show(); } } // Helper: Check if the device has flash support private boolean hasFlashSupport() { return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); } // Helper: Get the ID of the rear-facing camera (API 23+) @RequiresApi(api = Build.VERSION_CODES.M) private String getRearCameraId() { CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { for (String cameraId : cameraManager.getCameraIdList()) { CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); Integer lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING); if (lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) { return cameraId; } } } catch (CameraAccessException e) { Log.e("TorchControl", "Failed to get camera ID", e); } // Fall back to the first camera ID if rear isn't found return "0"; }
Final Tips
- Resource Cleanup: In your activity's
onPause()method, callsetTorchEnabled(false)to ensure the torch is turned off and the legacy camera is released. - Permission Handling: Before calling
setTorchEnabled(), verify that theCAMERApermission is granted. For API 23+, useActivityCompat.requestPermissions()to ask the user for access. - Testing: Test on real devices running Android 5.0/5.1 to catch any edge cases (like camera being in use by another app).
内容的提问来源于stack exchange,提问作者Muhammad Haad Bin Zahid




