从 API 级别 8 开始,您可以允许将应用安装到外部存储装置(例如,设备的 SD 卡)。您可以使用 android:installLocation
清单属性为您的应用声明此可选功能。如果不声明此属性,应用就只会安装到内部存储设备,并且无法移至外部存储装置。
如需允许系统将您的应用安装到外部存储装置,请修改您的清单文件,以便在 <manifest>
元素中添加 android:installLocation
属性,该属性的值为“preferExternal
”或“auto
”。例如:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="preferExternal" ... >
如果声明“preferExternal
”,表示您请求将应用安装到外部存储装置,不过系统不保证会将应用安装到外部存储装置。如果外部存储空间已满,系统会将应用安装到内部存储设备。用户还可以在两个位置之间移动应用。
如果声明“auto
”,表示您同意可以将应用安装到外部存储装置,但您对安装位置并无偏好。系统会根据多个因素决定应用的安装位置。用户还可以在两个位置之间移动应用。
当应用安装在外部存储装置中时:
- 只要外部存储装置是安装到设备上的,便不会对应用性能产生影响。
.apk
文件保存在外部存储装置中,但所有用户私有数据、数据库、经过优化的.dex
文件和已提取的原生代码都保存在内部设备内存中。- 存储应用的唯一容器使用随机生成的密钥进行加密,该密钥只能由最初安装该应用的设备解密。因此,安装在 SD 卡上的应用仅适用于一台设备。
- 用户可以通过系统设置将应用移至内部存储设备。
警告:当用户通过启用 USB 大容量存储与计算机共享文件时,或通过系统设置卸载 SD 卡时,外部存储装置将从设备中卸载,在外部存储装置上运行的所有应用也将立即终止。
向后兼容性
将应用安装到外部存储装置的功能仅在搭载 API 级别 8 (Android 2.2) 或更高级别操作系统的设备上可用。在 API 级别 8 之前构建的现有应用将始终安装在内部存储设备中,并且无法移至外部存储装置(即使在搭载 API 级别 8 的设备上也是如此)。不过,如果应用的设计目的是支持低于 8 的 API 级别,您可以选择在搭载 API 级别 8 或更高级别操作系统的设备上支持此功能,同时仍与 API 级别低于 8 的设备兼容。
如需允许在外部存储装置中安装应用并仍与低于 API 级别 8 的版本兼容,请执行以下操作:
- 在
<manifest>
元素中添加android:installLocation
属性,该属性的值为“auto
”或“preferExternal
”。 - 保持
android:minSdkVersion
属性不变(例如低于“8”),并确保应用代码仅使用与该级别兼容的 API。 - 为编译应用,请将构建目标更改为 API 级别 8。此为必要操作,因为版本更低的 Android 库不了解
android:installLocation
属性,也不会在存在应用时对其进行编译。
如果在 API 级别低于 8 的设备上安装应用,android:installLocation
属性会被忽略,应用会安装到内部存储设备中。
注意:虽然版本更低的平台会忽略此类 XML 标记,但您必须小心,除非是在代码中提供向后兼容性所必需,否则不要在 minSdkVersion
低于“8”时使用 API 级别 8 中引入的编程 API。
不应安装到外部存储装置的应用
当用户通过启用 USB 大容量存储与计算机共享文件(或以其他方式卸载或移除外部存储装置)时,安装在外部存储装置上且当前正在运行的任何应用都会终止。在停用大容量存储并在设备上重新安装外部存储装置之前,这些应用对系统而言相当于不存在。除了终止应用并使用户无法使用应用外,此举可能还会对某些类型的应用造成更加严重的破坏。为使应用始终按预期运行,如果应用使用以下任何功能,您不应允许将其安装到外部存储装置,因为卸载外部存储装置时会出现下述后果:
- 服务
- 正在运行的
Service
会终止,并且在重新安装外部存储装置后也不会重启。绑定到该服务的应用可以注册ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
广播 intent,当安装在外部存储装置中的应用再次对系统可用时,该广播 intent 将通知所有未安装在外部存储装置上的应用。收到此广播后,应用可以尝试绑定到您的服务。 - 闹钟 Service
- 利用
AlarmManager
注册的闹钟会被取消。重新安装外部存储装置后,您必须手动重新注册所有闹钟。 - 输入法引擎
- 您的 IME 会替换为默认 IME。重新安装外部存储装置后,用户可以打开系统设置再次启用 IME。
- 动态壁纸
- 正在运行的动态壁纸会替换为默认动态壁纸。重新安装外部存储装置后,用户可以再次选择您的动态壁纸。
- 应用微件
- 您的应用微件会从主屏幕中移除。重新安装外部存储装置后,在系统重置主应用之前(通常直到系统重新启动后才会重置),用户无法选择您的应用微件。
- 账号管理器
- 在重新安装外部存储装置之前,使用
AccountManager
创建的账号会消失。 - 同步适配器
- 在重新安装外部存储装置之前,您的
AbstractThreadedSyncAdapter
及其所有同步功能将不起作用。 - 设备管理器
- 您的
DeviceAdminReceiver
及其所有管理功能都会停用,这可能会对设备功能产生无法预料的后果,这些后果甚至可能会在重新安装外部存储装置后继续存在。 - 监听“启动已完成”的广播接收器
- 在将外部存储装置安装到设备之前,系统会发出
ACTION_BOOT_COMPLETED
广播。如果应用安装在外部存储装置上,将永远无法接收此广播。
如果您的应用使用上述任一功能,您不应允许将应用安装到外部存储装置。默认情况下,系统不会允许应用安装到外部存储装置,因此您无需担心现有应用。但是,如果您确定应用绝对不应安装到外部存储装置,那么您应该通过声明值为“internalOnly
”的 android:installLocation
以明确这一点。虽然这不会更改默认行为,但会明确指出您的应用只应安装在内部存储设备中,并提醒您和其他开发者已作出此决定。
应安装到外部存储装置的应用
简言之,只要不使用前文所列的功能,应用安装到外部存储装置时便安全无虞。大型游戏通常属于应允许安装到外部存储装置的应用类型,因为游戏通常不在非活动状态时提供其他服务。如果外部存储装置变得不可用且游戏进程被终止,当该存储装置再次可用且用户重启游戏时(假设游戏在正常的 Activity 生命周期中正确保存了其状态),应该不会有明显的影响。
如果应用需要数兆字节空间供 APK 文件使用,您应认真考虑是否允许应用安装在外部存储装置上,以便用户可以保留其内部存储设备上的空间。
如需了解其他相关信息,请参阅:<manifest>