使您的应用适应最新的隐私最佳做法

Android 11 final release is here! This release builds upon the privacy improvements in previous releases, and provides even better control and transparency for users as well as guardrails to help apps handle data responsibly.

Android 11最终版本就在这里 ! 此版本以以前版本的隐私改进为基础,并为用户以及护栏提供了更好的控制和透明度,以帮助应用程序负责地处理数据。

Many of these improvements reinforce modern best practices applicable to recent Android releases (they aren’t specific to Android 11!). In this article, we will examine 4 of these best practices to help you future-proof your design and plan for compatibility test cases.

其中许多改进强化了适用于最新Android版本的现代最佳实践(它们并非特定于Android 11!)。 在本文中,我们将研究这些最佳实践中的4种,以帮助您对设计进行过时验证并计划兼容性测试用例。

  1. Handling content URI sharing

    处理内容URI共享
  2. Incremental permission requests

    增量许可请求
  3. Sensitive data access in the foreground

    前台的敏感数据访问
  4. Using resettable identifiers

    使用可重置标识符

Give proper URI permissions to other apps.

给其他应用适当的URI权限。

With the package visibility change in Android 11, apps that target API level 30 will have limited visibility to other installed packages on the device by default. This is designed to provide better accountability for apps to “see” other packages on the device.

随着Android 11中软件包可见性的更改,默认情况下,面向API级别30的应用对设备上其他已安装软件包的可见性将受到限制。 旨在为应用提供更好的责任感,以“查看”设备上的其他程序包。

To ease migration, an implementation guide is available for common use cases. In general, an app must have visibility (verified using the PackageManager API) to other installed packages in order to interact with them. This applies to, for example, starting a service or reading from a content provider that belongs to another app.

为了简化迁移,可为常见用例提供实施指南 。 通常,应用程序必须对其他已安装的软件包具有可见性(已使用PackageManager API进行了验证),以便与它们进行交互。 例如,这适用于启动服务或从属于另一个应用程序的内容提供商那里读取信息。

Your content provider’s access model likely involves sending an implicit intent as opposed to an explicit intent targeted to a given package. As a result, your design cannot assume the receiving app’s target API level, which determines whether the app is subject to package visibility restrictions on Android 11.

内容提供商的访问模型可能涉及发送隐式意图,而不是针对给定包的显式意图。 因此,您的设计无法假定接收应用程序的目标API级别,该级别决定了该应用程序是否受Android 11上程序包可见性的限制。

To ensure that the receiving app has visibility to your package and thus, can access any shared URIs, you need to include the FLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSION URI flag in the intent. Note that the write permission does not imply read access. Upon getting triggered by the intent, the receiving app will be granted temporary access to the URIs.

为了确保接收方的应用程序可以看到您的包裹,从而可以访问任何共享的URI,您需要在意图中包含FLAG_GRANT_READ_URI_PERMISSION和/或FLAG_GRANT_WRITE_URI_PERMISSION URI标志。 请注意,写权限并不意味着读访问。 一旦被意图触发,接收方的应用将被授予对URI的临时访问权限。

val shareIntent = Intent(Intent.ACTION_VIEW).apply {
    flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    data = // Content Uri to be shared with others
}

As you plan to update your app’s target SDK version (even to a version before Android 11), pay attention to cases that involve sharing content provider access with another app and make sure that proper URI permissions are granted. This is applicable regardless of the owner of the content provider.

在计划更新应用程序的目标SDK版本(甚至更新为Android 11之前的版本)时,请注意涉及与其他应用程序共享内容提供者访问权限的情况,并确保已授予适当的URI权限。 这与内容提供商的所有者无关。

Limiting the level of data access to what’s required by the task at hand is generally a good practice. Ideally, your content providers should already have proper sharing permissions for individual URI patterns. If so, your content providers are already compatible on Android 11!

通常,将数据访问级别限制为当前任务所需的级别。 理想情况下,您的内容提供商应该已经对各个URI模式具有适当的共享权限。 如果是这样,您的内容提供商已经在Android 11上兼容!

Request permissions incrementally.

逐步请求权限。

This Android user study shows that users are more likely to grant a permission if the request aligns with their expectations. Therefore it is best practice to request permissions in-context, when a feature in your app needs those permissions.

这项Android用户研究表明,如果请求符合他们的期望,则用户更有可能授予权限。 因此,当应用程序中的功能需要这些权限时,最佳实践是在上下文中请求权限。

Top user permission grant reasons. Source: Android user study.

最高用户权限授予原因。 资料来源: Android用户研究

