Android Q 简介 - Privacy and location

写在前面

官方文档镇楼

本文为阅读官方文档的同时,翻译并整理而成。因为文档很长,一边看一边记录,并持续更新到这里~

作者的思维有些跳脱,经常想开一个坑就开一个坑,然后慢慢填。如有错误,望大佬们指出,不胜感激。

2019.05.01

Restrictions to background activity starts
User control over app access to device location
Other privacy changes
五一快乐!

2019.04.29

Android Q privacy checklist
Scoped storage


目录

Android Q privacy checklist
  Scoped storage
  Restrictions to background activity starts
  User control over app access to device location
Other privacy changes
  Changes to data and identifiers
  Changes to camera and connectivity
  Changes to permissions


Privacy and location

Android Q扩展了用户对数据和应用功能的透明度和控制。 对于开发人员,这些功能可能会影响您的应用可能依赖的特定行为或数据。
所有开发人员都应该查看隐私功能并测试他们的应用。 影响可能因每个应用的核心功能,定位和其他因素而异。

Android Q privacy checklist

Android Q隐私功能扩展了用户对其数据的透明度和控制以及他们为应用提供的功能。 这些功能可能意味着您的应用所依赖的特定行为或数据可能不再可用。 此清单为您提供了要测试的主要功能的概述,以及要记住的其他隐私更改。

如果您的应用遵循当前处理用户数据的最佳做法,则可以最大限度地减少对应用的影响。 我们建议您尽快开始测试和更新应用。

release-notes

Key behavior changeApps affectedMitigation strategyHow to enable
Scoped storage
New permissions and APIs for accessing media and download collections in external storage
范围存储
用于访问外部存储中的媒体和下载集合的新权限和API
Apps that access and share files in external storage
访问和共享外部存储中的文件的App
Use isolated sandbox or media collection directories
使用isolated sandbox(隔离沙盒) 或 media collection directories (媒体集合目录)
Enabled by default; use ADB command to disable
默认开启;使用ADB命令关闭
More user control over location permissions
New foreground-only permission that gives users more control over app access to device location
对于定位权限更强大的控制
新的仅限前台的权限,可让用户更好地控制对设备位置的应用访问权限
Apps that request the user’s location while in the background
App可以在后台获取用户位置
Ensure graceful degradation in the absence of background location updatesUse new permission to access location in the background
在没有背景位置更新的情况下确保优雅降级;使用新权限在后台访问位置
Behavior is always enabled on Android Q
Android Q上永远开启
Background activity startsNew restrictions on launching activities from the background
从后台开启Activity
从后台启动Activity增加了新的限制
Apps that launch activities without user interaction
在用户不操作的情况下打开Activity的App
Use notification-triggered activities
使用通知触发的Activity
Turn off Allow background activity starts developer option to enable restrictions
关闭“允许后台活动启动开发人员”选项以启用限制
Non-resettable hardware identifiers
New restrictions on accessing device serial and IMEI
不可重置的硬件标识符
访问设备序列和IMEI的新限制
Apps that access device serial or IMEI
访问设备序列或IMEI的App
Use an identifier that the user can reset
使用用户可重置的标识符
Install app on device running Android Q
Android Q上安装的app
Permission for wireless scanning
Access to some Wi-Fi, Wi-Fi Aware, and Bluetooth scanning methods requires fine location permission
无线扫描的权限
访问某些Wi-Fi,Wi-Fi Aware和蓝牙扫描方法需要获得精确的位置许可
Apps using Wi-Fi and Bluetooth APIs
使用Wi-Fi和蓝牙APIs的App
Request ACCESS_FINE_LOCATIONpermission for related use cases
请求相关用例的ACCESS_FINE_LOCATION权限
Target Android Q
Android Q
Other privacy changes

Android Q引入了许多其他隐私更改,您在测试和更新应用时应该记住这些更改:

Data & identifiers
Camera & connectivity
Permissions

在这里插入图片描述


Scoped storage

为了让用户更好地控制文件并限制文件混乱,Android Q改变了应用程序访问设备外部存储上文件的方式。 Android Q使用更细粒度的媒体特定权限替换READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限,并且访问外部存储设备上自己文件的应用程序不需要特定权限。 这些更改会影响您的应用保存和访问外部存储上的文件的方式。

本节介绍了如何更新您的应用,以便它可以继续共享,访问和更新保存在外部存储设备上的文件,提供兼容性注意事项,并说明如何切换此行为更改。

Isolated storage sandbox for app-private files 独立存储沙盒

对于每个应用程序,Android Q都会创建一个独立的存储沙箱,限制其他应用程序访问您的应用程序存储在外部存储设备上的文件。 常见的外部存储设备是/ sdcard。

这种设计具有以下优点:

1.需要更少的权限。 应用程序沙箱中的文件对您的应用程序是私有的。 因此,您不再需要任何权限来访问和保存自己的文件在外部存储中。
2.相对于设备上的其他应用程序,隐私性更强。 没有其他应用可以直接访问您应用的独立存储沙箱中的文件。 此访问限制使您的应用程序更容易维护沙盒文件的隐私。

Note:如果用户卸载了应用,则会清除隔离存储沙箱中的文件。

在外部存储上存储文件的最佳位置是Context.getExternalFilesDir()返回的位置,因为此位置在所有Android版本中表现一致。 使用此方法时,请传入与要创建或打开的文件类型对应的媒体环境。 例如,要访问或保存app-private图像,请调用Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)。

Shared collections for media files

如果您的应用创建了属于该用户的文件,并且该用户希望在卸载您的应用时保留该文件,则将其保存到其中一个公共媒体集合(也称为共享集合)中。 共享集合包括:照片和视频,音乐和下载。

Permissions for viewing other apps’ files

您的应用程序无需请求任何权限即可在这些共享集合中创建和修改自己的文件。 但是,如果您的应用需要创建和修改其他应用已创建的文件,则必须首先请求相应的权限:

1.访问照片和视频共享集合中的其他应用程序文件需要READ_MEDIA_IMAGES或READ_MEDIA_VIDEO权限,具体取决于您的应用程序需要访问的文件类型。
2.访问音乐共享集合中的其他应用程序文件需要READ_MEDIA_AUDIO权限。
注意:您无权访问Downloads共享集合。 您的应用可以访问此集合中自己的文件。 但是,要访问此集合中的其他应用程序文件,需要用户使用系统的文件选择器应用程序选择文件。

注意:如果您的应用使用存储访问框架,则无需请求这些媒体范围的权限。

Access shared collections

在请求必要的权限后,您的应用程序使用MediaStore API访问这些集合:

1.对于照片和视频共享集合,请使用MediaStore.Images或MediaStore.Video。
2.对于Music共享集合,请使用MediaStore.Audio。
3.对于Downloads共享集合,请使用MediaStore.Downloads。

Caution:对于Android Q上新安装的应用程序,对getExternalStoragePublicDirectory()的调用仅提供对应用程序存储在其独立存储沙箱中的文件的访问权限。

要保持对其他应用程序文件的访问权限,请通过以下方式之一更新应用程序的逻辑:

1.使用MediaStore并请求与您要访问的媒体集相对应的READ_MEDIA_ *权限。
2.使用存储访问框架,它不需要任何权限。

Preserve your app’s files in shared collections

默认情况下,当用户卸载您的应用时,Android Q会清除您保存到沙箱中的文件。 要在卸载应用程序时保留这些文件,请使用存储访问框架,或将文件保存到共享集合。

要保留共享集合中的文件,请在相关的MediaStore集合中插入新行,并按以下方式填充其列:

1.至少应为DISPLAY_NAME和MIME_TYPE列提供值。
2.(可选)您可以使用PRIMARY_DIRECTORY和SECONDARY_DIRECTORY列来影响文件在磁盘上的放置位置。
3.保持DATA列未定义。这样,该平台可以灵活地将文件保存在沙箱之外。

插入行后,您可以使用ContentResolver.openFileDescriptor()等API来读取或写入新创建的文件的数据。

但是,如果用户稍后重新安装了您的应用,则您的应用无法访问这些文件,除非它执行以下操作之一:

1.请求相应权限
2.从Storage Access Framework向用户发送请求。

这种情况类似于应用程序尝试访问其他应用程序文件的情况。

Special considerations for photographs

Android Q增加了一些增强功能,使用户可以更好地控制在外部存储上访问照片的方式。

Access location information in pictures

一些照片在其Exif元数据中包含位置信息,允许用户查看拍摄照片的位置。 由于此位置信息是敏感的,因此默认情况下Android Q会对信息进行编辑。 对位置信息的这种限制与适用于相机特性的限制不同。

Note:如果您的应用是用户的默认Photo Manager应用,则平台会自动让您的应用访问照片中的位置信息。

如果您的应用需要访问照片的位置信息,请完成以下步骤:

1.将新的ACCESS_MEDIA_LOCATION权限添加到您应用的清单中。
2.使用MediaStore对象调用setRequireOriginal(),传入照片的URI。

例如:

Uri photoUri = Uri.withAppendedPath(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        cursor.getString(idColumnIndex));

final double[] latLong;
if (BuildCompat.isAtLeastQ()) {
    // When running Android Q, get location data from `ExifInterface`.
    photoUri = MediaStore.setRequireOriginal(photoUri);
    InputStream stream = getContentResolver().openInputStream(photoUri);
    if (stream != null) {
        ExifInterface exifInterface = new ExifInterface(stream);
        double[] returnedLatLong = exifInterface.getLatLong();

        // If lat/long is null, fall back to the coordinates (0, 0).
        latLong = returnedLatLong != null ? returnedLatLong : new double[2];

        // Don't reuse the stream associated with {@code ExifInterface}.
        stream.close();
    } else {
        // Failed to load the stream, so return the coordinates (0, 0).
        latLong = new double[2];
    }
} else {
    // On devices running Android 9 (API level 28) and lower, use the
    // media store columns.
    latLong = new double[]{
            cursor.getFloat(latitudeColumnIndex),
            cursor.getFloat(longitudeColumnIndex)
    };
}
Show users a gallery of photos

如果您的应用是相机应用,则它无法直接访问照片和视频共享集中保存的照片,除非它是设备的默认Photo Manager应用。 要将用户定向到图库应用,请使用ACTION_REVIEW intent。

Work with other apps’ files

本节介绍了App如何与存储在共享集合中的其他App的文件进行交互。

Access files created by other apps

要访问和读取其他应用程序已保存到外部存储设备的媒体文件,请完成以下步骤:

1.根据包含您要访问的文件的共享集合,请求必要的权限。
2.使用ContentResolver对象查找并打开该文件。

Note:ContentResolver类包含一个新方法loadThumbnail(),它为您的应用程序提供文件预览。 最好首先调用loadThumbnail(),以便用户可以查看媒体文件的快照,而无需您的应用程序自己加载整个文件。 此方法还允许更灵活的请求,例如请求特定维度和取消请求。

Write to files created by other apps

通过将文件保存到共享集合,您的应用程序将成为该文件的所有者。 通常,只有当您是文件所有者时,您的应用才能写入共享集合中的文件。 但是,如果您的应用程序充当特定用例的用户默认应用程序,您还可以写入其他应用程序拥有的文件:

1.如果您的应用是用户的默认Photo Manager应用,则可以修改其他应用保存到“照片和视频”共享集合中的图像文件。
2.如果您的应用是用户的默认音乐应用,则可以修改其他应用保存到音乐共享收藏集的音频文件。

Note:无论是默认的照片管理器还是音乐应用,您的应用都应保持正常运行。

要修改其他应用最初保存到外部存储设备的媒体文件,请使用ContentResolver对象查找文件并进行就地修改。执行编辑/修改操作时,catch RecoverableSecurityException,以便您可以请求用户授予您对该特定项目的写入权限。

Access media files from native code

