应用程序的安装位置(App Install Location)

从API Level 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 Level 8(Android2.2)以上版本的设备上才有效。既存的创建与API Level 8之前应用程序会始终安装在内部存储器上,并且不能被转移到外部存储器上(即使是在API Level 8的设备上)。

但是,如果你的应用程序被设计成要支持API Level 8以前的版本,你可以选择让这些功能支持API Level 8以上的版本,并且依然兼容API Level 8以前的版本。

以下是允许应用程序安装在外部存储器上,同时保持跟API Level 8以前版本兼容的方法:

  • <manifest>元素中包含带有“auto”或“preferExternal”值的android:installLocation属性。

  • 保留android:minSdkVersion属性,确保该属性值是你的应用程序要兼容的那个API等级。

  • 为了编译你的应用程序,把你的编译目标改变到API Level 8。这是必须的,因为较旧的Android类库不理解android:installLocation属性,所以在这个属性存在的时候不会编译你的应用程序。

当你的应用程序被安装在API Level 8以前版本的设备上时,android:installLocation属性会被忽略,并且该应用程序会被安装在内部存储器上。

注意:尽管像这样的XML标记会被较旧的平台所忽略,但是你要注意在minSdkVersion属性值比8小时,不要使用在API Level 8以前引入的编程API,除非你要执行一些必要的工作,以便让代码提供向后兼容性。

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

当用户启用USB存储器来跟计算机共享文件时(或者是卸载或移除外部存储器),任何被安装在外部存储器上,并且当前正在运行的应用程序都会被杀死。在USB存储器被禁用和外部存储器被重新挂载到设备上之前,系统不会有效的感知到引用程序的存在。除了终止应用程序并让它对用户无效之外,这样做还可以中断某些更严重的应用程序类型。为了让你的应用程序能够像预期的那样,如果它使用了以下功能,你不应该允许你的应用程序被安装在外部存储器上,由于在外部存储器被卸载时,会引发一些后果:

  • Services(服务)

    在外部存储器被卸载时,正在运行的Service将会被终止,而在外部存储器重新被挂载时,它也不会被重启。但是,你可以注册ACTION_EXTERNAL_APPLICATIONS_AVAILABLE类型的广播Intent,当被安装在外部存储器上的应用再次对系统有效时,它会给你的应用程序发通知。这时,你可以重启你的服务。

  • Alarm Services(警告服务)

    使用AlarmManager注册的所有警告将会取消。当外部存储设备重新加载时,用户必须重新手动注册。

  • Input Method Engines(输入法)

    用户的输入法将会由默认的代替。当外部存储设备重新加载时,用户可以通过系统设置重新启用自己的输入法。

  • Live Wallpapers(动态壁纸)

    运行中的动态壁纸将会被默认的动态壁纸代替。当外部存储设备重新加载时,用户可以重新选择动态壁纸。

  • App Widgets(窗口小部件)

    你的AppWidget会被从主屏上删除。当外部存储器被重新挂载时,你的AppWidget不会自动的对用户有效,除非系统重新设置主应用程序(通常会一直到系统重启)。

  • Account Managers(帐号管理)

    你用AccountManager创建的账号,会一直到外部存储器被重新挂载才会显示。

  • Sync Adapters(同步适配器)

    直到外部存储器被重新挂载,你的AbstractThreadedSyncAdapter和所有的异步功能才会工作。

  • Device Administrators(设备管理器)

    你的DeviceAdminReceiver和所有的管理员能力会被禁用,这可能会产生一些不可预知的结果,甚至会持续到外部存储器被重新挂载之后。

  • Broadcast ReceiversListening For “boot completed”(监听“启动完成”的广播接收器)

    在外部存储器被从设备上卸载之前,系统会发送ACTION_BOOT_COMPLETED广播。如果你应用程序被安装在外部存储器上,它就不会接收到这个广播。

  • Copy Protection(复制保护)

    如果你的应用程序使用了GooglyPlay的复制保护功能,你的应用程序不会被安装在设备的SD卡上。但是,如果你使用了GooglePlay的ApplicationLicensing来代替,你的应用程序就可以被安装在内部或外部存储器上,包括SD卡。

如果应用程序包含以上特点,那么用户不应该将应用程序安装在外部存储设备中。 默认情况下,系统不允许将应用程序安装到外部存储设备中,所以用户不用担心已经存在的应用程序。 然而,如果用户非常肯定应用程序永远都不会安装在外部存储设备中,那么用户可以显示地声明android:installLocation属性,并将属性值设为"internalOnly". 尽管这样不会改变系统的默认属性,但是这样非常明确地声明了应用程序只能安装在内存中,给了用户和其他开发者一个明确的提示。

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

简单的说,任何不使用上述所列功能的应用程序安装在外部存储器上是安全的。通常一些大型游戏会允许把应用程序安装在外部存储器上,因为通常游戏在不活动时不会提供额外的服务。当外部存储器无效,且游戏进程被杀死时,不会影响外部存储器再次有效且用户重启游戏时的可视效果(假定游戏在标准的Activity生命周期中正确的保存了它们的状态)。

如果你的应用程序需要几M字节存储空间,你就应该认真考虑是否允许应用程序安装在外部存储器上,以便用户可以保留内部存储的空间。

Copyright© 2020-2022 li-xyz 冀ICP备2022001112号-1