Image for post

This is especially applicable to sensitive permissions like location access. Since Android 10, the platform has introduced a fine-grain location model which distinguishes foreground from background location access. Most location use cases only need foreground access, such as when the user is engaging with an activity.

这尤其适用于敏感权限,例如位置访问。 自Android 10起,该平台引入了细粒度的位置模型,该模型将前台与后台位置访问区分开来。 大多数位置用例仅需要前台访问,例如在用户参与活动时。

In fact, Google Play has a policy restricting unnecessary background location access. To check where your app might be accessing background location, go through this checklist. If your app requires background location, such as for a geofencing use case, make sure that it’s critical to your functionality.

实际上,Google Play的政策是限制不必要的后台位置访问。 要检查您的应用可能在哪里访问后台位置, 请查看此清单 。 如果您的应用需要背景位置,例如地理围栏用例,请确保它对您的功能至关重要。

For applicable apps, they should request foreground location at first, then background location at a later time. This approach gives users the option to control the level of permission grants. Additionally, you may strategically display an explanation or design an appropriate UX, to provide additional context on how the user may benefit from granting an additional location permission.

对于适用的应用程序,他们应该首先请求前台位置,然后再请求后台位置。 这种方法为用户提供了控制权限授予级别的选项。 此外,您可以策略性地显示说明或设计适当的UX,以提供有关用户如何从授予附加位置权限中受益的附加上下文。

Image for post

Android 11 enforces incremental location permission requests for apps that target API level 30. Any permission requests that include both foreground location (either fine or coarse) and background location permissions will be ignored and result in the following error message.

Android 11对目标API级别为30的应用强制执行增量位置权限请求。 任何同时包含前台位置(精细或粗糙)和后台位置权限的权限请求将被忽略,并导致以下错误消息。

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

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

Note that any other non-location permissions in the same requestPermissions() API call will be ignored as well.

请注意,同一 requestPermissions() API调用 中的任何其他非定位权限 也将被忽略。

As the requestPermissions API takes an array of permissions as an input parameter, you may have existing code that demonstrates the following patterns. You’re encouraged to audit and design an alternative user flow as necessary.

由于requestPermissions API将权限数组作为输入参数,因此您可能已有演示以下模式的代码。 建议您根据需要审核和设计其他用户流程。

If ActivityCompat or frameworks API is used:

如果使用ActivityCompat或frameworks API:

requestPermissions(
        arrayOf(
            // Do not request foreground and background location permissions together,
            // as they will be ignored along with any other permissions in the request. 
            // Request location permissions incrementally instead. 
            android.Manifest.permission.ACCESS_COARSE_LOCATION,         
            android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
            ...)
        )

Likewise, if the Jetpack Activity library is used:

同样,如果使用Jetpack活动库:

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


...
requestPermissionsLauncher.launch(
        arrayOf(
            // Do not request foreground and background location permissions together,
            // as they will be ignored along with any other permissions in the request. 
            // Request location permissions incrementally instead.
            android.Manifest.permission.ACCESS_COARSE_LOCATION,         
            android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
            ...)
    )

Proper access to location, microphone, and camera.

正确访问位置,麦克风和摄像头。

Android’s design encourages transparency when accessing sensitive data such as microphone, camera, and location. For example, apps can only use the microphone and camera while in the foreground, such as when the UI is visible to the user. This improves transparency, so users can make an informed decision on enabling related features.

Android的设计可提高访问敏感数据(如麦克风,摄像头和位置)时的透明度。 例如,应用程序只能在前景中使用麦克风和摄像头,例如当用户可见UI时。 这提高了透明度,因此用户可以在启用相关功能方面做出明智的决定。

If your app has existing foreground services that access sensitive data, be sure that the use case involves direct user interactions, where the user can control the task being performed. For example, in a video conferencing app, you may use a foreground service to support an active meeting session that involves microphone and camera access. There should also be an affordance for the user to start and stop the session, and thus the foreground service.

如果您的应用程序具有访问敏感数据的现有前台服务,请确保该用例涉及直接的用户交互,以便用户可以控制正在执行的任务。 例如,在视频会议应用程序中,您可以使用前台服务来支持涉及麦克风和摄像头访问的活动会议会话。 用户也应该有能力开始和停止会话,从而开始和停止前台服务。

Additionally, your app must properly set the foregroundServiceType attribute to indicate usage of location, microphone, or camera. This gives the system visibility to apps that need the data and is a requirement for apps that target Android 11. Learn more about foreground service changes.