您可能会遇到以下情况:您的应用需要使用native code中的特定媒体文件,例如另一个应用与您的应用共享的文件,或来自用户媒体集的媒体文件。 在这些情况下,请在基于Java或基于Koltin的代码中搜索媒体文件,然后将文件的关联文件描述符传递到本机代码中。

以下代码段显示了如何将媒体对象的文件描述符传递到应用程序的本机代码中:

Uri contentUri = ContentUris.withAppendedId(
        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
        cursor.getLong(Integer.parseInt(BaseColumns._ID)));
String fileOpenMode = "r";
ParcelFileDescriptor parcelFd = resolver.openFileDescriptor(uri, fileOpenMode);
if (parcelFd != null) {
    int fd = parcelFd.detachFd();
    // Pass the integer value "fd" into your native code. Remember to call
    // close(2) on the file descriptor when you're done using it.
}
Access specific files

在某些用例中,您的应用可能需要打开或创建无权访问的文件:

1.在照片编辑应用中,打开一张图纸(open a drawing)。
2.在企业生产力App中,将文本文档保存到用户选择的位置。

对于这些情况,请使用存储访问框架,该框架允许用户选择要打开的特定文件,或选择特定位置来保存文件。

Companion app file sharing

请遵循以下最佳做法,以便以更安全的方式与其他应用分享您的应用内容:

1.根据需要强制执行只读或只写权限。
2.使用FLAG_GRANT_READ_URI_PERMISSION和FLAG_GRANT_WRITE_URI_PERMISSION标志为客户端提供一次性数据访问。
3.共享数据时,请使用“content://”URI,而不是“file://”URI。 FileProvider的实例为您执行此操作。

以下代码段显示了如何使用URI权限授予标志和内容提供程序权限在单独的PDF Viewer应用程序中显示应用程序的PDF文件:

// Create an Intent to launch a PDF viewer for a file owned by this app.
Intent viewPdfIntent = new Intent(Intent.ACTION_VIEW);
viewPdfIntent.setData(Uri.parse("content://com.example/personal-info.pdf"));

// This flag gives the started app read access to the file.
viewPdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Make sure that the user has a PDF viewer app installed on their device.
if (viewPdfIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(viewPdfIntent);
}
相关:android:grantUriPermissions

通常无权访问内容提供者数据的人是否可以被授予这样做的权限,暂时克服readPermission,writePermission和权限属性所施加的限制 - 如果可以授予权限,则为“true”。如果为“true”,则可以向任何内容提供商的数据授予权限。如果为“false”,则只能授予子元素中列出的数据子集的权限(如果有)。默认值为“false”。

授予权限是一种为应用程序组件一次性访问受权限保护的数据的方法。例如,当电子邮件消息包含附件时,即使查看者没有查看所有内容提供者的数据的一般许可,邮件应用程序也可以呼叫适当的查看者打开它。

在这种情况下,权限由激活组件的Intent对象中的FLAG_GRANT_READ_URI_PERMISSION和FLAG_GRANT_WRITE_URI_PERMISSION标志授予。例如,邮件应用程序可能将FLAG_GRANT_READ_URI_PERMISSION放入传递给Context.startActivity()的Intent中。该权限特定于Intent中的URI。
如果通过将此属性设置为“true”或通过定义子元素来启用此功能,则必须在从提供程序中删除覆盖的URI时调用Context.revokeUriPermission()。

Compatibility mode for previously installed apps on upgrading devices

访问外部存储中文件的限制仅适用于以Android Q为目标的应用,或者在运行Android Q的设备上新安装的应用。

当满足以下每个条件时,系统会将应用程序的文件访问权限置于兼容模式:

1.App以Android 9(API级别28)或更低级别为target。
2.App安装在从Android 9升级到Android Q的设备上。

当您的应用处于兼容模式时,以下文件访问行为适用:

1.您的应用可以访问MediaStore集合中存储的所有文件,甚至是您的应用尚未创建的文件。
2.面向用户的存储权限允许或拒绝您的应用程序作为一个整体访问外部存储,而不是单独的共享集合,如照片和视频或音乐。

在首次卸载您的应用程序之前,此兼容模式仍然有效。

Note:如果稍后在同一设备上重新安装您的应用,则不会重新激活兼容模式。

Identify a specific external storage device

在Android 9(API级别28)及更低版本中,所有存储设备上的所有文件都显示在单个“extenal”卷名称下。 Android Q为每个外部存储设备提供唯一的卷名。 此命名系统可帮助您有效地组织和索引内容,并使您可以控制新内容的存储位置。

Note:主外部存储设备(The primary external storage device)始终使用卷名“extenal”。

要唯一标识外部存储中的特定文件,必须同时使用卷名和ID。 例如,主存储设备上的文件将是content://media/external/images/media/12,但是名为FA23-3E92的辅助存储设备上的相应文件将是content://media/FA23-3E92/images/media/12。您可以通过将此卷名称传递到特定媒体集合(例如MediaStore.Images.getContentUri())来访问存储在特定卷上的文件。

Get the list of external storage devices

要获取所有当前可用卷的名称列表,请调用MediaStore.getAllVolumeNames(),如以下代码段所示:

Set<String> volumeNames = MediaStore.getAllVolumeNames(context);
Set up a virtual external storage device

在没有可移动外部存储的设备上,使用以下命令启用虚拟磁盘以进行测试:

$ adb shell sm set-virtual-disk true
Test the behavior change

为了帮助您使应用程序与此新行为更改兼容,该平台提供了多种方法来调整与更改相关的多个参数。

Toggle the behavior change

在Android Q中,默认情况下会启用此行为更改。 要禁用更改以进行测试,请在终端窗口中执行以下命令:

$ adb shell sm set-isolated-storage off

运行此命令后,设备将重新启动。 如果没有,请等一下再尝试再次运行该命令。

要确认您已成功切换行为更改,请使用以下命令:

$ adb shell getprop sys.isolated_storage_snapshot
Test compatibility mode behavior

