随着信息化技术的普及,移动应用在迅速改变着人们的生活方式。作为数字生活的载体,智能设备的演进带动了数据处理技术的不断成熟,这使得应用对用户信息的掌控日趋深入。与此同时,人们的隐私保护意识也越来越强,希望在享受移动应用带来的无限便利之余,也能保护自己的隐私不受侵犯。因此,人们会更青睐那些能从操作系统层面对用户和数据提供保护的平台。 本文将向您介绍关于 Android 在隐私方面的变化和最佳实践,帮助您主动为用户提供优秀的隐私保护。同时我们还有几个关于未来 Android 版本的概念构想与您分享。
隐私保护三原则
我们在设计 Android 之初就充分考虑了对用户隐私权的保护,并且在最近的版本中将这一理念进一步强化,进而在保护用户信息安全方面取得了更加显著的进步。我们一如既往地关心用户的隐私权,这份执着背后是以下三个核心原则:
隐私保护最佳实践
基于隐私保护三个核心原则,我们会持续为您提供各种各样的工具和指导,帮助您在应用中高效地集成隐私保护功能。这里要向您分享的是在移动应用开发中可以考虑的三个最佳实践,您会了解如何提升隐私访问的透明度,了解如何在尊重用户选择权的前提下提供隐私访问的选项,以及了解如何通过最小化隐私访问尽可能减少不必要用户数据的获取。
关注数据访问
您需要考虑的第一个最佳实践是要仔细斟酌应用对用户数据的访问。一方面是由于 Android 12 让用户更直观地看到自己的隐私如何被访问,另一方面则是出于您尊重用户意愿的考量。应用访问传感器时的系统提示
应用的隐私数据访问记录
我们常常收到用户的反馈,他们希望了解应用究竟使用了哪些数据。对此我们做出了一些努力,全新的隐私信息中心让用户可以通过一个简单清晰的时间线视图来了解到过去 24 小时中,哪些应用访问了设备的麦克风、摄像头和地理位置数据。另外,用户还可以查看到应用是否在过去 24 小时里使用其他运行时权限访问过相关数据。
应用的数据使用说明
应用读取剪贴板时的通知
每当有应用从剪贴板读取数据时,Android 都会通知用户。每当应用调用 ClipboardManager#getPrimaryClip() 方法时,Android 会判断写入和读取剪贴板数据的是不是同一个应用,当两者来源不同时,系统会通过一个消息框来提示用户;当两者来自同一个应用时,则不会产生这样的提示。所以我们建议您的应用首先调用 ClipboardManager#getPrimaryClipDescription() 方法来获取剪贴板中数据的基本信息,并根据其类型判断是否需要进一步读取,从而最大限度减少对剪贴板数据的访问。另外,我们还建议您不要随意访问剪贴板,如果有必要,也应该在用户知情和许可的前提下进行。
为更加透明的隐私访问做好准备
为了更好支持 Android 12 带来的隐私透明特性,我们建议您仔细审查应用的代码是否还存在意外的隐私访问操作。您可以借助审计 (auditing) API 来更好地发现潜在的隐私数据读取操作以及第三方 SDK 对隐私数据的访问。这个 API 可以在您的应用访问敏感数据时调用一个应用内的回调函数,并向其提供所访问的数据类型,这样您就可以轻松地发现应用在何时、何种情况下读取了隐私数据。
<activity android:name="DataAccessRationaleActivity"
android:permission="android.permission.START_VIEW_PERMISSION_USAGE"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/>
<action android:name="android.intent.action.VIEW_PERMISSION_USAGE_FOR_PERIOD"/>
intent-filter>
activity>
上面的代码展示了您添加权限 intent 时需要进行的配置。这段代码在您的应用中添加了一个 activity,它可以在启动时告知用户为什么要访问数据。您需要把 android:permission 属性设置为 START_VIEW_PERMISSION_USAGE。如果您的应用是针对 Android 12 进行构建的,那么还需要添加 android:exported="true" 属性。接着添加一个 intent-filter 标签,随后根据您的需要,分别将 android.intent.action.VIEW_PERMISSION_USAGE (在应用的权限管理界面显示) 和 android.intent.action.VIEW_PERMISSION_USAGE_FOR_PERIOD (在隐私访问面板显示) 添加到这个标签里。这样一来,用户就可以在您的应用名称旁看到一个与应用的 intent-filter 对应的图标。
综上所述,在开发应用时,对于数据访问需要注意以下几点:
尊重用户选择
我们要分享的第二个最佳实践关乎着用户的选择。Android 用户可以自行掌控哪些应用可以访问他们的敏感数据,以及这些数据被应用访问的程度。对于开发者来说,掌握好这个度非常重要。
研究表明,用户对应用需要访问数据的原因了解得越充分,那么他们认可这些访问的可能性就越大。您需要通过提供安全的默认参数来平衡用户的掌控权和应用的访问权限,所以您应该向用户提供一些易于理解的选项,并尊重他们的意志。
更细致的位置权限选项
我们在 Android 12 中引入了粒度更细的位置权限选项,使得用户可以自行决定是否只向应用提供粗略的位置信息。我们建议您仔细检查应用中所有需要访问位置信息的用例,如果精确的定位不是必须的,请改为申请 ACCESS_COARSE_LOCATION 权限。
无论何种情况下,您都应该具体地向用户说明为什么需要访问位置信息,并且按照具体的精度需求逐渐向用户申请更精确定位信息的访问权限。同时,您需要考虑到用户仅允许应用获取粗略位置的情况,不能因为位置信息不精确就拒绝让用户继续使用。
如下示例代码包含了两个功能,其中一个是只需要访问大概位置,而另一个则是需要获取精确定位。当用户给予应用获取大致位置的权限时,您需要通过 shouldShowRequestPermissionRationale API 来检查是否需要向用户显示必要的权限申请说明。如果返回了 true,则需要展示您的说明,同时显示申请大致位置的弹框 (请求 ACCESS_COARSE_LOCATION 权限)。
// 请求 ACCESS_COARSE_LOCATION 权限
requestPermissions(
Context,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
REQUEST_CODE
)
if (grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// ACCESS_COARSE_LOCATION 权限已获授权。
}
当用户以后用到需要获取精确定位的功能时,您就可以通过向用户显示申请更精确位置信息的弹框来获得 ACCESS_FINE_LOCATION 权限了。您同样需要确保用户了解您的位置用例后再发起请求。
// 请求 ACCESS_FINE_LOCATION 权限
requestPermissions(
Context,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_CODE
)
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// ACCESS_FINE_LOCATION 权限已获授权。
}
全局权限开关
Android 12 中引入了这样两个开关,分别对应摄像头和麦克风的全局访问:
此外值得一提的是,我们在这次更新中还增加了对运动传感器采样率的限制 (200Hz 以内)。
通知显示权限
我们常常听到用户关于设备上通知过多的抱怨,所以我们在新版本中,要求应用需要向用户申请通知显示权限,只有当用户希望或允许收到通知时,应用才可以向用户发送通知。
您可以通过 Notification.areNotificationsEnabled API 或者 PermissionChecker 来检查应用是否已经获得了通知权限。申请通知权限的方法与申请其他权限相同,您不需要做额外的调整。 这里给您补充了一些需要注意的事项:// 请求权限后向用户发送通知
requestPermissions(
Context,
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
REQUEST_CODE
)
在访问数据前,让用户充分了解您读取数据的原因;
做好用户和系统拒绝权限时的操作,当用户二次拒绝时,您应该尊重用户的意愿;
按需逐级获取隐私数据,不要一次性申请所有权限;
当用户拒绝或是撤销某项权限时,您需要让应用能无缝回退到无需权限即可运行的状态。
最大程度减少权限使用
第三个最佳实践是最大程度减少权限的使用。一方面您应当对用户的意愿和选择保持尊重,另一方面您还可以使用 Android 的替代 API,在简化敏感数据访问的同时提供更好的隐私控制。以下几个方案可以帮助您最大限度减少数据访问。
使用新的附近设备访问权限
可穿戴设备在最近几年发展迅猛,大量的应用需要与这些设备进行交互。在以前,应用必须先申请位置访问权限才能与配套设备进行蓝牙连接。开发者们向我们反馈了这种不恰当的设计,尤其是当应用只需要获取蓝牙访问权限而不需要获得设备位置的时候。过度的权限申请也使得用户对应用的行为正当性产生怀疑,这些反馈敦促着我们改进权限的对应关系。
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
当您切换到构建 API 31 的应用时,可以在上述权限声明的基础上添加一个 maxSDKVersion 属性:
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
随后,您需要添加 BLUETOOTH_SCAN 权限声明,并且使用 neverForLocation 标记来向系统说明您不会使用这个权限来推算设备的位置信息。同时您需要声明 BLUETOOTH_CONNECT 权限来与蓝牙设备交互、通过 BLUETOOTH_ADVERTISE 来将当前设备信息广播给附近的蓝牙设备。
为应用设置智能应用休眠功能
在 2020 年发布 Android 11 时,我们同时推出了自动重置权限的功能,并且通过 Google Play 服务的更新将这项功能带到了运行 Android 6 及以后版本系统的设备上。当某个应用有数月没有被使用时,Android 会自动撤销该应用的某些授权。从这项更新发布以后的情况分析,仅 14 天内已经有 850 万应用的权限因长久未使用被撤销了。所以建议您总是要先检查权限是否还存在,避免因为系统撤销权限而产生错误。
2021 年,在权限自动重置功能的基础上,我们推出了智能应用休眠功能。Android 会自动将长期没有使用的应用进行休眠,从而优化设备存储、改善性能和提高安全性。系统不仅会撤销用户此前的授权,还会强制停止应用,收回内存、存储空间及其他临时资源。
当应用进入休眠后,系统会阻止应用在后台运行任务,或者接收推送通知。而结束应用休眠的方式也非常简单,用户只需要启动应用即可。与权限自动重置类似,应用进入休眠时,用户会收到相应的通知,同时用户也可以在设置中选择关闭休眠。
用好分区存储策略
Android 10 的发布首次引入了分区存储机制,它为隐私保护提供了一种新的存储方案。随着后续几个版本的迭代更新,其他应用不再能访问某个应用的外部目录了。您也可以在不请求任何权限的基础上添加和编辑本应用的文件,或是在用户知情同意的前提下编辑第三方应用产生的文件。而如果您将文件添加到共享存储目录中,则无需任何权限申请操作。
- 使用照片选择器
未来我们会发布一个照片选择器 (Photo Picker),它可以无需任何请求即可读取用户选择的照片或视频。您可以在其中选择设备本地存储的照片或视频,也可以访问到来自 Google Photos 等云提供商的照片或视频。这个新的选择器会替换以前申请权限的访问方式,简化应用的权限声明。
通过 Google Play 系统更新,Android 11 及以后的设备都可以使用这个新的照片选择器。下面是一个使用这款新照片选择器的例子:
如果您需要在应用中唤起这个选择器,需要启动 ACTION_PICK_IMAGES Intent,然后指定可选取媒体的最大数量和支持的文件类型。当用户选中文件后,可以通过 clipData 属性读取各个文件的 URI,然后使用 ContentResolver 来读取文件内容。为了能够兼容更早前的设备,我们还计划发布一个支持库,让应用在支持时使用新的照片选择器,不支持时使用存储访问框架简化对文件元数据、内容的读取。// 要发送的 intent
val intent = Intent(MediaStore.ACTION_PICK_IMAGES).apply {
putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 15)
putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*"))
}
// 处理返回的 intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
// 遍历所有的 URI 结果
for (i in 0 until data.clipData.itemCount) {
val uri = data.clipData.getItemAt(i).uri
val inputStream = contentResolver.openInputStream(uri)
}
}
- 新的存储权限划分策略
此外,我们还在努力通过新的存储空间功能为用户带来更清晰、为开发者带来更精准的存储权限划分粒度。比如在下个版本中引入的 READ_IMAGES 权限允许您读取共享存储空间上的所有图片和视频文件,而 READ_AUDIO 可用于读取所有的音频文件 (包括 .m3u 播放列表)。 借助分区存储,您应用访问自己分区内的文件时不需要申请访问权限;位于共享存储空间的非媒体文件仍然可以通过存储访问框架获得。如果要在您的 manifest 中包括这些变化,您可以参照这个例子:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="31"/>
<uses-permission android:name="android.permission.READ_IMAGES"/>
<uses-permission android:name="android.permission.READ_AUDIO"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
请注意,MANAGE_EXTERNAL_STORAGE 权限可以用于那些核心功能就是要与大量的文件进行交互的应用。但此权限受限于 Google Play 关于使用 "所有文件访问权限" 的政策。
以上这些建议概括如下几点:
开发者可降级权限
一些应用可能不再需要某些之前由用户授予过的权限,这些权限曾用于开启某项特定功能或保留旧的 Android 版本中的敏感权限。在 Android 13 中,我们提供了新的 API,让您的应用通过降级以前被授予的运行时权限来保护用户隐私。
感谢您的阅读,希望我们可以共同构建一个能够让用户安心使用的操作系统和应用生态。
原文标题:保护 Android 用户隐私,从这些事做起
文章出处:【微信公众号:谷歌开发者】欢迎添加关注!文章转载请注明出处。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !