从API Level 8(Android 2.2)开始,你可以将你的应用程序安装到外部存储上(例如,设备的SD卡)。你可以在应用程序的manifest文件中声明android:installLocation属性来使用这个可选的功能。如果你没有声明这个属性,你的应用程序只能被安装在内部存储中,并且不能移动到外部存储上。
允许系统将你的应用程序安装到外部存储上,你需要修改你的manifest文件。在其中的<manifest>标签下,添加android:installLocation属性,并将值设置为“preferExternal”或者“auto”。例如:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="preferExternal" ... >
如果你声明了“preferExternal”,这就表示请求系统将你的应用程序安装到外部存储中,但是系统不保证一定能将你的应用程序安装到外部存储上。如果外部存储空间已经满了,系统就会将应用程序安装到内部存储上。用户同样可以将你的应用程序在内部和外部存储之间移动。
如果你声明了“auto”,这表明你的应用程序可以安装到外部存储上,但是你没有指定首选的安装位置。系统会根据几个因素来决定将你的应用程序安装到什么位置。用户同样可以将你的应用程序在内部和外部存储之间移动。
当你的应用程序安装在外部存储上:
* 只要外部存储一直挂载在设备上,将应用程序安装在外部存储上对应用程序的性能没有任何影响。
* .apk文件会保存在外部存储上,但是所有用户的私有数据、数据库、优化过的.dex文件,还有附加的本地代码都会保存在内部的设备存储器上。
* 安装了你的应用程序的特定存储器会使用一个随机生成的key进行加密,这个key可以被原来安装这个应用程序的设备解密出来。因此,安装在SD卡上的应用程序只能在一台设备上运行。
* 用户可以用过系统设置将你的应用程序移动到内部存储上。
注意:当用户启用USD设备存储模式与计算机共享文件,或者通过系统设置卸载了SD卡,外部存储将会从设备上被卸载下来,并且所有运行在外部存储上的应用程序都会马上结束被杀死。
1、向后兼容性
只有运行API Level 8(Android 2.2)或者更高版本的设备才允许将你的应用程序安装到外部存储上。已经存在的应用程序,如果是用低于API Level 8版本所编译的,那么这些应用程序只能一直安装在内部存储上,不能移动到外部存储上(即使程序所安装的设备运行的是Android 2.2或以上的版本)。然而,如果你的应用程序必须支持低于API Level 8的版本,你仍然可以为运行API Level 8或者更高版本的设备提供这个功能,并且兼容低于API Level 8版本的设备。
为了允许应用程序安装到外部存储上,并且仍然兼容低于API Level 8的版本,你需要:
1.1 在manifest文件中的<manifest>标签中添加android:installLocation属性,并设置值为“auto”或者“preferExternal”。
1.2 继续保持你的android:minSdkVersion属性(低于版本8的值),并且确保你的应用程序的代码只使用了兼容这个版本的API。
1.3 为了能够编译你的应用程序,将你的android:targetSdkVersion修改为8或者更高的版本。这是必须的,因为旧的Android库不能识别android:installLocation这个属性,这会导致无法编译你的应用程序。
当你的应用程序安装到低于API Level 8版本的设备上,android:installLocation这个属性就会被忽略,应用程序会被安装到内部存储上。
警告:尽管像这样的XML标签在旧版本平台上会被忽略,但当你的minSdkVersion低于“8”时,你要小心不要在代码中使用API Level 8版本才提供的API,除非你进行必要的工作以保证你的代码能够向后兼容(进行版本判断后再执行高版本API等)。
2、不应该安装在外部存储上的应用程序
当用户启用USB存储模式与他们的计算机共享文件(或者直接卸载和移除外部存储器),安装在外部存储上的应用程序会立即被杀死。系统会无法识别这些应用程序,直到USB存储模式关闭并且外部存储重新挂载到设备上。除了杀死应用程序和让用户无法使用这些应用程序之外,这也可能会造成一些类型的应用程序产生更严重的后果。为了保持你的应用程序始终按照预期运行,如果你的应用程序使用了下面列出的功能,你就不应该将应用程序安装在外部存储上,以避免外部存储被卸载的情况:
2.1 Services:你运行的Service会被杀死,并且在外部存储重新挂载后不会重新运行。当然,你也可以注册ACTION_EXTERNAL_APPLICATIONS_AVAILABLE类型的Intent广播,这将会在系统可以重新使用安装在外部存储上的应用程序时通知你的应用程序。接收到广播后,你可以重启的你的Service。
2.2 Alarm Services(闹钟/系统定时服务):你通过AlarmManager注册的闹钟会被取消。你必须在外部存储重新挂载之后手动再注册这些闹钟。
2.3 Input Method Engines(IME,输入法):你的输入法将会被默认的输入法代替。当外部存储重新挂载后,用户可以打开系统设置重新启用你的输入法。
2.4 Live Wallpapers(动态壁纸):你运行的动态壁纸将会被默认的动态壁纸替换。当外部存储重新挂载后,用户可以重新选择你的动态壁纸。
2.5 App Widget(窗口小部件):你的窗口小部件将会从home界面上被移除。当外部存储重新挂载后,你的窗口小部件对于用户同样不可使用,直到系统重置了home上面的应用程序(通常要等到系统重启)。
2.6 Account Manager(账号管理):使用AccountManager创建的账号会消失,知道外部存储重新挂载。
2.7 Sync Adapter(同步适配器):你的AbstractThreadedSyncAdapter和它的同步功能将会停止工作,直到外部存储重新挂载上。
2.8 Device Administrators(设备管理员):你的恶DeviceAdminReceive和它所有的管理权限都会被禁用,这对设备功能可能造成不可预见的后果,并且在外部存储重新挂载后可能还会持续下去。
2.9 监听“设备启动完成”的广播接收器:系统在外部存储挂载到设备上之前就会发布ACTION_BOOT_COMPLETED广播。如果你的应用程序安装在外部存储上,它将无法接收到这个广播。
如果你的应用程序使用上面列出的一些功能,你就不应该允许你的应用程序安装到外部存储上。默认情况下,系统不会允许你的应用程序安装到外部存储上,因此你不用担心你已经发布完成的应用程序。然而,如果你需要确保你的应用程序永远不会被安装到外部存储上,你可以清楚的声明android:installLocation属性,并赋值为“internalOnly”。尽管这不会改变默认的设置,但它可以明确你的应用程序只能安装在内部存储上,并提醒你自己或其他开发者这一个决定。
3、应该安装在外部存储上的应用程序
简单来说,任何没有使用前面所列举功能的应用程序安装到外部存储上都是安全的。大型游戏通常都要允许安装到外部存储上,因为游戏通常不会提供待机时运行的服务。当外部存储不可用的时候,游戏进程会被杀死。当外部存储重新可用并且用户重启了游戏,在视觉界面上应该没有什么影响(假设游戏通过标准的Activity生命周期正确保存了它的状态)。
如果你的应用程序需要几个兆字节的APK文件,你需要仔细考虑是否允许应用程序安装到外部存储上来为用户节省内部存储空间。
原文地址:http://developer.android.com/guide/topics/data/install-location.html