测试应用程序时,可以通过在终端窗口中运行以下命令来启用外部文件存储访问的兼容性模式:

$ adb shell cmd appops set your-package-name android:legacy_storage allow && \
adb shell am force-stop your-package-name

禁用兼容模式,请在Android Q上卸载并重新安装您的应用,或在终端窗口中运行以下命令:

$ adb shell cmd appops set your-package-name android:legacy_storage default && \
adb shell am force-stop your-package-name
Browse external storage as a file manager

要像文件管理器应用程序那样获得对外部存储中目录的广泛访问权限,请使用ACTION_OPEN_DOCUMENT_TREE intent。 有关示例,请参阅GitHub上的android-DirectorySelection示例。

Caution:在Android Q中不推荐使用StorageVolume类中的createAccessIntent()方法,因此不应使用此方法浏览外部存储设备。 如果您这样做,运行Android Q设备的用户将无法在您的应用中查看保存在外部存储中的文件。


Restrictions to background activity starts

Android Q限制了应用何时可以startActivity。 此行为更改有助于最大限度地减少用户的中断,并使用户更好地控制屏幕上显示的内容。 特别是,在Android Q上运行的应用只有在满足以下一个或多个条件时才能startActivity:

1.该应用程序具有可见窗口,例如前台活动。
2.位于前台的另一个应用程序会发送属于该应用程序的PendingIntent。 示例包括Costom Tabs provider发送menu item pending intent。
3.系统发送属于应用程序的PendingIntent,例如点击通知。 只有应用程序可以启动UI的pending intents才可以免除。
4.系统向应用程序发送广播,例如SECRET_CODE_ACTION。 只有应用程序预期启动UI的特定广播才免除。

Note:startActivity时,前台服务不会将App认为位于前台。

此行为更改适用于在Android Q上运行的所有应用,甚至是针对Android 9(API级别28)或更低级别的应用。 此外,即使您的应用针对Android 9或更低版本并且最初安装在运行Android 9或更低版本的设备上,行为更改仍会在设备升级到Android Q后生效。

但是,只要您的应用以用户互动的直接结果开始活动,您的应用很可能不会受到此更改的影响。 实际上,大多数应用程序都不受此更改的影响。

Warning messages

在Beta 2中,如果您的应用程序在Android Q上运行并尝试从后台启动活动,则平台允许活动启动,但它会向logcat发送警告消息并显示以下警告Toast消息:

从package-name开始的后台活动将在未来的Q版本中被阻止。

与Android Q中后台启动活动相关的限制类似于系统在设备进入屏幕固定状态后阻止活动启动的方式。

Create notifications for time-sensitive events

几乎在所有情况下,后台应用程序都应创建通知,以便向用户提供信息,而不是直接启动活动。

在特定情况下,您的应用可能需要立即引起用户的注意,例如正在进行的警报或来电。 您可能已将应用配置为为此目的启动后台活动。 要在运行Android Q的设备上提供相同的行为,请完成以下各节中显示的步骤。

Create a high-priority notification

创建通知时,请确保包含描述性标题和消息,并且您可以选择提供全屏意图:

public Notification.Builder setFullScreenIntent (PendingIntent intent, boolean highPriority)

该intent为全屏启动名,而不是将通知发布到状态栏的。 仅适用于要求用户立即关注的极高优先级通知,例如用户明确设置为特定时间的来电或闹钟。 如果此功能用于其他用途,请为用户提供关闭它并使用正常通知的选项,因为这可能会造成极大的破坏性。

当用户使用该设备时,系统UI可以选择显示抬头通知,而不是启动该意图。针对Build.VERSION_CODES#Q及以上版本的应用必须请求权限(Manifest.permission.USE_FULL_SCREEN_INTENT)才能使用全屏意图。

以下代码段中会显示示例通知:

