安卓 11 来了,快!扶我起来,音视频开发书籍
在 SDK Platforms 标签页下,选择窗口底部的 Show Package Details。
在 Android 11 Developer Preview 下,选择系统映像(例如 Google APIs Intel x86 Atom System Image)。
在 SDK Tools 标签页中,选择最新版 Android 模拟器,点击 OK 开始安装。
安装完成后,依次选择 Tools > AVD Manager,然后按照说明[创建新的 AVD](
)。
请务必选择 Pixel 设备,并对系统映像选择 R。
返回 AVD 管理器的虚拟设备列表,双击新虚拟设备即可启动该设备。
“万事俱备,只欠适配了!”
这里就不写刷 OTA 的具体步骤了,需要的可以[自行下载和刷写](
)。
[](
)正文
“来了来了,开始了,别说话了,安静!!!”
[](
)分区存储
还记得在适配安卓 10 的时候设置 requestLegacyExternalStorage 为 true 来修改外部存储空间视图模型(true 为 Legacy View,false 为 Filtered View)吗?这是重点:当您将应用更新为以 Android 11 为目标平台后,将无法使用 requestLegacyExternalStorage
来停用分区存储。
“大哥,这都停用了那我该怎么适配呢?”
“这孩子,猴急猴急的,这不就要说了嘛!”
[](
)数据迁移到使用分区存储时可见的目录:
在以 Android 11 为目标平台之前,应将数据迁移到与分区存储兼容的目录。在大多数情况下,可以将数据迁移到应用的[应用专用目录](
)。
如果有要迁移的数据,当用户升级到以 Android 11 为目标平台的新版应用时,可以保留旧版存储模型。这样,用户就可以保留对应用之前用来保存数据的目录中存储的应用数据的访问权限。要启用旧版存储模型以进行升级,请在应用的清单中将 [preserveLegacyExternalStorage
](
) 属性设为 true
。
这里需要注意以下两点:
大多数应用都不需要使用
preserveLegacyExternalStorage
。此标记仅适用于这样一种情况:你将应用数据迁移到了与分区存储兼容的位置,并且希望用户在更新你应用时保留对数据的访问权限。使用此标记会导致更难以测试分区存储对应用的用户有何影响,因为当用户更新应用时,它会继续使用旧版存储模型。如果使用
preserveLegacyExternalStorage
,则旧版存储模型只在用户卸载应用之前保持有效。如果用户在搭载 Android 11 的设备上安装或重新安装应用,则无论preserveLegacyExternalStorage
的值是什么,应用都无法停用分区存储模型。
[](
)测试分区存储
如果要在应用中启用分区存储,而不考虑应用的目标 SDK 版本和清单标记值,请启用以下应用兼容性标记:
[
DEFAULT_SCOPED_STORAGE
](
)(默认情况下,对所有应用处于启用状态)
[
FORCE_ENABLE_SCOPED_STORAGE
](
)(默认情况下,对所有应用处于停用状态)
要停用分区存储而改用旧版存储模型,请取消设置这两个标记。
[](
)管理设备存储空间
如果你的应用是文件管理器应用并且在 Android 11 上运行,它就不能再删除其他应用的缓存文件,即使您的应用具有[所有文件访问权限](
)也是如此(清理文件的应用尤其需要注意,比如某某管家、卫士啥的)。相反,你应执行以下操作:
通过调用 [
ACTION_MANAGE_STORAGE
](
) intent 操作来检查可用空间。
如果设备上的可用空间不足,请提示用户同意让您的应用清除所有缓存。为此,请调用
ACTION_CLEAR_APP_CACHE
intent 操作。
这里需要注意:ACTION_CLEAR_APP_CACHE
intent 操作会严重影响设备的电池续航时间,并且可能会从设备上移除大量的文件。
[](
)媒体文件访问权限
这个很赞,Android 11 增加了以下访问媒体功能。
[](
)执行批量操作
为实现各种设备之间的一致性并增加用户便利性,Android 11 向 [MediaStore
](
) API 中添加了多种方法。对于希望简化特定媒体文件更改流程(例如在原位置编辑照片)的应用而言,这些方法尤为有用。
添加的方法如下:
[
createWriteRequest()
]([developer.android.google.cn/reference/a…](
)(android.content.ContentResolver, java.util.Collection))
用户向应用授予对指定媒体文件组的写入访问权限的请求。
[
createFavoriteRequest()
]([developer.android.google.cn/reference/a…](
)(android.content.ContentResolver, java.util.Collection, boolean))
用户将设备上指定的媒体文件标记为“收藏”的请求。对该文件具有读取访问权限的任何应用都可以看到用户已将该文件标记为“收藏”。
[
createTrashRequest()
]([developer.android.google.cn/reference/a…](
)(android.content.ContentResolver, java.util.Collection, boolean))
用户将指定的媒体文件放入设备垃圾箱的请求。垃圾箱中的内容在特定时间段(默认为 7 天)后会永久删除。
[
createDeleteRequest()
]([developer.android.google.cn/reference/a…](
)(android.content.ContentResolver, java.util.Collection))
用户立即永久删除指定的媒体文件(而不是先将其放入垃圾箱)的请求。
系统在调用以上任何一个方法后,会构建一个 [PendingIntent
](
) 对象。应用调用此 intent 后,用户会看到一个对话框,请求用户同意应用更新或删除指定的媒体文件。
[](
)使用原始路径访问文件
从 Android 11 开始,具有 [READ_EXTERNAL_STORAGE
](
) 权限的应用可以使用直接文件路径和原生库来读取设备的媒体文件。通过这项新功能,应用可以更顺畅地使用第三方媒体库。
[](
)文件和目录访问限制
以下与存储访问框架 (SAF) 相关的变更只有在应用以 Android 11 为目标平台时才会生效。
[](
)访问目录
无法再使用 [ACTION_OPEN_DOCUMENT_TREE
](
) intent 操作来请求访问以下目录:
Downloads
根目录。设备制造商认为可靠的各个 SD 卡卷的根目录,无论该卡是模拟卡还是可移除的卡。
[](
)访问文件
无法再使用 ACTION_OPEN_DOCUMENT_TREE
或 [ACTION_OPEN_DOCUMENT
](
) intent 操作来请求用户从以下目录中选择单独的文件:
Android/data/
目录及其所有子目录。Android/obb/
目录及其所有子目录。
[](
)权限
不管应用的目标 SDK 版本是什么,以下变更均会在 Android 11 中生效:
存储运行时权限已重命名为文件和媒体。
如果应用未停用[分区存储](
)并且请求 [READ_EXTERNAL_STORAGE
](
) 权限,则用户会看到不同于 Android 10 的对话框。该对话框会指示应用正在请求访问照片、视频、音频剪辑和文件。
用户可以在系统设置中查看哪些应用具有
READ_EXTERNAL_STORAGE
权限。在设置 > 隐私 > 权限管理器 > 文件和媒体页面上,具有该权限的每个应用都列在允许存储所有文件下。
这里要注意:如果应用以 Android 11 为目标平台,切记,对“所有文件”的这种访问权限是只读访问权限。要使用此应用读取和写入[共享的存储空间](
)中的所有文件,需要具有[所有文件访问权限](
)。
[](
)所有文件访问权限
某些应用的核心用例需要访问大量的文件,如文件管理操作或备份和恢复操作。这些应用可通过执行以下操作来获取“所有文件访问权限”:
声明 [
MANAGE_EXTERNAL_STORAGE
](
) 权限。
使用 [
ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
](
) intent 操作将用户引导至一个系统设置页面,在该页面上,用户可以为应用启用以下选项:授予所有文件的管理权限。
“所有文件访问权限”可授予以下权限:
对[共享的存储空间](
)内所有文件的读写访问权限。
对 [
MediaStore.Files
](
) 表的内容的访问权限。
应用可以使用 [MediaStore
](
) API 或[原始文件路径](
)来访问这些文件。如果应用使用[存储访问框架](
),不能使用它来访问“所有文件访问权限”提供的其他文件和目录。获得此权限的应用仍然无法访问属于其他应用的[应用专用目录](
)。这些目录在存储卷上显示为 Android/data/
的子目录。
[](
)自定义消息框视图被屏蔽
出于安全方面的考虑,同时也为了保持良好的用户体验,如果包含自定义视图的消息框是以 Android 11 为目标平台的应用从后台发送的,则系统会屏蔽这些消息框。请注意,仍允许使用文本消息框;此类消息框是使用 [Toast.makeText()
](
) 创建的,并不调用 [setView()
](
)。
如果您的应用仍尝试从后台发布包含自定义视图的消息框,则系统不会向用户显示相应的消息,而会执行以下操作:
显示以下消息框消息:
Background custom toast blocked for package package-name. See g.co/dev/toast.
在 logcat 中记录以下消息:
W/NotificationService: Blocking custom toast from package due to package not in the foreground
如果希望在消息框(文本消息框或自定义消息框)出现或消失时收到通知,请使用新的 [addCallback()
](
) 方法。
这里需要注意,由于平台行为发生了变更,以 Android 11 为目标平台的应用会发现文本消息框受到以下负面影响:
[
getView()
](
) 方法返回 null
。
以下方法的返回值并不反映实际值,因此尽量别使用:
[
getHorizontalMargin()
](
)
[
getVerticalMargin()
](
)
[
getGravity()
](
)
[
getXOffset()
](
)
[
getYOffset()
](
)
以下方法是空操作,因此应用不应使用:
[
setMargin()
]([developer.android.google.cn/reference/a…](
)(float, float))
[
setGravity()
]([developer.android.google.cn/reference/a…](
)(int, int, int))
[](
)前台服务类型
从 Android 9 开始,应用仅限于[在前台](
)访问摄像头和麦克风。为了进一步保护用户,Android 11 更改了前台服务访问摄像头和麦克风相关数据的方式。如果应用以 Android 11 为目标平台并且在某项前台服务中访问这些类型的数据,则需要在该前台服务的声明的 foregroundServiceType
属性中添加新的 camera
和 microphone
类型。
来举个例子吧,如果应用中的某项前台服务需要访问与设备的位置信息和摄像头相关的数据,请按以下代码段所示声明该服务:
<manifest>
...
<service ... android:foregroundServiceType="location|camera" />
</manifest>
复制代码
评论