当前位置: 代码迷 >> 综合 >> 1203 - 数据存储 - 应用安装位置
  详细解决方案

1203 - 数据存储 - 应用安装位置

热度:34   发布时间:2023-12-16 19:18:40.0

应用安装位置

来源:Android Develop - API Guides - Data Storage - App Install Location

自 API Level 8 开始,我们可以让应用安装在 external storage (例如:设备的SD卡)中,在AndroidManifest文件中声明明 android:installLocation 属性可以实现这个功能。如果没有声明这个属性,应用就只能安装在 internal storage 中且不能被移到 external storage 中。

为了能让系统在 external storage 中安装应用,我们需要在AndroidManifest文件中加入 android:installLocation 属性,其值为 "preferExternal" 或"auto"。例如:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"android:installLocation="preferExternal"... >

如果声明为 "preferExternal", 表示我们对系统请求将应用安装到 external storage 中,但是系统并不能保证将应用安装到  external storage 中,如果 external storage 为空,系统会将应用安装到 internal storage 中,而用户可以将应用随意移动到 external storage 或者 internal storage 中。

如果声明为 "auto",表示我们并不关注应用是安装到了 external storage 中还是 internal storage 中,系统就会根据几点因素来决定应用被安装到哪里,而用户也可以将应用随意移动到 external storage 或者 internal storage 中。

当应用被安装到 external storage 之后:

  • 只要 external storage 被挂载到设备上,那么应用的执行将不会受到任何影响。
  • 应用的.apk 文件被存储到 external storage 中,但是应用所有的私有用户数据,数据库、.dex 文件以及提取的本地代码会被存储到手机内部存储中。
  • 应用存储的空间会被随机生成的密钥加密,只有安装应用的设备才能对其进行解密。因此,安装在SD卡中的应用也只能在安装应用的设备上运行。
  • 通过系统设置,用户可以将应用移动到 internal storage 。

提醒: 当用户使用USB将设备与电脑进行文件传输或者SD卡未挂载到手机上时,那么 external storage 也会从设备上卸载并且所有运行在其中的应用会被马上kill掉。

低版本兼容问题


应用可以安装到 external storage 的特性需要设备的版本为 API Level 8 (Android 2.2) 或者更高。 在 API Level 8 版本之前编译的应用只能安装在 internal storage 中并且不能被移动到external storage (即便设备的版本高于 API Level 8)。然而,如果应用设计为支持低于API Level 8版本的设备,那就需要让低于API Level  8 的版本兼容该特性。

为了使低于API Level  8 的版本兼容应用可以安装到 external storage 的特性,需要做到:

  1. 在 <manifest> 元素中加入 android:installLocation 属性,其值为 "auto" 或者 "preferExternal" 。
  2. 需要有这个 android:minSdkVersion 属性 (要比 "8" 更低) 并且确保应用使用了兼容这个版本的APIs。
  3. 编译应用时要将编译目标版本改为 API Level 8,因为旧的Android库不识别 android:installLocation 属性并且在这个属性存在时不能兼容。

当应用安装到低于 API Level  8 的设备上时, android:installLocation 属性会被忽视并且应用会被安装到internal storage 中。

提醒: 尽管在低版本的环境中这个 XML 属性会被忽略,但当 minSdkVersion 小于8时你也尽量不要使用API Level 8的APIs,除非必须要让代码兼容某个特性。

不应该安装到 External Storage 中的应用


当用户使用USB与电脑进行文件传输时 (或者是卸载了 external storage), 任何安装在 external storage 中且正在运行中的应用都会被kill掉。直到与电脑的文件传输模式终止 external storage 重新挂载到设备上为止,这些应用都会变成无响应状态。除了会kill掉这些应用以及使其对用户不可用之外,这还会对几种类型的应用造成更严重的影响。因此为了让应用按照预期执行,我们不应该将包含了以下功能的应用安装到 external storage 中以避免在 external storage 被卸载之后引起下述可能出现的后果。

服务
正在运行的  Service 会被 kill 掉,并且在 external storage 重新装载时不会重启,不过我们可以注册 ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 广播,当安装  external storage 的应用对系统而言重新变得可用时会发出这条广播来提醒应用,这时,我们可以重启 Service 。
闹钟服务
注册在  AlarmManager 的闹钟会被取消。 在  external storage 重新装载时,必须要手动注册被取消的闹钟。
输入法
应用的  IME (输入法)会被默认的输入法代替。当 external storage 重新装载时,用户可以打开系统设置来启用你的输入法
动态壁纸
正在运行的  Live Wallpaper (动态壁纸)会被默认的动态壁纸所代替。 当  external storage 重新装载时, 用户可以再次选择你的动态壁纸。
应用小部件
应用的  App Widget ( 应用小部件)会被主屏幕移除 当  external storage 重新装载时,  在系统重置 home 应用之前(通常需要重启),你的应用小部件对于用户而言处于不可用状态。
账户管理
应用使用  AccountManager 创建出来的账户会消失知道 external storage 重新装载。
同步适配器
在  external storage 被重新装载之前,应用的 AbstractThreadedSyncAdapter 以及其所有同步功能都不可用。
设备管理器
应用的  DeviceAdminReceiver 及其管理的所有功能都会不可用,这会对设备造成不可预知的后果,即便 external storage 被重新装载,后果也依然会持续。
监听开机广播
 external storage 被装载到设备上之前,系统就会发出  ACTION_BOOT_COMPLETED 广播,如果应用安装到了 external storage 中,那么 应用将永远无法收到开机广播。

如果应用使用了上述特性,那么就不应该将应用安装到 external storage 中。系统不会默认将应用安装到 external storage 中,然而,如果要保证应用不会被安装到 external storage 中,我们应该声明 android:installLocation 属性的值为  "internalOnly"。尽管这不会改变系统安装应用的默认位置,但它明确声明了应用仅仅应该安装到 internal storage 中并且将此设置暗示给了其他开发者。

应该安装到 External Storage 中的应用


简单来说,任何没有用到上一节提到的那些功能的应用安装到 external storage 之后都是安全的。 大型游戏通常应该安装到 external storage ,因为游戏在不用的时候一般不会提供什么额外的服务。当external storage 不可用游戏被 kill 掉之后,再重新装载 external storage 然后重启游戏,也不会出什么什么比较明显的影响 (需要游戏在Activity正常的生命周期中合适地保存了它的状态)。

如果应用需要几百万字节大小的APK文件,你应该谨慎决定是否需要将应用安装到 external storage 来为用户节省 internal storage 空间。