
Android 11权限适配老项目升级的实战避坑指南当你的老项目终于决定升级到Android 11时那些陈旧的权限代码就像定时炸弹一样随时可能引爆。作为经历过多次系统升级的老兵我深知这种升级过程中的痛苦——尤其是当你的targetSdkVersion还停留在石器时代的时候。本文将带你直击三个最致命的权限变更点用实战经验帮你避开那些让应用崩溃或功能静默失效的深坑。1. 单次授权权限管理的全新游戏规则Android 11彻底改变了位置、麦克风和摄像头权限的授权方式。还记得以前用户只能在始终允许和拒绝之间二选一吗现在系统增加了一个仅限这一次的选项这看似微小的变化却对应用逻辑产生了深远影响。单次授权的核心行为特征临时访问窗口当Activity可见时权限有效转入后台后短时间内仍可访问具体时长由系统决定前台服务例外如果在Activity可见时启动了相关前台服务权限会持续到服务停止随时可撤销用户可以在系统设置中随时撤回授权此时应用进程会被终止// 传统权限请求方式需要调整 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ! PackageManager.PERMISSION_GRANTED) { // 现在这里可能会得到单次授权 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE); }实际案例我们有一个健身应用在升级后突然收到大量用户投诉说跑步轨迹记录不全。原因正是我们假设一旦获得位置权限就会持续有效没有处理单次授权场景。修复方案是在onResume()中检查权限状态并在必要时重新请求。关键提示所有依赖这些权限的功能都需要增加授权状态检查不能假设一次授权永久有效2. 后台位置权限从简单到复杂的进化Android 11将后台位置权限(ACCESS_BACKGROUND_LOCATION)完全独立出来形成了更严格的管控机制。这直接影响了需要持续位置跟踪的应用如运动追踪、家庭安防等场景。新旧行为对比表行为特征Android 10及以前Android 11权限选项始终允许直接包含前后台必须分开请求请求流程可与其他权限同时请求必须单独请求且先有前台权限用户引导直接弹窗跳转系统设置页// 正确的递增请求示例 fun requestLocationPermissions() { when { hasBackgroundLocationPermission() - { // 已有全部权限 } hasForegroundLocationPermission() - { // 只有前台权限请求后台权限 requestPermissions(arrayOf(ACCESS_BACKGROUND_LOCATION), REQ_BACKGROUND) } else - { // 先请求前台权限 requestPermissions(arrayOf(ACCESS_FINE_LOCATION), REQ_FOREGROUND) } } }踩坑记录我们最初尝试同时请求前后台权限结果应用直接崩溃。日志显示系统抛出了SecurityException这正是Android 11的新限制——禁止混合请求后台位置权限与其他权限。3. 软件包可见性那些突然消失的应用这是最隐蔽也最危险的变化。在Android 11上你的应用默认看不见其他应用了这直接影响了分享、支付、跳转等核心功能而且失败时没有任何提示受影响的典型场景检查微信是否安装以便启动分享查询支付宝包信息验证版本获取设备上所有浏览器列表通过包名判断特定应用是否存在!-- 解决方案在AndroidManifest中添加queries声明 -- queries !-- 明确声明需要交互的包名 -- package android:namecom.tencent.mm / !-- 微信 -- package android:namecom.eg.android.AlipayGphone / !-- 支付宝 -- !-- 或者通过intent-filter声明 -- intent action android:nameandroid.intent.action.SEND / data android:mimeTypeimage/* / /intent /queries血泪教训我们的应用有一个分享到微博的功能在测试时一切正常因为测试机安装了开发工具。但上线后用户完全无法使用日志显示queryIntentActivities返回空列表。根本原因就是缺少包可见性声明而startActivity()调用却依然能工作这种静默失败最危险。4. 其他不容忽视的权限细节除了上述三大变更Android 11还引入了一些容易被忽略但同样重要的权限调整前台服务类型强化!-- 访问麦克风或摄像头的前台服务必须声明类型 -- service android:name.RecorderService android:foregroundServiceTypemicrophone|camera /权限自动重置// 检查用户是否开启了自动重置 if (Build.VERSION.SDK_INT Build.VERSION_CODES.R) { boolean isWhitelisted getPackageManager().isAutoRevokeWhitelisted(); if (!isWhitelisted) { // 引导用户前往设置页 Intent intent new Intent(Settings.ACTION_AUTO_REVOKE_PERMISSIONS); intent.setData(Uri.fromParts(package, getPackageName(), null)); startActivity(intent); } }电话权限细分!-- 获取电话号码需要新增专门权限 -- uses-permission android:nameandroid.permission.READ_PHONE_NUMBERS /5. 实战检查清单为了确保老项目平稳过渡建议按照以下步骤系统性地检查权限相关代码全局搜索权限相关代码# 在项目目录下执行 grep -r requestPermissions( app/src/ grep -r checkSelfPermission( app/src/重点检查三类敏感权限位置权限ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION麦克风权限RECORD_AUDIO摄像头权限CAMERA验证包可见性影响所有使用PackageManager.queryIntentActivities()的地方所有显式检查其他应用是否安装的逻辑分享、支付等跨应用交互功能测试边界场景授予单次授权后转入后台拒绝两次权限请求后的表现长时间未使用应用的权限自动重置兼容性测试工具# 启用特定变更进行测试 adb shell am compat enable FORCE_SCOPED_STORAGE com.your.package adb shell am compat enable FORCE_PACKAGE_VISIBILITY com.your.package在经历了三个老项目的Android 11升级后我发现最耗时的不是实现新功能而是找出那些基于旧版系统假设的隐蔽代码。特别是那些没有崩溃但功能异常的情况往往需要结合用户反馈和详细日志分析才能定位。建议在升级前先建立完善的监控体系确保能及时发现生产环境中的权限相关问题。