爱笑的姑娘|拖不得了,Android11真的要来了,最全适配实践指南奉上( 七 )


官方说明说的很清楚了 , 而且只要应用遵循有关在运行时请求权限的最佳做法 , 也就是每次需要调用权限的时候都会去判断 , 那么就不会有什么问题 。
如果需要关闭这个功能怎么办呢?只有引导用户去设置页面关闭了 , 可以调用包含Settings.ACTION_APPLICATION_DETAILS_SETTINGS action的 Intent将用户定向到系统设置中应用的页面 。
怎么检查应用是否停用自动重置功能呢?调用 PackageManager的isAutoRevokeWhitelisted()方法 。 如果此方法返回 true , 代表系统不会自动重置应用的权限 。
前台服务类型
从 Android 9 开始 , 应用仅限于在前台访问摄像头和麦克风 。 为了进一步保护用户 , Android 11 更改了前台服务访问摄像头和麦克风相关数据的方式 。 如果您的应用以 Android 11 为目标平台并且在某项前台服务中访问这些类型的数据 , 您需要在该前台服务的声明的 foregroundServiceType 属性中添加新的 camera 和 microphone 类型 。
举例 , 如果应用某项前台服务需要访问位置信息、摄像头和麦克风 , 那么就这样添加:

适配Android11手机此模块的修改内容针对所有项目在Android11手机上存在的改动 , 与targetSdkVersion无关 。
数据访问审核 ?
为了让应用及其依赖项访问用户私密数据的过程更加透明 , Android 11 引入了数据访问审核功能 。 借助此流程得出的见解 , 您可以更好地识别和纠正可能出现的意外数据访问 。
哪些范畴属于用户私密数据呢?其实就是危险权限的调用 , 所以这个功能就是提供了可以监听危险权限调用的监听 。 主要涉及到的方法是AppOpsManager.OnOpNotedCallback 。 无论是应用本身 , 还是依赖库或者SDK中的代码 , 只要访问到私密数据(危险权限) , 都会回调给我们 。
对于工程庞大或者使用较多SDK的工程比较适合用上这个功能 , 让自己应用的私有数据管理更加透明规范 , 否则对于私有数据的使用和管理并不全面和方便 。 而且还可以对权限使用添加归因 , 也就是一个tag , 标志权限用到了什么地方 。 方便回调的时候知晓哪里使用了私有数据 。
来:
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_test1)//创建归因(attribute)attributionContext = createAttributionContext("shareLocation")//监听事件val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {private fun logPrivateDataAccess(opCode: String, attributionTag: String, trace: String) {Log.i(TAG, "Private data accessed. " +"Operation: $opCode\n " +"Attribution Tag:$attributionTag\nStack Trace:\n$trace")}override fun onNoted(syncNotedAppOp: SyncNotedAppOp) {syncNotedAppOp.attributionTag?.let {logPrivateDataAccess(syncNotedAppOp.op,it,Throwable().stackTrace.toString())}}override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) {syncNotedAppOp.attributionTag?.let {logPrivateDataAccess(syncNotedAppOp.op,it,Throwable().stackTrace.toString())}}override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) {asyncNotedAppOp.attributionTag?.let {logPrivateDataAccess(asyncNotedAppOp.op,it,asyncNotedAppOp.message)}}}//开启私密数据监听val appOpsManager =getSystemService(AppOpsManager::class.java) as AppOpsManagerappOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback)btn1.setOnClickListener {getLocation()}}fun getLocation() {val locationManager = attributionContext.getSystemService(LocationManager::class.java) as LocationManagerif (!checkPermission()) {return}val location: Location? = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)if (location != null) {showToast("${location.latitude}")}}