隐私策略更新 | Android 11 应用兼容性适配

image

作者 / Fred Chung

Android 11 的最终版本已正式发布!该版本延续了之前发行版本里不断改进的隐私策略,为用户提供更加完善的控制机制和透明度,并帮助应用更好地处理自身的数据。

其中很多优化将当前安全策略的最佳实践应用于最近的 Android 发行版本中(它们并不仅仅针对 Android 11)。在本文中,我们将以下面四个最佳实践作为切入点,助力您的应用设计与时俱进,并计划开始进行兼容性测试。

  1. 处理内容 URI 分享
  2. 递增式权限申请
  3. 在前台访问敏感数据
  4. 使用可重置的标识符

为其它应用提供合适的 URI 权限

随着 Android 11 中 软件包可见性 的策略更新,目标 API 级别为 30 的应用对设备上已安装的其它软件包默认仅拥有受限的可见性。这样的设计旨在为应用“查看”设备上的其它已安装软件包时,提供更好的“问责”制度。

为了简化迁移,对于常见的应用场景,我们提供了 实现指南。通常,应用需要具备对其它已安装软件包的可见性(通过 PackageManager API 验证)才可以和其它软件包进行交互。该特性通常应用于诸如:启动服务,或者访问属于其它应用的 Content Provider。

您访问 Content Provider 的模式可能不是通过发送显式 intent 到某个特定的应用,而是通过发送隐式 intent。这样的话,您无法预判接收端应用(最终处理这个 intent 的应用)的目标 API 等级,而这个等级决定了接收端应用是否会受到 Android 11 中引入的应用包可见性限制的影响。

为了保证接收端应用能够"查看"您的软件包,从而能够访问任何共享的 URI,您需要在 intent 中添加 FLAG_GRANT_READ_URI_PERMISSION 和/或者 FLAG_GRANT_WRITE_URI_PERMISSION。请注意,写入权限并不包含读取访问权限。当被 intent 触发以后,接收端应用会被授予对相关 URI 的临时访问权限。

val shareIntent = Intent(Intent.ACTION_VIEW).apply {
    flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    data = //需要向其它应用共享的 Content Uri
}

随着应用的目标 SDK 版本的更新(即使更新到 Android 11 之前的版本),请您特别关注涉及到与其它应用分享 Content Provider 访问权限的用例,并确保授予适当的 URI 权限。无论哪个应用是这 content provider 的拥有者,这个策略都管用。

通常,我们要将数据访问程度限制为当前任务所需的水平,如果您遵循了这个最佳实践,您的 Content Provider 访问权限应该是按照个别 URI 模式 设定的。只要做到这点,您的 Content Provider 就已经可以兼容 Android 11 了!

递增式申请权限

Android 用户研究报告 显示,在请求获取用户的授权时,那些符合用户期望值的请求更有可能被获准。因此,当您应用中的某个功能需要这些权限时,最佳实践是在上下文中 请求权限

用户授予权限的原因排行。来源:Android 用户研究报告

△ 大多数用户会为了使用某个特定的功能而选择同意授权

△ 大多数用户会为了使用某个特定的功能而选择同意授权

这项策略对于敏感权限尤其适用,如位置访问权限。从 Android 10 开始,平台引入了细粒度的位置模型,区分了前台和后台位置访问。大多数位置场景仅需要前台访问,比如当用户在操作 Activity 的时候。

事实上,Google Play 已经出台了相关政策限制不必要的后台位置访问。要检查您的应用可能在哪些地方从后台访问位置,请参阅:后台访问位置信息文档。如果您的应用需要后台位置权限,比如地理围栏应用,请确保后台位置对您的功能设计是不可或缺的。

对于适用的应用,需要先申请前台位置权限,然后在稍晚些再申请后台位置权限。这种方法为用户提供了控制权限授予级别的选择。此外,您还可以有策略地显示一个权限申请的说明,或者设计一个合理的交互界面,为用户提供更多信息,以说明用户授予位置权限之后所获得的的功能提升。

image

Android 11 要求面向 API 级别为 30 的应用使用递增式位置权限请求。任何同时申请前台位置权限(无论是粗略位置还是精确位置)和后台位置权限的请求都会被忽略并且返回如下错误信息。

E/GrantPermissionsActivity: Apps targeting 30 must have foreground permission before requesting background and must request background on its own.

请注意在 requestPermissions() API 请求的任何其它非位置权限也会同时被忽略。

