天天看點

Android 程式設計下 App Install Location

從 API 8 開始(參考官方文檔:App Install Location | Android Developers),你可以将你的應用安裝在外部儲存中(例如,安裝到裝置的 SD 卡上)。這是一個可選的特征,你可以在你的應用的 AndroidManifest.xml 中聲明 android:installLocation 屬性。如果你沒有聲明這個屬性,你的應用程式将會被安裝在内部儲存,并且不能被移到外置儲存中。

修改 AndroidManifest.xml 檔案中 <manifest> 元素下的 android:installLocation 屬性,指派為 “preferExternal” 或 “auto”,即可允許系統将應用安裝到外部存儲中。代碼如下:

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

如果 android:installLocation 屬性聲明為 preferExternal,意味着你要求應用程式安裝在外置儲存,但是系統不保證你的程式一定會被安裝在外部儲存中。如果外部儲存空間已滿,程式将會被安裝在内部儲存。使用者也可以在兩個儲存之間移動你的應用程式。如果聲明了 auto,表明你的應用程式可以安裝在外部儲存,但是你沒有一個安裝位置的偏好。系統會根據一些因素來決定你的應用程式安裝在哪。使用者也可以在兩個儲存之間移動你的程式。

當你的應用被安裝在外部儲存時:

  • 隻要外部存儲一直挂載在裝置上,就不會對應用的性能造成影響。
  • .apk 檔案會儲存在外部儲存中,但所有私有的使用者資料,資料庫,優化的 .dex 檔案,和提取的本地的代碼都會儲存在内部儲存中。
  • 存儲應用的特定容器被一個随機生成的 Key 加密,并且隻能被最初安裝這個應用的裝置解密。這樣就可以保證一個安裝在 SD 卡上的應用隻為唯一的裝置服務。
  • 使用者可以通過系統設定将應用移到内部儲存中。

▐ 注意:當使用者啟用 USB 大容量存儲與電腦共享檔案或通過系統設定解除安裝 SD 卡時,外部存儲就會從裝置解除安裝同時所有運作在外部存儲的應用會被立即殺死。

Backward Compatibility

隻有在運作 API 8(Android 2.2)或更高版本的裝置上才可以将應用安裝到外部存儲中,在 API 8 之前建立的應用隻能被安裝到内部存儲中,并且不能移動到外部存儲中(即使在 API 8 的裝置上)。如果要求應用支援 API < 8 的裝置,你可以讓運作 API  >= 8 的裝置使用這個特性,也可通過如下的設定來相容 API < 8 的裝置。

  1. 在 AndroidManifest.xml 檔案 <manifest> 元素中設定的 android:installLocation 屬性為 auto 或 perferExternal。
  2. 保持  android:minSdkVersion 屬性不變(一個小于8的數)并保證你應用代碼所使用的 API 與之相符。
  3. 在編譯你的應用之前,将  build target 的 API 級别修改為 8。因為低版本的 Android 庫不識别 android:installLocation 屬性,是以也就不會在該屬性存在的情況下編譯應用。

當你的應用安裝在一個運作 API < 8 的裝置上時,android:installLocation 屬性會被忽略,并且應用程式會被安裝到内部存儲中。

▐ 注意:盡管通過 XML 标記可以讓低版本的平台忽略這個問題,但仍然要小心的是,當 minSdkVersion < 8 的時候,不要在程式設計過程中引入級别為 8 的 API,除非你的代碼需要向後相容。

Applications That Should NOT Install on External Storage

當使用者啟用 USB 大容量存儲與計算機共享檔案(通過其他方式解除安裝或移除外部存儲),任何安裝在外部存儲并正在運作的程式都會被殺死。直到大容量存儲處于不可用狀态,外部存儲重新被挂載到裝置上,系統才會識别這些應用。除了殺死應用使得它對使用者不可用之外,還會通過一些更危險的方式破壞某些類型的應用程式。如果你的應用使用了如下特征,會在外部存儲解除安裝的時出現引用問題,是以你應該禁止你的應用安裝在外部存儲中。

服務(Services)

正在運作的服務會被殺死,并且在外部存儲被重新挂載後也不會重新開機。但是你可以注冊一個 ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 的廣播,這樣應用程式就可以在外置存儲可用時接收到通知并重新開機服務。

警報服務(Alarm Services)

使用 AlarmManager 注冊的 Alarm Services 将被取消。你必須在外置存儲被重新挂載的時候重新手動的注冊 Alarm Services。

輸入法引擎(Input Method Engines)

你的 IME 将會被替換為預設的 IME。當外部存儲重新挂載的時候,使用者可以在系統設定中激活自己的 IME。

動态桌面(Live Wallpapers)

動态桌面會被替換為預設的動态桌面。外部存儲重新挂載的時候,使用者可以重新選擇自己之前的桌面。

視窗小部件(App Widgets)

應用程式的 App Widget 會被移除,即使外部存儲重新被挂載,使用者也無法使用該應用的 App Widget,除非系統重置 Home 應用(通常要等到系統重新開機)。

賬戶管理器(Account Managers)

通過 AccountManager 建立的賬戶會消失,直到外部存儲重新挂載後在可用。

同步擴充卡(Sync Adapters)

AbstractThreadedSyncAdapter 以及它的一切異步方法将停止工作,同樣也的等到外部存儲重新挂載後才能恢複正常。

裝置管理者(Device Administrators)

你的 DeviceAdminReceiver 及其所有管理功能将被禁用,這可能對裝置造成不可預見的後果。

監聽“啟動完成”的廣播接收者(Broadcast Receivers listening for "boot completed")

系統會在外部存儲挂載到裝置之前發出 ACTION_BOOT_COMPLETED 廣播。如果你的應用程式安裝在外部存儲器,它永遠不會收到此廣播。

如果你的應用程式使用了上面列出的功能,你不應該允許你的應用安裝到外部存儲。預設情況下,系統将不允許你的應用安裝到外部存儲,是以你不需要擔心你現有的應用程式。然而,如果你非常确定你的應用不應該安裝到外部存儲,那麼你應該聲明 android:installLocation 的值為 “internalOnly”。但這并不會改變預設的行為,它隻是很明确的提醒你和其他的開發者這個應用隻應該被安裝在内部存儲中。

Applications That Should Install on External Storage

簡單來說,隻要你的應用沒有使用上節中列出的特性,那麼安裝到外部存儲中就是安全的。大型遊戲通常會允許安裝到外部存儲中,因為遊戲通常不會在閑置狀态提供額外的服務。當外部存儲不可用時,遊戲程序會被殺死,當外置儲存變得可用而且使用者重新開機遊戲時,不應該有明顯的影響(假設遊戲在它正常的 Activity 生命周期适當的儲存了狀态)。

如果你應用程式的 APK 檔案占用很大位元組的存儲空間,你應該仔細的考慮是否将應用安裝到外部存儲中,以便為使用者節省内部存儲空間。

專注移動網際網路産品設計研發 分享最新的移動網際網路産品和技術

app

繼續閱讀