应用安装位置

从 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 或更高的设备支持此功能,并且仍然与使用低于 8 的 API 级别的设备兼容。

要允许安装在外部存储上并保持与低于 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将被终止并且不会重新启动。绑定到此服务的应用程序可以注册ACTION_EXTERNAL_APPLICATIONS_AVAILABLE广播意图,该意图在安装在外部存储上的应用程序再次可用于系统时通知所有安装在外部存储上的应用程序。收到此广播后,应用程序可以尝试绑定到您的服务。
闹钟服务
使用AlarmManager注册的闹钟将被取消。当外部存储设备重新挂载时,您必须手动重新注册所有闹钟。
输入法引擎
您的IME将被默认IME替换。当外部存储设备重新挂载时,用户可以打开系统设置以再次启用您的IME。
动态壁纸
您的正在运行的动态壁纸将被默认动态壁纸替换。当外部存储设备重新挂载时,用户可以再次选择您的动态壁纸。
App小部件
您的App小部件将从主屏幕中移除。当外部存储设备重新挂载时,您的App小部件将不会可供用户选择,直到系统重置主应用程序(通常直到系统重新启动)。
帐户管理器
使用AccountManager创建的帐户将消失,直到外部存储设备重新挂载。
同步适配器
您的AbstractThreadedSyncAdapter及其所有同步功能将无法工作,直到外部存储设备重新挂载。
设备管理员
您的DeviceAdminReceiver及其所有管理员功能将被禁用,这可能会对设备功能产生不可预见的后果,这些后果在外部存储设备重新挂载后可能会持续存在。
侦听“启动完成”的广播接收器
系统在外部存储设备挂载到设备之前传递ACTION_BOOT_COMPLETED广播。如果您的应用程序安装在外部存储设备上,则它永远无法接收此广播。

如果您的应用程序使用上述任何功能,则**不应**允许您的应用程序安装在外部存储设备上。默认情况下,系统不会允许您的应用程序安装在外部存储设备上,因此您无需担心您现有的应用程序。但是,如果您确定您的应用程序永远不应安装在外部存储设备上,则应通过声明android:installLocation的值为"internalOnly" 来明确说明这一点。虽然这不会改变默认行为,但它明确声明您的应用程序只能安装在内部存储上,并提醒您和其他开发人员已做出此决定。

应安装在外部存储上的应用程序

简单来说,任何不使用上一节中列出的功能的应用程序安装在外部存储设备上都是安全的。大型游戏更常见的是应该允许安装在外部存储设备上的应用程序类型,因为游戏在非活动状态下通常不会提供其他服务。当外部存储设备不可用并且游戏进程被终止时,当存储设备再次可用且用户重新启动游戏时,不应该有任何明显的影响(假设游戏在正常的Activity生命周期期间正确保存了其状态)。

如果您的应用程序的APK文件需要几兆字节,则应仔细考虑是否允许应用程序安装在外部存储设备上,以便用户可以节省内部存储空间。

有关其他相关信息,请参阅: <manifest>