因为 requestPermissions API 接受一个由所需权限组成的数组作为参数,您现有的代码可能已有了同时申请多个权限的情况(如下所示),因此这里我们鼓励大家检查和审核一下自己的代码,如果代码修改影响到用户交互,则需要按需进行相应设计。

如果启用了 ActivityCompat 或者框架 API:

requestPermissions(
        arrayOf(
            // 不要同时申请前台位置权限和后台位置权限
            // 因为所有同时申请的权限都会被忽略
            // 而是通过增量式请求位置权限
            android.Manifest.permission.ACCESS_COARSE_LOCATION,         
            android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,

            ...)

        )

同样地,如果启用了 Jetpack Activity 库

// 使用 Activity 库
val requestPermissionsLauncher =
                registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
                    map: MutableMap<String, Boolean> ->
                        ...
                }
...

requestPermissionsLauncher.launch(
        arrayOf(
            // 不要同时申请前台位置权限和后台位置权限
            // 因为所有同时申请的权限都会被忽略
            // 而是通过增量式请求位置权限
            android.Manifest.permission.ACCESS_COARSE_LOCATION,         
            android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,

            ...)
    )

合理访问位置、麦克风和相机

Android 的系统设计支持公开透明地访问敏感数据,比如麦克风、相机和位置。例如,应用在前台的时候,也就是用户能看到应用界面的时候,才可以使用麦克风和相机。这样可以提高公开透明性,所以用户可以在知情的情况下启用相关特性。

如果您的应用包含访问敏感数据的前台服务,请确认应用场景中包含直接的用户交互,使用户可以控制所执行的任务。例如,在一个视频会议应用中,您可以使用一个前台服务来支持活跃的会议进程,其中会涉及到访问麦克风和相机。其中应该包含一个对于用户可见的用于启动和停止会议进程的操作,也就是该前台服务。

此外,您的应用必须正确设置 foregroundServiceType 属性来表明位置、麦克风或者相机的用途。这样可以为应用增加系统可见性,同时在 Android 11 中也是必须配置的属性。更多信息请访问:Android 11 中的前台服务

您可能需要在 AndroidManifest 中声明多种数据类型的用途。

android:foregroundServiceType = "microphone location camera"

如果您的功能是基于 WorkManager 的 长时间运行的 worker 来实现的,那么它实际上是运行在叫做 SystemForegroundService 的前台服务上。您应该在应用的 AndroidManifest 中包含适合的前台服务类型,它会同 Jetpack 库的 AAR AndroidManifest 文件 合并。

在应用的 AndroidManifest 中添加下面的声明,并且在其中定义所需的前台服务类型。

<service
    android:name="androidx.work.impl.foreground.SystemForegroundService"
    android:foregroundServiceType="location|microphone"//这里选择和您的应用相关的服务类型
    tools:node="merge" />

当您需要将 worker 以前台服务运行时,您需要将合适的前台服务类型传入 ForegroundInfo 对象。传入的服务类型必须和上面在 AndroidManifest 中添加的声明一致或者是其子集。

setForeground(
    ForegroundInfo(NOTIF_ID,
        notification.build(),
        // 前台服务类型
        ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION or ...)
)

弃用不可重置标识符

Android 系统使用了一些不可重置的硬件标识符,比如 IMEI 以支持各种操作系统功能。出于隐私方面的考虑,这些相对“强大”的持久性和唯一性的标识符不适合用于大部分应用场景。

从 Android 10 开始,系统对不可重置的设备标识符 实施了限制。比如,只有带有 READ_PRIVILEGED_PHONE_STATE 权限的系统应用才可以通过 getSimSerialNumber() 方法访问 SIM 卡的硬件标识符。在 Android 11 中,操作系统对 getIccId() 方法也增加了类似的限制来进一步 限制访问权限,现在该方法仅返回空字符串。

对于需要使用 SIM 卡信息作为唯一性标识的应用,需要在 Android 11 里进行“空字符串”的兼容性检查。一个替代方案是使用 getSubscriptionId() 方法,它会针对设备上指定的 SIM 卡信息返回一个以数字 1 开头的唯一索引值,也就是说,如果同一张 SIM 卡被重新安装到设备上的话,它会保持之前的订阅标识符,除非设备恢复出厂设置。更多请参阅:唯一标识符最佳做法

平台和 Google Play 服务为应用提供了一些其它的 标识符,提供各种唯一性、可重置性和有作用域限制的标识符,适用于各种不同的应用场景。更多请参阅:唯一标识符最佳做法

以上内容能够帮助大家更快更新适配最新的 API ,并设计出对隐私更友好的应用。更多资源请参阅:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353