应用安装位置

从 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> 元素中添加 android:installLocation 属性,该属性的值为“auto”或“preferExternal”。
  2. 保持 android:minSdkVersion 属性不变(例如低于“8”),并确保应用代码仅使用与该级别兼容的 API。
  3. 为了编译应用,请将构建目标更改为 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>