val fullScreenIntent = Intent(this, CallActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Incoming call")
    .setContentText("(919) 555-1234")
    .setPriority(NotificationCompat.PRIORITY_HIGH)
    .setCategory(NotificationCompat.CATEGORY_CALL)

    // Use a full-screen intent only for the highest-priority alerts where you
    // have an associated activity that you would like to launch after the user
    // interacts with the notification. Also, if your app targets Android Q, you
    // need to request the USE_FULL_SCREEN_INTENT permission in order for the
    // platform to invoke this notification.
    .setFullScreenIntent(fullScreenPendingIntent, true)

val incomingCallNotification = notificationBuilder.build()
Display the notification to the user

在向用户显示通知时,他们可以根据当前上下文选择是否确认或关闭应用的警告或提醒。 例如,用户可以选择是接受还是拒绝来电。

如果您的通知是连续的通知(例如来电),请将通知与前台服务相关联。 以下代码段显示了如何显示与前台服务关联的通知:

// Provide a unique integer for the "notificationId" of each notification.
startForeground(notificationId, notification)

Note:系统UI可以选择在用户使用设备时显示抬头通知,而不是启动全屏意图。

Benefits of notifications

这种基于通知的警报和提醒系统为用户提供了以下几个优势:

1.使用设备时,会向用户显示抬头通知,允许他们接听或拒绝来电,或者取消闹钟。 用户保持着当前的上下文并控制他们在屏幕上看到的内容。
2.您的来电或闹钟会受到用户的“请勿打扰”规则的影响。 例如,当启用“请勿打扰”时,用户可能仅允许来自特定联系人或重复呼叫者的呼叫。
3.当设备的屏幕关闭时,您的全屏意图会立即启动。
4.在设备的“设置”界面中,用户可以查看哪些应用最近发送了通知,包括来自特定通知渠道的通知。 在该界面中,用户可以控制他们的通知偏好。

Enable the behavior change

即使此行为更改在Android Q Beta 2中默认不生效,您也可以通过完成以下任务之一来模拟行为更改:

1.导航到“设置”>“开发人员”选项,然后禁用“允许后台活动启动”选项。
2.在终端窗口中,运行以下命令:

$ adb shell settings put global background_activity_starts_enabled 0

通过测试行为更改,您可以更加确信用户在Android Q上按预期继续与App进行交互。


User control over app access to device location

Android Q让用户可以更好地控制应用何时可以访问设备位置。 当在Android Q上运行的应用程序请求位置访问时,用户会看到 如图所示的对话框。此对话框允许用户授予对两个不同范围的位置访问权限:while in use 在使用中(仅限前景)或 all the time 始终(前景和后台)。

在这里插入图片描述
为了支持用户对应用访问位置信息的额外控制,Android Q引入了新的位置权限ACCESS_BACKGROUND_LOCATION。 与现有的ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION权限不同,新权限仅影响应用在后台运行时对位置的访问权限。 除非其中一个活动可见或应用程序正在运行前台服务,否则应用程序被视为处于后台。

Request background location

如果您的应用针对Android Q并且需要在后台运行时访问用户的位置,则必须在应用的清单文件中声明新权限:

<manifest>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

如果您的应用在Android Q上运行但针对的是Android 9(API级别28)或更低的版本,则以下行为适用:

1.如果您的应用为ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION声明标记,则系统会在安装期间自动为ACCESS_BACKGROUND_LOCATION添加标记。
2.如果您的应用请求ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION,系统会自动将ACCESS_BACKGROUND_LOCATION添加到请求中。

Caution:虽然您的应用可以请求并接收ACCESS_BACKGROUND_LOCATION,但用户可以通过选择"您的应用仅应在前台访问位置信息"来撤消此权限。

Request background location access

Note:此部分适用于在Android Q上运行的所有应用,无论它们针对哪个版本。

如果您的应用程序的用例需要在后台运行时访问位置信息,请务必考虑您需要此访问权限的程度:

1.您的应用程序的用例依赖于continuation of a user-initiated action,例如导航或智能家庭操作。 在这种情况下,您需要配置前台服务,以便在用户按下其设备上的“Home”键或关闭其设备显示后,即使用户已请求您的应用只能访问其位置,也可以保留对用户位置的访问权限在前台。
2.您应用的用例依赖于定期检查用户的位置,例如地理围栏或位置共享。 在这种情况下,您的应用应向用户说明他们需要允许您的应用始终访问其位置才能正常运行,然后请求访问后台位置。

Continuation of user-initiated action

Note:如果您的应用在后台运行时不需要访问位置,则最佳做法是定位Android Q而不是请求新的后台位置权限。 这样,您的应用只会在使用时收到位置更新,具体实现可参照本节末尾的Github链接。

如果用户已将您的应用仅限前景访问位置,用户仍可能会启动要求您的应用访问其位置的工作流,即使用户已经按下“Home”键或关闭了显示屏。

要在此特定用例中保留对用户位置的访问权限,启动一个已在应用清单中声明的foreground service,type为“location”:

<service
    android:name="MyNavigationService"
    android:foregroundServiceType="location" ... >
    ...
</service>

启动foreground service前需要确认App拥有访问位置的权限:

boolean permissionAccessCoarseLocationApproved =
    ActivityCompat.checkSelfPermission(this,
        permission.ACCESS_COARSE_LOCATION) ==
        PackageManager.PERMISSION_GRANTED;

if (permissionAccessCoarseLocationApproved) {
    // App has permission to access location in the foreground. Start your
    // foreground service that has a foreground service type of "location".
} else {
   // Make a request for foreground-only location access.
   ActivityCompat.requestPermissions(this, new String[] {
        Manifest.permission.ACCESS_COARSE_LOCATION},
       your-permission-request-code);
}
Periodic checks of user’s location

您应用的用例依赖于定期检查用户的位置,例如地理围栏或位置共享。如果App有此情况,您可以继续请求位置信息,无需任何修改,只要用户授予App all-the-time access to their location:

<!-- It's unnecessary to include a foreground service type for services that must have
     access to the user's location "all the time" in order to run successfully.-->
<service
    android:name="MyFamilyLocationSharingService" ... >
    ...
</service>

虽然您的应用可以请求在后台访问位置,但用户可以将权限降级为前台访问权限或完全撤消访问权限。 因此,每当您的应用启动服务时,请检查用户是否仍允许您的应用在后台访问位置信息。

如果用户仅请求您的应用访问位置位于前台,则应用最佳做法是显示自定义对话框,提醒用户您的应用无法正常运行而无法始终访问其位置。 用户确认此对话框后,您可以请求后台位置,此时会出现如图所示的系统对话框:

在这里插入图片描述
以下代码段中显示了此权限检查逻辑的示例:

boolean permissionAccessCoarseLocationApproved =
    ActivityCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION)
        == PackageManager.PERMISSION_GRANTED;

if (permissionAccessCoarseLocationApproved) {
   boolean backgroundLocationPermissionApproved =
           ActivityCompat.checkSelfPermission(this,
               permission.ACCESS_BACKGROUND_LOCATION)
               == PackageManager.PERMISSION_GRANTED;

   if (backgroundLocationPermissionApproved) {
       // App can access location both in the foreground and in the background.
       // Start your service that doesn't have a foreground service type
       // defined.
   } else {
       // App can only access location in the foreground. Display a dialog
       // warning the user that your app must have all-the-time access to
       // location in order to function properly. Then, request background
       // location.
       ActivityCompat.requestPermissions(this, new String[] {
           Manifest.permission.ACCESS_BACKGROUND_LOCATION},
           your-permission-request-code);
   }
} else {
   // App doesn't have access to the user's location at all. Make full request
   // for permission.
   ActivityCompat.requestPermissions(this, new String[] {
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_BACKGROUND_LOCATION
        },
        your-permission-request-code);
}
Design for device upgrade scenarios

在设备升级到Android Q后确定此行为更改如何影响您的应用时,请考虑计划在即将发布的Android Q测试版中进行的以下更改。

如果用户完成以下步骤:

1.在运行Android 9(API级别28)的设备上安装您的应用
2.授予您对设备位置的应用访问权限 - ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION。
3.将他们的设备从Android 9升级到Android Q.
…然后系统会根据目标SDK版本及其定义的权限自动更新应用程序的默认位置权限状态,如下表所示:

