Android如何监听是否有应用在使用当前系统权限如定位、语音、摄像头等?
需求来源:应用正在收集个人敏感信息时,顶部状态栏位置显示图标
使用Android系统服务(Context.APP_OPS_SERVICE)即可监听当前是否有应用使用权限
具体使用代码如下:
//在AndroidManifest.xml文件中声明使用权限
<uses-permission android:name="android.permission.WATCH_APPOPS"/>
private AppOpsManager.OnOpActiveChangedListener changedListener;
initAppops(getApplicationContext());
void initAppops(Context context){
Log.i(TAG, "initAppops()");
if (context == null) {
Log.e(TAG, "Context is null!");
return;
}
// 获取 AppOpsManager 实例
final AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (appOpsManager != null) {
// 创建监听器并实现回调
changedListener = new AppOpsManager.OnOpActiveChangedListener() {
@Override
public void onOpActiveChanged(String op, int uid, String packageName, boolean active) {
Log.i(TAG, "onOpActiveChanged op=" op + ", packageName=" + packageName + ", active=" + active);
// 检查是否是相关权限的操作
switch (op) {
case AppOpsManager.OPSTR_RECORD_AUDIO:
case AppOpsManager.OPSTR_MUTE_MICROPHONE:
case AppOpsManager.OPSTR_PLAY_AUDIO:
Log.d(TAG, String.format("MICROPHONE-麦克风权限被调用, 权限: %s, 状态: %b, 包名: %s", op, active, packageName));
break;
case AppOpsManager.OPSTR_FINE_LOCATION:
case AppOpsManager.OPSTR_COARSE_LOCATION:
case AppOpsManager.OPSTR_MONITOR_LOCATION:
case AppOpsManager.OPSTR_MONITOR_HIGH_POWER_LOCATION:
case AppOpsManager.OPSTR_GPS:
Log.d(TAG, String.format("LOCATION-定位权限被调用, 权限: %s, 状态: %b, 包名: %s", op, active, packageName));
break;
case AppOpsManager.OPSTR_CAMERA:
Log.d(TAG, String.format("CAMERA-相机权限被调用, 权限: %s, 状态: %b, 包名: %s", op, active, packageName));
break;
case AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE:
case AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE:
case AppOpsManager.OPSTR_LEGACY_STORAGE:
case AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE:
Log.d(TAG, String.format("STORAGE-存储权限被调用, 权限: %s, 状态: %b, 包名: %s", op, active, packageName));
break;
case AppOpsManager.OPSTR_READ_CONTACTS:
case AppOpsManager.OPSTR_WRITE_CONTACTS:
Log.d(TAG, String.format("CONTACTS-联系人权限被调用, 权限: %s, 状态: %b, 包名: %s", op, active, packageName));
break;
case AppOpsManager.OPSTR_READ_CALL_LOG:
case AppOpsManager.OPSTR_WRITE_CALL_LOG:
case AppOpsManager.OPSTR_READ_PHONE_STATE:
Log.d(TAG, String.format("CALL_LOG-通话记录权限被调用, 权限: %s, 状态: %b, 包名: %s", op, active, packageName));
break;
default:
break;
}
}
};
// 开始监听相关权限
appOpsManager.startWatchingActive(
new String[]{
AppOpsManager.OPSTR_RECORD_AUDIO, // 麦克风权限
AppOpsManager.OPSTR_FINE_LOCATION, // 精确定位权限
AppOpsManager.OPSTR_COARSE_LOCATION, // 粗略定位权限
AppOpsManager.OPSTR_CAMERA, // 相机权限
AppOpsManager.OPSTR_MONITOR_LOCATION,
AppOpsManager.OPSTR_MONITOR_HIGH_POWER_LOCATION,
AppOpsManager.OPSTR_GPS,
AppOpsManager.OPSTR_MUTE_MICROPHONE,
AppOpsManager.OPSTR_PLAY_AUDIO,
AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE,
AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE,
AppOpsManager.OPSTR_LEGACY_STORAGE,
AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE,
AppOpsManager.OPSTR_READ_CONTACTS,
AppOpsManager.OPSTR_WRITE_CONTACTS,
AppOpsManager.OPSTR_READ_CALL_LOG,
AppOpsManager.OPSTR_WRITE_CALL_LOG,
AppOpsManager.OPSTR_READ_PHONE_STATE
},
context.getMainExecutor(),
changedListener
);
} else {
Log.e(TAG, "AppOpsManager is not available.");
}
}
// 注销监听器
public void unregisterAppOpsListener(Context context) {
if (context == null || changedListener == null) return;
final AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (appOpsManager != null) {
appOpsManager.stopWatchingActive(changedListener);
}
}
unregisterAppOpsListener(getApplicationContext());
注意事项:
1、一个应用在持续使用权限,不会持续回调
2、只会发一次true,不使用才会再次回调发false
3、和包名没关系,只和权限相关,单个应用使用权限,只会发一次,如果其他应用在调过来相同权限,是会再次触发回调的
4、要判断包名,有些包使用敏感权限是不需要显示的
如果对你有帮忙的话,用你发财的小手点赞收藏一下吧