一、Android 14/15 隐私新特性全景
说实话,每次 Android 大版本更新,最让我头疼的就是隐私合规这块。不是技术难,而是变化太快。我记得 Android 13 刚适配完,14 又来了,15 紧接着跟上。今天我就把这三个最关键的隐私特性——照片选择器、后台活动限制、通知权限和精确位置权限变更——给你讲透。
先看一张总览图,了解这几个特性在隐私体系中的位置:
二、照片选择器:告别 READ_MEDIA_IMAGES
这个改动其实挺大的。以前我们要读取用户相册,得申请 READ_EXTERNAL_STORAGE 或者 READ_MEDIA_IMAGES 权限。但从 Android 14 开始,Google 强烈推荐用系统自带的照片选择器。
2.1 为什么推荐照片选择器?
说白了,就是让用户自己选,而不是你直接扫整个相册。你想想看,一个修图 App 要读你所有照片,合理吗?其实大部分场景只需要用户选的那一两张。
我在项目中遇到过,有些团队为了省事,直接申请了 READ_MEDIA_IMAGES,结果审核被拒。Google Play 现在对这类权限审查特别严,没有充分理由基本过不了。
2.2 适配代码示例
// 使用照片选择器(Android 14+)
val pickMedia = registerForActivityResult(
ActivityResultContracts.PickVisualMedia()
) { uri: Uri? ->
uri?.let {
// 用户选择了照片,处理 URI
imageView.setImageURI(it)
}
}
// 启动选择器
pickMedia.launch(PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.ImageOnly
))
// 如果需要视频,可以这样
pickMedia.launch(PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.VideoOnly
))
takePersistableUriPermission 申请持久化权限。
2.3 兼容性处理
如果你的 App 还要支持 Android 13 以下,怎么办?我建议做降级处理:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// 使用照片选择器
pickMedia.launch(...)
} else {
// 回退到传统方式,申请 READ_EXTERNAL_STORAGE
requestStoragePermission()
}
三、后台活动限制:别想偷偷启动 Activity
这个改动我印象特别深。以前有些流氓 App 会在后台偷偷弹广告,或者拉起其他 Activity。Android 14 直接把这个口子堵死了。
3.1 限制规则
从 Android 14 开始,App 在后台时不能随意启动 Activity。除非满足以下条件之一:
- App 有一个可见的窗口(比如前台服务通知)
- 用户主动与 App 交互(比如点击通知)
- 系统发出的 PendingIntent(比如闹钟、来电)
- App 拥有
SYSTEM_ALERT_WINDOW权限
3.2 避坑指南
我曾经踩过一个坑:App 收到推送后,想在后台直接打开一个 Activity 展示详情。结果在 Android 14 上直接崩溃,日志显示 BackgroundActivityStartNotAllowedException。
正确的做法是:
// 错误做法:直接在广播接收器里启动 Activity
// Intent intent = new Intent(context, DetailActivity.class);
// context.startActivity(intent); // 会崩溃!
// 正确做法:通过通知的 PendingIntent 启动
val notificationIntent = Intent(context, DetailActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
context,
0,
notificationIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
// 构建通知时传入 PendingIntent
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setContentIntent(pendingIntent)
.build()
四、通知权限:用户终于可以关掉你的通知了
这个改动其实从 Android 13 就开始了,但 Android 14/15 进一步强化了。现在用户安装 App 后,系统会弹窗询问是否允许通知。如果用户拒绝,你的通知就发不出去了。
4.1 权限声明
首先,你需要在 Manifest 中声明权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
4.2 运行时申请
// 检查通知权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
// 申请权限
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
NOTIFICATION_PERMISSION_REQUEST_CODE
)
}
}
4.3 适配建议
我个人习惯是在用户第一次需要通知功能时再申请权限,而不是一启动就弹窗。比如用户点击「开启消息提醒」按钮时再申请,这样成功率更高。
五、精确位置权限:用户可以选择「大概位置」
这个改动对地图、外卖、打车类 App 影响最大。以前用户要么给精确位置,要么不给。现在用户可以选择只给「大致位置」(精度约 500 米)。
5.1 权限变更
| 权限 | 说明 | Android 14/15 变化 |
|---|---|---|
| ACCESS_FINE_LOCATION | 精确位置(GPS 级别) | 用户可选「大致位置」替代 |
| ACCESS_COARSE_LOCATION | 大致位置(基站/WiFi 级别) | 无变化 |
| ACCESS_BACKGROUND_LOCATION | 后台位置访问 | 需单独申请,审核更严 |
5.2 适配代码
// 申请精确位置权限
val locationPermissionRequest = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
when {
permissions.getOrDefault(
Manifest.permission.ACCESS_FINE_LOCATION, false
) -> {
// 用户授予了精确位置
}
permissions.getOrDefault(
Manifest.permission.ACCESS_COARSE_LOCATION, false
) -> {
// 用户只授予了大致的置
}
else -> {
// 用户拒绝了所有位置权限
}
}
}
locationPermissionRequest.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
5.3 避坑指南
我曾经遇到一个外卖 App,用户只给了大致位置,结果 App 直接崩溃了——因为代码里强转 Location.getAccuracy() 时没做空判断。后来我加了个兜底逻辑:如果精度不够,就提示用户手动输入地址。
六、总结与适配清单
好了,这四个特性讲完了。我最后给你列个检查清单,方便你对照适配:
- 照片选择器:替换
READ_MEDIA_IMAGES为系统照片选择器,做好降级兼容 - 后台活动限制:所有后台启动 Activity 改为通过通知 PendingIntent
- 通知权限:声明
POST_NOTIFICATIONS,在合适时机申请 - 精确位置权限:支持用户选择「大致位置」,做好精度不足的兜底
适配这些特性,说白了就是尊重用户的选择权。你想想看,用户把照片、位置、通知这些敏感权限交给你,你得对得起这份信任。合规不是负担,而是产品长期发展的基石。
公众号:蓝海资料掘金营,微信deep3321