Target SDK versionCoarse or fine permission granted?Background permissiondefined in manifest?Updated default permission state
Android QYesYesForeground and background access
Android QYesNoForeground access only
Android QNo(Ignored by system)No access
Android 9 (API level 28)or lowerYes(Automatically added by the system at device upgrade time)Foreground and background access
Android 9 (API level 28)or lowerNo(Ignored by system)No access

Note:即使系统自动更新了应用对设备位置的访问权限,用户也可以选择更改此级别的访问权限。 用户可以将权限降级为前台访问权限或完全撤消访问权限。因此,在访问设备的位置更新之前,请按照最佳做法检查用户是否仍允许您的应用接收此位置信息。

Follow location best practices

通过按照本指南中显示的方式检查和请求位置权限,您的应用可以成功跟踪其有关用户位置的访问级别。

应用权限最佳做法:

使用 Android 权限的原则

使用 Android 权限时,我们建议遵循以下原则:

1.仅使用应用正常工作所需的权限。根据您使用权限的方式,您可以通过其他方式执行所需的操作(系统 intent、标识符、电话的后台处理),而无需依赖于访问敏感信息。
2.注意库所需的权限。 添加某个库时,您也会继承它的权限要求。您应了解正在添加的库、它们需要的权限以及这些权限的用途。
3.公开透明。 请求权限时,请清晰说明您要访问的内容以及访问原因,以便用户可以做出明智的决策。在请求权限时(包括安装、运行时或更新权限对话框)列出这些信息。
4.让系统以显式方式访问。 在访问敏感功能(例如,摄像头或麦克风)时提供连续指示,让用户知道您在收集数据,避免让他们认为您在偷偷地收集数据。

改用 intent

在许多情况下,要让应用执行某项任务,有两种方法供您选择。应用可以要求提供权限来自行执行该任务,也可以使用 intent 让其他应用执行该任务。
例如,假设应用需要使用设备摄像头才能够拍摄照片。应用可以请求 CAMERA 权限,以便允许应用直接访问摄像头。然后,应用将使用摄像头 API 控制摄像头并拍摄照片。此方法使应用能够完全控制拍摄过程,并且您可以将摄像头界面整合到应用中。

不过,如果您很少需要访问用户数据,换句话说,每次您需要访问数据时都向用户显示运行时对话框,这种中断操作并非不可接受,那么您可以使用基于 intent 的请求。Android 提供了一些系统 intent,借助这些 intent,应用无需请求权限,因为在发出基于 intent 的请求时用户会选择与应用共享的内容。
例如,您可以使用 intent 操作类型 MediaStore.ACTION_IMAGE_CAPTURE 或 MediaStore.ACTION_VIDEO_CAPTURE 来拍摄图像或视频,而无需直接使用 Camera 对象(或请求权限)。在这种情况下,每次拍摄图像时,系统 intent 都会代表您请求用户提供权限。

同样,如果您需要拨打电话、访问用户的联系人或执行其他操作,您可以通过创建适当的 intent 来完成,也可以直接请求权限并访问相应的对象。每种方法各有优缺点。

不要让用户感到无所适从

如果用户运行的是 Android 6.0(API 级别 23)或更高版本,则用户必须在运行应用时为其授予权限。如果您让用户一次面对大量的权限请求,可能会让用户感到无所适从,导致他们退出您的应用。您应根据需要请求权限。
在某些情况下,一项或多项权限可能对您的应用来说必不可少。在这种情况下,合理的做法是,在应用启动之后立即请求提供所有这些权限。例如,如果您创建的是摄影应用,则该应用将需要访问设备的摄像头。当用户首次启动该应用时,系统会要求他们提供摄像头使用权限,他们不会对此感到惊讶。但是,如果同一应用还具备与用户的联系人分享照片的功能,那么您或许不应在应用首次启动时请求用户提供READ_CONTACTS 权限,而应等到用户尝试使用“分享”功能之后再请求该权限。如果应用提供教程,则合理的做法是,在教程结束时请求提供应用的必要权限。

失去音频焦点后暂停媒体

在这种情况下,当用户接电话时,您的应用需要转入后台,只有在通话停止后才会重新获得焦点。
出现此类情况(例如,媒体播放器在通话期间静音或暂停)时,通常采用的方法是使用 PhoneStateListener 或监听 android.intent.action.PHONE_STATE 的广播,以监听通话状态有无变化。这种解决方法的问题是它需要 READ_PHONE_STATE 权限,这将强制用户授予对广泛的敏感数据(如用户的设备和 SIM 硬件 ID 以及来电的电话号码)的访问权限。
您可以通过为应用请求 AudioFocus,在没有 READ_PHONE_STATE 或 MODIFY_PHONE_STATE 权限的情况下检测用户是否在通话中,这么做不需要显式权限,因为它不访问敏感信息。只需将对音频放入后台所需的代码放入onAudioFocusChange() 事件处理程序,当操作系统转换其音频焦点时,它将自动运行。要详细了解如何执行此操作,请参阅Handling changes in audio output

确定正在运行实例的设备

在这种情况下,您需要一个唯一标识符来确定您的应用实例正在哪个设备上运行。
应用可能具有设备特定的偏好设置或消息(例如,在云端为用户保存设备特定的播放列表,以便他们在车上和家里可以有不同的播放列表)。常见的解决方案是利用设备标识符(如 Device IMEI),但这需要 Device ID and call information 权限组(M+ 中为 PHONE)。它还使用一个无法重置且在所有应用之间共享的标识符。下面两种方法可以替代这些类型的标识符:

1.使用 com.google.android.gms.iid InstanceID API。getInstance(Context context).getID() 将为您的应用实例返回一个唯一设备标识符。结果是一个应用实例作用域标识符,在存储有关应用的信息时,该标识符可用作键,如果用户重新安装应用,该标识符会重置。
2.使用 randomUUID() 之类的基本系统函数创建您自己的标识符,其作用域限定为应用的存储空间。

