Android 权限体系详解:普通权限、危险权限、工控固件预置权限、静默授权

发布时间:2026/7/25 23:14:42
Android 权限体系详解:普通权限、危险权限、工控固件预置权限、静默授权 Android 权限体系详解普通权限、危险权限、工控固件预置权限、静默授权权限这玩意就像你家门锁——普通权限是厕所门装了但不锁危险权限是保险柜必须你点头才能开而工控固件的预置权限嘛……那是把钥匙焊死在门把手上。一、Android 权限模型演进Android的权限体系经历了两个重要的分水岭。Android 6.0API 23之前所有权限在安装APP时一次性授予。用户在安装时看到一大串权限列表要么全接受要么别装。这种做法对用户来说完全没有控制力——很多APP要了短信权限就为读个验证码但谁知道它在后台有没有偷看你的隐私。Android 6.0 之后引入运行时权限机制。普通权限Normal Permissions仍然安装时自动授予危险权限Dangerous Permissions必须在运行时弹窗询问用户。这个改动让用户终于有了按需授权的权利。对于工控场景运行时权限弹窗是个麻烦——设备可能没有屏幕或者运行在无人值守模式弹窗没人点允许APP就卡住了。所以工控领域需要特殊的权限管理策略这就是我们后面要讲的固件预置和静默授权。二、普通权限 vs 危险权限2.1 什么是普通权限普通权限是指那些不会直接威胁用户隐私和安全的权限。只需要在AndroidManifest.xml中声明即可系统自动授予不需要运行时弹窗。工控项目常用的普通权限!-- 网络权限必须 --uses-permissionandroid:nameandroid.permission.INTERNET/uses-permissionandroid:nameandroid.permission.ACCESS_NETWORK_STATE/uses-permissionandroid:nameandroid.permission.ACCESS_WIFI_STATE/uses-permissionandroid:nameandroid.permission.CHANGE_WIFI_STATE/!-- 震动控制 --uses-permissionandroid:nameandroid.permission.VIBRATE/!-- 前台Service --uses-permissionandroid:nameandroid.permission.FOREGROUND_SERVICE/!-- 开机自启 --uses-permissionandroid:nameandroid.permission.RECEIVE_BOOT_COMPLETED/!-- 保持唤醒 --uses-permissionandroid:nameandroid.permission.WAKE_LOCK/!-- 蓝牙普通的部分 --uses-permissionandroid:nameandroid.permission.BLUETOOTH/uses-permissionandroid:nameandroid.permission.BLUETOOTH_ADMIN/这些权限都在系统的普通权限白名单内声明即授予不用操任何心。2.2 什么是危险权限危险权限是指可能危及用户隐私的权限划分为9个权限组。同一组内只要申请了其中一个权限并被用户批准组内其他权限也自动获得。权限组典型权限工控用途CALENDARREAD_CALENDAR生产计划同步CAMERACAMERA扫码、视觉检测CONTACTSREAD_CONTACTS很少用到LOCATIONACCESS_FINE_LOCATIONGPS定位MICROPHONERECORD_AUDIO声学检测PHONEREAD_PHONE_STATE获取设备信息SENSORSBODY_SENSORS很少用到SMSSEND_SMS告警通知STORAGEREAD_EXTERNAL_STORAGE读写SD卡/U盘工控设备常用的危险权限清单!-- 摄像头 --uses-permissionandroid:nameandroid.permission.CAMERA/!-- 存储读写 --uses-permissionandroid:nameandroid.permission.READ_EXTERNAL_STORAGE/uses-permissionandroid:nameandroid.permission.WRITE_EXTERNAL_STORAGE/!-- 定位 --uses-permissionandroid:nameandroid.permission.ACCESS_FINE_LOCATION/uses-permissionandroid:nameandroid.permission.ACCESS_COARSE_LOCATION/!-- 读取设备信息 --uses-permissionandroid:nameandroid.permission.READ_PHONE_STATE/注意Android 10API 29引入了分区存储Scoped StorageREAD_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE在Android 10上对公共目录的访问受限。如果你需要读写任意目录工控常见需求需要在Manifest中声明applicationandroid:requestLegacyExternalStoragetrue.../applicationAndroid 11及以上则需要使用MANAGE_EXTERNAL_STORAGE权限。三、运行时权限申请流程3.1 基本流程publicclassPermissionHelper{privatestaticfinalintREQUEST_CODE100;publicstaticvoidrequestPermissions(Activityactivity,String...permissions){ListStringneedRequestnewArrayList();for(Stringpermission:permissions){if(ActivityCompat.checkSelfPermission(activity,permission)!PackageManager.PERMISSION_GRANTED){needRequest.add(permission);}}if(!needRequest.isEmpty()){ActivityCompat.requestPermissions(activity,needRequest.toArray(newString[0]),REQUEST_CODE);}}publicstaticbooleanallGranted(int[]grantResults){for(intresult:grantResults){if(result!PackageManager.PERMISSION_GRANTED)returnfalse;}returntrue;}}在Activity中处理回调OverridepublicvoidonRequestPermissionsResult(intrequestCode,String[]permissions,int[]grantResults){super.onRequestPermissionsResult(requestCode,permissions,grantResults);if(requestCode100){for(inti0;ipermissions.length;i){if(grantResults[i]PackageManager.PERMISSION_GRANTED){Log.i(Permission,permissions[i] 已授权);}else{// 被拒绝可以判断用户是否点了不再询问if(!shouldShowRequestPermissionRationale(permissions[i])){// 用户勾选了不再询问引导去设置页面openAppSettings();}}}}}privatevoidopenAppSettings(){IntentintentnewIntent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);intent.setData(Uri.parse(package:getPackageName()));startActivity(intent);}3.2 工控场景的痛点上面的代码依赖用户点击弹窗——但在工控设备上可能出现以下情况设备没有触摸屏只有物理按键设备运行在无人值守模式没有人操作弹窗挡住了工业应用界面影响监控解决方案就是下面要讲的固件预置权限和静默授权。四、工控固件预置权限4.1 系统应用方案如果你的APP作为系统应用预装到设备中可以在AndroidManifest.xml中加上manifestxmlns:androidhttp://schemas.android.com/apk/res/androidpackagecom.example.industrialandroid:sharedUserIdandroid.uid.systemcoreApptrueuses-permissionandroid:nameandroid.permission.REBOOT/uses-permissionandroid:nameandroid.permission.SHUTDOWN/!-- 系统级权限普通APP装不上 --/manifestandroid:sharedUserIdandroid.uid.system需要系统签名platform签名才能生效。编译时用固件对应的platform.pk8和platform.x509.pem签名即可。coreApptrue告诉系统这是一个核心应用提高进程优先级。4.2 privileged 应用从Android 8.0开始Google引入了privileged应用的概念。将APK放到/system/priv-app/目录下可以获取比普通系统应用更高的权限!-- 需要放到 /system/priv-app/ 目录下才能生效 --uses-permissionandroid:nameandroid.permission.INSTALL_PACKAGES/uses-permissionandroid:nameandroid.permission.DELETE_PACKAGES/uses-permissionandroid:nameandroid.permission.WRITE_SECURE_SETTINGS/uses-permissionandroid:nameandroid.permission.MANAGE_EXTERNAL_STORAGE/工控固件开发中把自己APP的APK预置到/system/priv-app/是最佳实践——权限够用、优先级够高、用户也无法卸载。五、静默授权方案如果你的设备没有刷自己固件的条件但至少可以通过adb操作静默授权就可以派上用场。5.1 adb pm grant 命令# 授予所有危险权限不需要用户交互adb shell pm grant com.example.industrial android.permission.CAMERA adb shell pm grant com.example.industrial android.permission.READ_EXTERNAL_STORAGE adb shell pm grant com.example.industrial android.permission.WRITE_EXTERNAL_STORAGE adb shell pm grant com.example.industrial android.permission.ACCESS_FINE_LOCATION adb shell pm grant com.example.industrial android.permission.READ_PHONE_STATE adb shell pm grant com.example.industrial android.permission.WRITE_SETTINGS adb shell pm grant com.example.industrial android.permission.SYSTEM_ALERT_WINDOW一行命令搞定所有权限。工控设备出厂前跑一遍这个脚本APP永远不用弹权限对话框。查看某个APP当前拥有的权限adb shell dumpsys package com.example.industrial|greppermission5.2 批量授权脚本#!/bin/bash# grant_all_permissions.shPACKAGEcom.example.industrialPERMISSIONS(android.permission.CAMERAandroid.permission.READ_EXTERNAL_STORAGEandroid.permission.WRITE_EXTERNAL_STORAGEandroid.permission.ACCESS_FINE_LOCATIONandroid.permission.ACCESS_COARSE_LOCATIONandroid.permission.READ_PHONE_STATEandroid.permission.RECORD_AUDIOandroid.permission.WRITE_SETTINGSandroid.permission.SYSTEM_ALERT_WINDOW)forpermin${PERMISSIONS[]};doechoGranting$perm...adb shell pm grant$PACKAGE$permdoneechoAll permissions granted!这个脚本打包进固件第一次启动时自动执行或者通过APP内的shell执行需要root权限——工控设备root后这都不是问题。5.3 系统签名后反射授权如果拿到了系统签名可以反射调用PackageManager的隐藏方法直接授权publicstaticvoidgrantPermissionSilently(StringpackageName,Stringpermission){try{PackageManagerpmgetPackageManager();MethodmethodPackageManager.class.getMethod(grantRuntimePermission,String.class,String.class,UserHandle.class);method.invoke(pm,packageName,permission,android.os.Process.myUserHandle());}catch(Exceptione){e.printStackTrace();}}注意这个方法需要系统签名才能调用普通签名的APP反射调用会抛SecurityException。六、工控常用权限清单整理一份工控APP的权限声明模板覆盖绝大多数场景!-- 网络通信 --uses-permissionandroid:nameandroid.permission.INTERNET/uses-permissionandroid:nameandroid.permission.ACCESS_NETWORK_STATE/uses-permissionandroid:nameandroid.permission.ACCESS_WIFI_STATE/uses-permissionandroid:nameandroid.permission.CHANGE_WIFI_STATE/!-- 存储 --uses-permissionandroid:nameandroid.permission.READ_EXTERNAL_STORAGE/uses-permissionandroid:nameandroid.permission.WRITE_EXTERNAL_STORAGE/uses-permissionandroid:nameandroid.permission.MANAGE_EXTERNAL_STORAGEtools:ignoreScopedStorage/!-- 硬件外设 --uses-permissionandroid:nameandroid.permission.CAMERA/uses-permissionandroid:nameandroid.permission.RECORD_AUDIO/uses-permissionandroid:nameandroid.permission.BLUETOOTH/uses-permissionandroid:nameandroid.permission.BLUETOOTH_ADMIN/uses-permissionandroid:nameandroid.permission.BLUETOOTH_CONNECT/uses-permissionandroid:nameandroid.permission.BLUETOOTH_SCAN/!-- USB --uses-featureandroid:nameandroid.hardware.usb.host/uses-featureandroid:nameandroid.hardware.usb.accessory/!-- 系统 --uses-permissionandroid:nameandroid.permission.RECEIVE_BOOT_COMPLETED/uses-permissionandroid:nameandroid.permission.WAKE_LOCK/uses-permissionandroid:nameandroid.permission.FOREGROUND_SERVICE/uses-permissionandroid:nameandroid.permission.FOREGROUND_SERVICE_DATA_SYNC/uses-permissionandroid:nameandroid.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS/!-- 定位工控设备 --uses-permissionandroid:nameandroid.permission.ACCESS_FINE_LOCATION/uses-permissionandroid:nameandroid.permission.ACCESS_COARSE_LOCATION/!-- 系统设置 --uses-permissionandroid:nameandroid.permission.WRITE_SETTINGS/uses-permissionandroid:nameandroid.permission.SYSTEM_ALERT_WINDOW/!-- 读取设备信息 --uses-permissionandroid:nameandroid.permission.READ_PHONE_STATE/这份清单基本覆盖了工控设备的所有常见需求。实际项目中根据需要增减即可但网络、存储、前台Service这三项几乎是必选的。七、权限申请完整代码示例/** * 工控APP权限管理器 * 在Service启动时检查并申请所有必要权限 */publicclassIndustrialPermissionManager{privatestaticfinalString[]REQUIRED_PERMISSIONS{Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.READ_PHONE_STATE,Manifest.permission.RECORD_AUDIO};publicstaticbooleancheckAllPermissions(Contextcontext){for(Stringpermission:REQUIRED_PERMISSIONS){if(ContextCompat.checkSelfPermission(context,permission)!PackageManager.PERMISSION_GRANTED){returnfalse;}}returntrue;}publicstaticListStringgetMissingPermissions(Contextcontext){ListStringmissingnewArrayList();for(Stringpermission:REQUIRED_PERMISSIONS){if(ContextCompat.checkSelfPermission(context,permission)!PackageManager.PERMISSION_GRANTED){missing.add(permission);}}returnmissing;}}权限管理是工控APP的基础设施宁愿多声明几个权限也别等线上炸了才想起来漏了某个。如果你的设备是自研固件强烈建议把APP放到/system/priv-app/里然后把权限脚本写进初始化流程——你的APP从此以后再也不用操心权限问题。

相关新闻

最新新闻

日新闻

周新闻

月新闻