如何在Android中检测相机是否在后台被使用(类iOS Access dot)?
用Camera2 API检测相机后台录制的问题修复
原代码的核心问题
- 重复注册回调:每次
onResume都会注册新的AvailabilityCallback,导致多次触发回调,逻辑混乱 - 错误调用父类方法:
super.onCameraAvailable和super.onCameraUnavailable应传入回调参数自带的cameraId,而非硬编码的第一个相机ID - UI线程问题:传入
null作为Handler,回调可能在非主线程执行,直接调用txt.setText会引发异常 - 回调未注销:未在生命周期结束时注销回调,易造成内存泄漏
修正后的代码
private CameraManager.AvailabilityCallback cameraCallback; private Handler mainHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txt = findViewById(R.id.txt); mainHandler = new Handler(Looper.getMainLooper()); CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { cameraCallback = new CameraManager.AvailabilityCallback() { @Override public void onCameraAvailable(String cameraId) { super.onCameraAvailable(cameraId); // 切换到主线程更新UI mainHandler.post(() -> txt.setText("相机可用")); } @Override public void onCameraUnavailable(String cameraId) { super.onCameraUnavailable(cameraId); mainHandler.post(() -> txt.setText("相机被占用(可能在后台录制)")); } }; manager.registerAvailabilityCallback(cameraCallback, mainHandler); } } @Override protected void onDestroy() { super.onDestroy(); CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && cameraCallback != null) { manager.unregisterAvailabilityCallback(cameraCallback); } }
进阶优化:更精准检测后台录制
AvailabilityCallback只能判断相机是否被占用,无法区分是预览还是录制。若需精准识别录制状态,可结合以下方案:
- Android 12+:使用
MediaRecorder的registerRecordingCallback,监听录制状态变化 - 权限补充:申请
PACKAGE_USAGE_STATS权限,通过UsageStatsManager查询当前使用相机的应用包名,判断是否在后台运行
注意:部分厂商系统可能对相机权限做特殊处理,导致回调触发不及时,需在不同设备上做兼容性测试。
内容的提问来源于stack exchange,提问作者mahdi
相关产品推荐
相关产品推荐