为广告或用户分析创建唯一标识符

在这种情况下,您需要一个唯一标识符来为没有登录您应用的用户构建配置文件(例如,用于广告定位或衡量转化率)。
为广告和用户分析构建配置文件有时需要一个在其他应用之间共享的标识符。此问题的常见解决方案需要利用设备标识符(如 Device IMEI),这需要 Device ID and call information 权限组(API 级别 23+ 中为 PHONE),并且无法由用户重置。无论是上述哪种情况,除了使用不可重置的标识符并请求用户可能认为不寻常的权限外,还会违反 Play 开发者计划政策。

遗憾的是,在这些情况下,使用 com.google.android.gms.iid InstanceID API 或系统函数创建应用作用域 ID 并不是适当的解决方案,因为可能需要在应用之间共享该 ID。一种替代解决方案是使用通过 getId() 方法从AdvertisingIdClient.Info类中获取的 Advertising Identifier。您可以使用 getAdvertisingIdInfo(Context)方法创建一个AdvertisingIdClient.Info对象,并调用 getId() 方法来使用该标识符。请注意,此方法会产生阻塞,因此,您不应从主线程调用它;有关此方法的详细说明,请查看AdvertisingIdClient

At last : GitHub上的LocationUpdatesForegroundService项目


Changes to data and identifiers

本文档描述了访问数据和系统标识符的几个限制。 这些更改有助于保护用户的隐私。

其中一部分更改会影响在Android Q上运行的所有应用,而其他更改仅会影响target Android Q的应用。

Changes affecting all apps

以下更改会影响在Android Q上运行的所有应用,即使target Android 9(API级别28)或更低level。

Contacts affinity

从Android Q开始,该平台不再跟踪联系人亲缘关系信息。 因此,如果您的应用对用户的联系人进行搜索,则结果不再按交互频率排序。

“联系人提供程序”指南包含一个通知,说明自Android Q起所有设备上已废弃的特定字段和方法。

Randomized MAC addresses

在Android Q上运行的设备默认传输随机MAC地址。 如果您的应用处理企业用例,该平台会提供几个新的API:

1.获取随机MAC地址:设备所有者应用和配置文件所有者应用可以通过调用getRandomizedMacAddress()来检索分配给特定网络的随机MAC地址。
2.获取实际的工厂MAC地址:设备所有者应用程序可以通过调用getWifiMacAddress()来检索设备的实际硬件MAC地址。 此方法对于跟踪设备队列非常有用。

Access to /proc/net filesystem

Android Q删除对/ proc / net的访问权限,其中包含有关设备网络状态的信息。 需要访问此信息的应用程序(如VPN)应参考NetworkStatsManager和ConnectivityManager类。

Non-resettable device identifiers

从Android Q开始,应用必须具有READ_PRIVILEGED_PHONE_STATE特权权限才能访问设备的不可重置标识符,包括IMEI和序列号。 许多用例不需要不可重置的设备标识符。 如果您的应用程序没有权限,并且您尝试询问有关标识符的信息,则平台的响应会因目标SDK版本而异:

1.如果您的应用针对Android Q,则会发生SecurityException。
2.如果您的应用针对Android 9(API级别28)或更低版本,则该方法会返回null或占位符数据(如果该应用具有READ_PHONE_STATE权限)。 否则,发生SecurityException。

Note:如果您的应用是设备或配置文件所有者应用,即使您的应用针对Android Q,您也只需要READ_PHONE_STATE权限即可访问不可重置的设备标识符。此外,如果您的应用具有特殊的运营商权限,则您不需要 访问标识符的任何权限。

Access to clipboard data

除非您的应用程序是默认输入法编辑器(IME)或当前具有焦点的应用程序,否则您的应用程序无法访问剪贴板数据。

Changes affecting apps targeting Android Q
Access to USB serial requires user permission

如果您的应用针对Android Q,则您的应用只能在用户授予您访问USB设备或配件的应用权限后才能读取序列号。


Changes to camera and connectivity

本文档描述了访问摄像机和连接信息的几个限制。 这些更改有助于保护用户的隐私。

其中一些更改会影响在Android Q上运行的所有应用,而其他更改仅会影响针对Android Q的应用。

Changes affecting all apps
Access to all camera information requires permission

Android Q更改了默认情况下getCameraCharacteristics()方法返回的信息的广度。 特别是,您的应用必须具有CAMERA权限才能访问此方法的返回值中包含的特定设备的潜在meta-data。

如果您的应用没有CAMERA权限,则无法访问以下字段:

ANDROID_LENS_POSE_ROTATION
ANDROID_LENS_POSE_TRANSLATION
ANDROID_LENS_INTRINSIC_CALIBRATION
ANDROID_LENS_RADIAL_DISTORTION
ANDROID_LENS_POSE_REFERENCE
ANDROID_LENS_DISTORTION
ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE
ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE
ANDROID_SENSOR_REFERENCE_ILLUMINANT1
ANDROID_SENSOR_REFERENCE_ILLUMINANT2
ANDROID_SENSOR_CALIBRATION_TRANSFORM1
ANDROID_SENSOR_CALIBRATION_TRANSFORM2
ANDROID_SENSOR_COLOR_TRANSFORM1
ANDROID_SENSOR_COLOR_TRANSFORM2
ANDROID_SENSOR_FORWARD_MATRIX1
ANDROID_SENSOR_FORWARD_MATRIX2

Restriction on enabling and disabling Wi-Fi

在Android Q上运行的应用无法启用或停用Wi-Fi。 WifiManager.setWifiEnabled()方法始终返回false。
如果需要,请使用设置面板提示用户启用和禁用Wi-Fi。

设置面板打开方式:

Intent panelIntent = new Intent(Settings.Panel.settings_panel_type);
startActivityForResult(panelIntent);

settings_panel_type:

