应用安装位置

从 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 的版本兼容,请执行以下操作:

  1. <manifest> 元素中添加值为“auto”或“preferExternal”的 android:installLocation 属性。
  2. 保持 android:minSdkVersion 属性不变(例如低于“8”),并确保应用代码仅使用与该级别兼容的 API。
  3. 为编译应用,请将构建目标更改为 API 级别 8。此为必要操作,因为较旧的 Android 库不了解 android:installLocation 属性,也不会在存在应用时对其进行编译。

如果在 API 级别低于 8 的设备上安装应用,android:installLocation 属性会被忽略,应用会安装到内部存储设备中。

注意:虽然较早的平台会忽略此类 XML 标记,但您必须小心,除非执行在代码中提供向后兼容性所需的工作,否则不要在 minSdkVersion 低于“8”时使用 API 级别 8 中引入的编程 API。

不应安装到外部存储装置的应用

当用户启用 USB 大容量存储与计算机共享文件(或者卸载或移除外部存储装置)时,安装在外部存储装置上且当前正在运行的任何应用都会遭到终止。在停用大容量存储并在设备上重新安装外部存储装置之前,系统实际上不会注意到应用。除了终止应用并使用户无法使用应用外,这还可能以更严重的方式破坏某些类型的应用。为使应用始终按预期运行,如果应用使用以下任何功能,则您不应允许其安装到外部存储装置,因为卸载外部存储装置时会出现以下引用后果:

Service
正在运行的 Service 会终止,并且重新安装外部存储装置也无法重启。绑定到该服务的应用可以注册 ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 广播 Intent,当安装在外部存储装置的应用再次对系统可用时,该广播 Intent 将通知所有安装在外部存储装置上的应用。收到此广播后,应用可以尝试绑定到您的服务。
闹钟 Service
利用 AlarmManager 注册的闹钟会被取消。重新安装外部存储装置后,您必须手动重新注册所有闹钟。
输入法引擎
您的 IME 会替换为默认 IME。重新安装外部存储装置后,用户可以打开系统设置以再次启用 IME。
动态壁纸
正在运行的动态壁纸会替换为默认动态壁纸。重新安装外部存储装置后,用户可以再次选择您的动态壁纸。
应用微件
您的应用微件会从主屏幕中移除。重新安装外部存储装置后,在系统重置主应用之前(通常在系统重新启动之前),用户无法选择您的应用微件。
帐号管理器
在重新安装外部存储装置之前,使用 AccountManager 创建的帐号会消失。
同步适配器
在重新安装外部存储装置之前,您的 AbstractThreadedSyncAdapter 及其所有同步功能将不起作用。
设备管理器
您的 DeviceAdminReceiver 及其所有管理功能都会停用,这可能会对设备功能产生无法预料的后果,这些后果甚至可能会在重新安装外部存储装置后继续存在。
广播接收器侦听“启动已完成”
在将外部存储装置安装到设备之前,系统会发出 ACTION_BOOT_COMPLETED 广播。如果应用安装在外部存储装置上,其将永远无法接收此广播。

如果您的应用使用上述任一功能,则您不应允许应用安装到外部存储装置。默认情况下,系统允许应用安装到外部存储装置,因此您无需担心现有应用。但是,如果您确定应用绝对不应安装到外部存储装置,则您应该通过声明 android:installLocation 的值为“internalOnly”来明确这一点。虽然这不会更改默认行为,但其会明确指出您的应用只应安装在内部存储设备中,并提醒您和其他开发者系统已作出此决定。

应安装到外部存储装置的应用

简言之,只要不使用前文所列的任意功能,应用安装到外部存储装置时便安全无虞。大型游戏通常属于应允许安装到外部存储装置的应用类型,因为游戏通常不在非活动状态时提供其他服务。如果外部存储装置变得不可用且游戏进程被终止,则当该存储装置再次可用且用户重启游戏时(假设游戏在正常的 Activity 生命周期中正确保存了其状态),便不应产生可见效果。

如果应用需要数兆字节的 APK 文件,则应认真考虑是否允许应用安装在外部存储装置上,以便用户可以保留其内部存储设备上的空间。

如需了解更多相关信息,请参阅:<manifest>