此外,您的应用必须正确设置foregroundServiceType属性以指示位置,麦克风或摄像头的使用情况。 这使系统可以看到需要数据的应用程序,并且是针对Android 11的应用程序的要求。了解有关前台服务更改的更多信息。

You may declare the usage of multiple data types in the manifest.

您可以在清单中声明多种数据类型的用法。

android:foregroundServiceType = "microphone | location | camera"

If your implementation is based on a long-running worker within WorkManager, it is in fact backed by a foreground service called SystemForegroundService. You should include the appropriate foreground service types in your app’s manifest, which will be merged with Jetpack library’s AAR manifest file.

如果您的实现基于WorkManager 中长期运行的工作程序 ,则实际上它由称为SystemForegroundService的前台服务提供支持。 您应在应用程序的清单中包括适当的前台服务类型,这些类型将与Jetpack库的AAR 清单文件合并。

Include this element in your app’s manifest with proper foreground service types defined.

在定义了正确的前台服务类型的情况下,将此元素包括在您的应用清单中。

<service
    android:name="androidx.work.impl.foreground.SystemForegroundService"
    android:foregroundServiceType="location|microphone"
    tools:node="merge" />

When you promote the worker to run as a foreground service, you will need to pass the appropriate foreground service types into the ForegroundInfo object. These types must be the same as those defined in the merged manifest above, or a subset of them.

当提升工作程序作为前台服务运行时,您需要将适当的前台服务类型传递到ForegroundInfo对象中。 这些类型必须与以上合并清单中定义的类型相同,或者是它们的子集。

setForeground(
    ForegroundInfo(NOTIF_ID,
                   notification.build(),
                   // Foreground service types.
                   ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION or ...)
)

Migrate off of non-resettable identifiers.

迁移不可重置的标识符。

The Android system uses a number of non-resettable hardware identifiers, such as the IMEI, to support various OS functionality. The durability and uniqueness of these identifiers make them unsuitable for most identification use cases due to privacy considerations.

Android系统使用许多不可重置的硬件标识符(例如IMEI)来支持各种OS功能。 这些标识符的持久性和唯一性由于隐私考虑,使其不适用于大多数标识用例。

Since Android 10, the system has limited access to various non-resettable identifiers. For example, only privileged system apps with the READ_PRIVILEGED_PHONE_STATE permission can access SIM hardware identifiers via the getSimSerialNumber() method. In Android 11, the system has further restricted access by applying similar restrictions to the getIccId() method, which now returns an empty string.

自Android 10起 ,系统只能访问各种不可重置的标识符。 例如,只有具有READ_PRIVILEGED_PHONE_STATE权限的特权系统应用程序才能通过getSimSerialNumber()方法访问SIM硬件标识符。 在Android 11中,系统通过对getIccId()方法应用类似的限制来进一步限制访问 ,该方法现在返回一个空字符串。

Apps that may previously be utilizing this identifier to link functionality to a certain SIM should verify compatibility with the “empty string” return value on Android 11. One alternative is to use the getSubscriptionId() method, which returns a 1-based unique index value for a given SIM on the device. That is, if the same SIM is reinstalled on a device, it will retain the previously assigned subscription identifier unless the device is factory-reset. Learn more.

以前可能使用此标识符将功能链接到特定SIM卡的应用程序应验证与Android 11上“空字符串”返回值的兼容性。一种替代方法是使用getSubscriptionId()方法,该方法返回基于1的唯一索引值设备上的给定SIM卡。 也就是说,如果在设备上重新安装了相同的SIM卡,则除非设备已恢复出厂设置,否则它将保留先前分配的订阅标识符。 了解更多

The platform and Google Play services offer a number of identifiers with various uniqueness, resettability, and scope that are suitable for various use cases. You can check out more identifier use cases.

该平台和Google Play服务提供了许多具有各种唯一性,可重置性和适用于各种用例的标识符 。 您可以查看更多标识符用例

I hope you find these recommendations useful in helping you prepare for target API level update and making your app’s design more privacy-friendly! You can learn more about other related improvements in Android 11 and privacy best practices in the documentation.

我希望您发现这些建议对帮助您为目标API级别更新做好准备,并使您的应用程序设计更加隐私友好! 您可以在文档中了解有关Android 11中其他相关改进隐私最佳做法的更多信息。

Thanks to Kevin Hufnagle and Jeremy Walker.

感谢Kevin Hufnagle和Jeremy Walker。

翻译自: https://medium.com/androiddevelopers/adapt-your-app-for-the-latest-privacy-best-practices-d7469a547314

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值