ACTION_INTERNET_CONNECTIVITY
显示与互联网连接相关的设置,例如飞行模式,Wi-Fi和移动数据。
ACTION_WIFI:
显示Wi-Fi设置,但不显示其他连接设置。 这对于需要Wi-Fi连接以执行大量上传或下载的应用非常有用。
ACTION_NFC
显示与NFC相关的所有设置。
ACTION_VOLUME
显示所有音频流的音量设置。

在这里插入图片描述
在这里插入图片描述

谷歌计划为此功能引入一个AndroidX wrapper。 在运行Android 9(API级别28)或更低级别的设备上调用时,包装器将在“设置”应用中打开最合适的页面。

Changes affecting apps targeting Android Q
Wi-Fi network configuration restrictions

为了保护用户隐私,现在将Wi-Fi网络列表的手动配置限制在系统应用程序中。 如果您的应用针对Android Q,则以下方法不再返回有用数据:

1.getConfiguredNetworks()方法始终返回一个空列表。
2.返回整数值的网络操作方法-addNetwork()和updateNetwork() - 始终返回-1。
3.返回布尔值的网络操作 - removeNetwork(),reassociate(),enableNetwork(),disableNetwork(),reconnect()和disconnect() - 始终返回false。

如果您的应用需要连接到Wi-Fi网络,请使用以下备用方法:

1.要触发与Wi-Fi网络的即时本地连接,请在标准NetworkRequest对象中使用WifiNetworkSpecifier。
2.要添加Wi-Fi网络以考虑为用户提供Internet访问,请使用WifiNetworkSuggestion对象。 您可以分别通过调用WifiManager.addNetworkSuggestions()和WifiManager.removeNetworkSuggestions()来添加和删除出现在自动连接网络选择对话框中的网络。 这些方法不需要任何位置权限。

Fine location permission needed for telephony, Wi-Fi, Bluetooth APIs
除非您的应用具有ACCESS_FINE_LOCATION权限,否则在Android Q上运行时,您的应用无法在Wi-Fi,Wi-Fi Aware或蓝牙API中使用多种方法。以下列表显示了受影响的方法:

Note:如果您的应用在Android Q上运行但针对的是Android 9(API级别28)或更低版本,只要您的应用具有ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限,您就可以使用受影响的API。

Telephony
	TelephonyManager
		getCellLocation()
		getAllCellInfo()
		requestNetworkScan()
		requestCellInfoUpdate()
		getAvailableNetworks()
		getServiceStateForSubscriber
		getServiceState()
	TelephonyScanManager
		requestNetworkScan()
	PhoneStateListener
		onCellLocationChanged()
		onCellInfoChanged()
		onServiceStateChanged()
	NetworkScanCallback
		onResults()
Wi-Fi
	WifiScanner
		startScan()
	WifiManager
		startScan()
		getScanResults()
		getConnectionInfo()
		getConfiguredNetworks()
	WifiAwareManager
	WifiP2pManager
	WifiRTTManager
Bluetooth
	BluetoothAdapter
		startDiscovery()
		startLeScan()
		LeScanCallback()

Changes to permissions

本文档介绍了权限模型的一些更改。 这些更改有助于增强用户隐私。

以下更改会影响在Android Q上运行的所有应用,即使它们定位到Android 9(API级别28)或更低级别。

Restricted access to screen contents

为了保护用户的屏幕内容,Android Q通过更改READ_FRAME_BUFFER,CAPTURE_VIDEO_OUTPUT和CAPTURE_SECURE_VIDEO_OUTPUT权限的范围来阻止对设备屏幕内容的静默访问,以便它们只能进行签名访问。

What is signature-access ?
The system grants these app permissions at install time, but only when the app that attempts to use a permission is signed by the same certificate as the app that defines the permission.

需要访问设备屏幕内容的应用应使用MediaProjection API,该API会显示提示,要求用户提供同意。

User-facing permission check on legacy apps

如果您的应用针对Android 5.1(API级别22)或更低版本,则用户首次在Android Q上运行您的应用时会看到权限屏幕,如图所示。此屏幕使用户有机会撤消对权限的访问权限 以前在安装时授予您应用的系统。

在这里插入图片描述

Caution:如果您要在Google Play上发布应用,则必须定位到Android 8.0(API级别26)或更高版本。 要了解详情,请参阅有关如何满足Google Play目标API级别要求的指南

Physical activity recognition

Android Q为需要检测用户移动的应用程序(例如步行,骑自行车或车辆)引入了新的ACTIVITY_RECOGNITION运行时权限。 这旨在让用户了解设置中如何使用设备传感器数据。

如果您的应用以Android 9(API级别28)或更低级别为目标,并在其清单文件中指定com.google.android.gms.permission.ACTIVITY_RECOGNITION权限,系统会根据需要自动向您的应用授予此权限。 但是,用户可以随时在系统设置中撤消此权限。

Note:除非用户已授予您的应用此权限,否则Google Play服务中的某些库(例如活动识别API)不会提供结果。

Permission groups removed from UI

从Android Q开始,应用无法查找权限在UI中分组。

Privacy-preserving machine learning is becoming increasingly important in today's world where data privacy is a major concern. Federated learning and secure aggregation are two techniques that can be used to achieve privacy-preserving machine learning. Federated learning is a technique where the machine learning model is trained on data that is distributed across multiple devices or servers. In this technique, the model is sent to the devices or servers, and the devices or servers perform the training locally on their own data. The trained model updates are then sent back to a central server, where they are aggregated to create a new version of the model. The key advantage of federated learning is that the data remains on the devices or servers, which helps to protect the privacy of the data. Secure aggregation is a technique that can be used to protect the privacy of the model updates that are sent to the central server. In this technique, the updates are encrypted before they are sent to the central server. The central server then performs the aggregation operation on the encrypted updates, and the result is sent back to the devices or servers. The devices or servers can then decrypt the result to obtain the updated model. By combining federated learning and secure aggregation, it is possible to achieve privacy-preserving machine learning. This approach allows for the training of machine learning models on sensitive data while protecting the privacy of the data and the model updates.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值