Android Q 预览版新特性解读 - Xiasm/Java-Android-Learn GitHub Wiki
Android Q 改变了应用程序访问设备外部存储上文件的方式。 通过使用更细粒度的媒体特定权限替换以前的 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE权限。
Android Q 为每个应用程序提供了一个独立的在外部存储设备的存储沙箱,没有其他应用可以直接访问您应用的沙盒文件。由于文件是私有的,因此访问这些文件不再需要任何权限。
并且 Android Q 推荐了获取外部存储私有文件的最佳位置:即Context.getExternalFilesDir()返回的位置,因为此位置在所有Android版本中表现一致。使用此方法时,请传入与要创建或打开的文件类型对应的媒体环境。例如,要访问或保存app-private图像,请调用Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)。
-
定义公共媒体集合:Photos & Videos、Music、 Downloads。
-
APP 无需请求任何权限即可在这些共享集合中创建和修改自己的文件。
-
如果你的APP想创建和修改其他应用已创建的文件,则必须首先请求相应的权限:
访问Photos & Videos目录的其他应用程序文件 需要请求 READ_MEDIA_IMAGES 或 READ_MEDIA_VIDEO 权限,具体取决于您的应用程序需要访问的文件类型。
访问 Music 共享集合中的其他应用程序文件需要 READ_MEDIA_AUDIO 权限。
没有访问Downloads共享集合的权限,您的应用可以访问此集合中自己的文件。但是,要访问此集合中的其他应用程序文件,您必须允许用户使用系统的文件选择器应用程序选择文件。
访问共享集合通过 MediaStore API ,如 MediaStore.Images、MediaStore.Video、MediaStore.Audio、MediaStore.Downloads。
需要注意的是:对于 Android Q 上新安装的应用,对 getExternalStoragePublicDirectory()的调用仅提供对应用已存储在其隔离存储沙箱中的文件的访问权限。要保持对其他应用程序文件的访问权限,请更新应用程序的逻辑以使用MediaStore。
一些照片在其数据中会包含位置信息,允许用户查看拍摄照片的位置。由于此位置信息是敏感的,因此我们想获取位置信息需要以下几步:
-
将新的 ACCESS_MEDIA_LOCATION 权限添加到AndroidManifest。
-
获取位置信息
photoUri = MediaStore.setRequireOriginal(photoUri);
InputStream stream = getContentResolver().openInputStream(photoUri);
//从流中读取位置信息
target API 级别等于 Android Q 的应用,或者在运行Android Q 的设备上新安装的应用默认都会采取新的权限策略
如果你的APP同时满足以下两个条件,则会兼容以前的权限策略:
- targetSdkVersion <= Android 9
- 你的应用安装在从 Android 9 升级到 Android Q 的设备上
Android Q 为每个外部存储设备提供唯一的卷名。
//获取卷名方式
Set<String> volumeNames = MediaStore.getAllVolumeNames(context);
Android Q 对应用未经通知用户就启动进行了极大地限制,在Android Q上运行的应用只有在满足以下一个或多个条件时才能启动活动:
- 该APP具有可见窗口,例如有前台Activity
- 位于前台的另一个 APP 发送属于该应用程序的 PendingIntent。
- 系统发送属于该 APP 的PendingIntent,例如点击通知。
- 系统向应用程序发送广播,例如SECRET_CODE_ACTION。只有应用程序预期启动UI的特定广播才免除。
此行为更改适用于在 Android Q 上运行的所有应用,甚至是针对Android 9(API级别28)或更低级别的应用。但是,只要您的应用以用户互动的直接结果开始活动,您的应用很可能不会受到此更改的影响。实际上,大多数应用程序都不受此更改的影响。
此外,Android Q 建议我们 后台应用程序都应创建通知,以便向用户提供信息,而不是直接启动活动。
一些特殊情况如:来电或者警报,需要立刻启动 Activity,则可以通过创建高优先级的通知,并提供 fullscreen itent。如何创建高优先级通知?
用户可以更好地控制应用何时可以访问设备位置。当在Android Q上运行的应用程序请求位置访问时,会通过对话框的形式给用户进行授权提示。此对话框允许用户授予对两个不同范围的位置访问权限:在使用中(仅限前台)或始终(前台和后台)。
如果你的应用针对 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)或更低版本,则会出现以下行为:
- 如果你的应用为 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 声明 标记,则系统会在安装期间自动为ACCESS_BACKGROUND_LOCATION 添加 标记。
- 如果你的应用请求 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION,系统会自动将 ACCESS_BACKGROUND_LOCATION添加到请求中。
- 虽然你的应用可以请求并接收 ACCESS_BACKGROUND_LOCATION,但用户可以通过选择您的应用仅应在前台访问位置信息来撤消此权限。
影响在Android Q 上运行的所有应用的更改:
从Android Q开始,该平台不再跟踪联系人亲缘关系信息。因此,如果您的应用对用户的联系人进行搜索,则结果不再按交互频率排序。 “联系人提供程序”指南包含一个通知,说明自Android Q起所有设备上已废弃的特定字段和方法。
在Android Q 运行的设备默认传输随机的MAC 地址,获取随机MAC地址API:WifiConfiguration.getRandomizedMacAddress()
获取实际硬件MAC地址:WifiInfo.getFactoryMacAddress()。
应用必须具有 READ_PRIVILEGED_PHONE_STATE 特权权限才能访问设备的不可重置标识符,包括IMEI和序列号。原则上 Android Q 建议避免使用更容易关联到个人的硬件标识符,而是使用实例ID。实例ID的做法推荐
除非您的应用程序是默认输入法编辑器或当前具有焦点的应用程序,否则您的应用程序无法访问剪贴板数据。
影响针对 Android Q API 级别运行的应用的更改:
如果您的应用针对Android Q,则您的应用只能在用户授予您访问USB设备或配件的应用权限后才能读取序列号。
影响在Android Q 上运行的所有应用的更改:
Android Q更改了默认情况下getCameraCharacteristics()方法返回的信息的广度。特别是,您的应用必须具有CAMERA权限才能访问此方法的返回值中包含的潜在设备特定元数据。
在Android Q上运行的应用无法启用或停用Wi-Fi。 WifiManager.setWifiEnabled()方法始终返回false。 如果需要,请使用设置面板提示用户启用和禁用Wi-Fi。
影响针对 Android Q API 级别运行的应用的更改:
除非您的应用具有ACCESS_FINE_LOCATION权限,否则在Android Q上运行时,您的应用无法在Wi-Fi,Wi-Fi Aware或蓝牙API中使用多种方法。要查看受影响方法的列表,请参阅隐私附录。
将Wi-Fi网络列表的手动配置限制在系统应用程序中。如果您的应用针对Android Q,则以下方法不再返回有用数据,下面方法将不会返回有效信息:
- getConfiguredNetworks()方法始终返回空List
- addNetwork()和updateNetwork() - 始终返回-1
- 返回布尔值的每个网络操作 - removeNetwork(),reassociate(),enableNetwork(),disableNetwork(),reconnect()和disconnect() - 始终返回false
针对 Android Q API 级别运行的应用,Android Q为需要检测用户移动的应用程序(例如步行,骑自行车或车辆)引入了新的ACTIVITY_RECOGNITION运行时权限。这旨在让用户了解设置中如何使用设备传感器数据。
最令我们关心的,还是我们的适配工作。下面,分两部分讲:
为了确保应用稳定性和兼容性,Google 在 Android O 中开始限制使用哪些非SDK接口(API级别28)。 Android Q 更新了非SDK接口的限制列表,并且修改了限制规则。
1.灰名单修改:在Android 9(API级别28)中,灰名单分为以下两个列表:
(1)lightgrey列表: targetSdkVersion<28 情况下可以使用的非SDK接口
(2)darkgrey list:targetSdkVersion>=28 情况下无法使用的非SDK接口
在 Android Q 中,我们现在将这两个列表统称为 greylist(灰名单),但是受目标API级别限制:
如在 Android P 中被限制的黑灰色名单:darkgrey list 现在叫做 greylist-max-o,
在 Android Q 中被限制的非SDK接口应该称为 greylist-max-p
2.代码注释修改:引入以下注解来区别哪些非SDK接口在哪个API做了限制
@UnsupportedAppUsge 无限制的灰名单
@UnsupportedAppUsage(maxTargetSdk = 0) 黑名单,哪个API都不能调用
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O) API <= Android O 可以调用
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) API <= Android P 可以调用
Android Q 非SDK接口限制列表过长,这里直接附上查询地址
在 Android Q 上,与 Wi-Fi Direct 功能相关的广播不再具有粘性。如果你的 APP 依赖于在注册时接收这些广播,可以在初始化时使用适当的get()方法来获取信息,具体可参考 WifiP2pManager 类相关方法。
在Android Q(Go版)设备上运行的应用无法接收SYSTEM_ALERT_WINDOW权限。这是因为绘制叠加窗口使用过多的内存,这对低内存Android设备的性能特别有害。
如果你的应用将targetSdkVersion设置为“android-Q”或更高版本,则下面的你需要注意了。
灰名单变更参考“针对所有运行在 Android Q 上的app的行为变更”的策略,意味着@UnsupportedAppUsage(maxTargetSdk < Build.VERSION_CODES.Q) 的非API方法你都需要注意了!!!
针对Q的应用不能再直接使用ashmem(/ dev / ashmem),而必须通过NDK的ASharedMemory类访问共享内存。此外,应用程序无法直接对现有的ashmem文件描述符进行IOCTL,而必须使用NDK的ASharedMemory类或Android Java API来创建共享内存区域。在使用共享内存时,此更改可提高安全性和稳健性,从而提高Android整体的性能和安全性。
Android运行时(ART)不再从应用程序进程调用dex2oat。此更改意味着ART将仅接受系统生成的OAT文件。
使用全屏Intent通知的应用必须在其应用的 Manifest 文件中请求 USE_FULL_SCREEN_INTENT 权限,这是正常权限,因此系统会自动授予。 如果针对Android Q或更高版本的应用尝试在不请求USE_FULL_SCREEN_INTENT权限的情况下创建具有全屏的Intent,系统将忽略全屏意图。