You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

API21中如何使用cameraManager.setTorchMode?求Android5.0适配替代方案

解决API 21下无法使用CameraManager.setTorchMode()的问题

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 CameraManager API you're already familiar with
  • For API 21-22: Fall back to the older Camera framework 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 CAMERA permission 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 Camera instance 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's onPause() or onDestroy() 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, call setTorchEnabled(false) to ensure the torch is turned off and the legacy camera is released.
  • Permission Handling: Before calling setTorchEnabled(), verify that the CAMERA permission is granted. For API 23+, use ActivityCompat.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

火山引擎 最新活动