開始使用 Android OBB 擴充程式檔(APK Expansion Files)

Terry Huang
安郡尼爾筆記
Published in
7 min readMay 21, 2018

iOS 與 Android 目前針對體積較大的 App 程式(常見在遊戲)採用不一樣的限制性。iOS 直接開放了產品上限到 4GB 大小,但如果封裝容量超過 150MB ,便會強制只能在 wifi 環境中下載,此限制有可能會降低下載率,因此也是有相當多的遊戲採用了先安裝,再進行資源檔案下載的做法(順便偷渡 Hot-Fix)。而在 Android 中,如果透過 Google Play 商店來進行上架,則條件相對性的較為限制,主程式 APK 必須在 100MB 以下,若超過則必須先進行擴充程式檔的分裝,才能進行上架。

OBB の 廬山真面目

Android 擴充程式檔使用 OBB 為副檔名(Opaque Binary Blob)。官方提供了 jobb 工具可進行加密的封裝,但並無強制限制其格式。

Android 官方設計的擴充程式檔分為 Main 與 Patch 兩個檔案,每個推出的程式版本除了 APK 主程式之外,都能設定一個對應的 Main 以及一個 Patch 擴充程式檔。

Main 為主要的擴充程式檔,用來存放不易變動的資源;Patch 則是擴充修補程式檔,用來進行較有變動性的資源更新。雙檔案的設計,能有效降低更新程式時耗費的流量與系統負荷。兩個檔案各有 2GB 的大小限制。

[main|patch].<expansion-version>.<package-name>.obb

在命名時,以 main 或是 patch 開頭。後續接上 expansion-version,package name 與副檔名。expansion-version 為擴充程式檔的版本號,預設與程式的 versionCode 為對應,但是由於 Google Play 在上架新版本程式時,可選用舊版本的程式擴充檔延續使用,可降低更新的負擔,但卻有可能會造成程式 versionCode 是 N 但是擴充程式檔版本號卻是 <N 的狀況,需特別注意。

主程式如何牽手擴充程式檔

在 Google Play 商店中,當您準備提交新版本時,在上傳主程式 apk 檔案之後、送出提交之前,可於點擊右邊的 + 號來管理這個版本的資源檔。可選擇上傳新檔案,或是用現行版本的程式擴充檔。

點擊 + 號來管理此版本的對應資源檔
擴充檔,可上傳新檔案或是沿用原本的程式檔

在權限管理員面前,沒有自己人

在 Android 6.0 以上,引入了動態的權限管理架構,對於預設存放在外部空間(External Storage)的擴充程式檔案相當不友善,當然在預設的 Android implementation 中(4.4 以上),其實是有 bypass 讀取擴充程式檔需要權限的窘境,但是部分手機製造商基於各種不可描述的理由,支援度並不一致,導致部分手機又需要先取得權限才能讀取。

因此保險起見,在取用擴充程式檔時(通常是一開始),建議還是進行權限需求的判斷,或是直接進行取得 READ_EXTERNAL_STORAGE 權限的步驟:

  • 在 manifest 中宣告權限使用
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  • 確認是否有權限
ContextCompat.checkSelfPermission(AppActivity.getContext(),
Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED
  • 嘗試取得權限
ActivityCompat.requestPermissions(AppActivity.getActivity(),
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_READ_EXTERNAL_STORAGE)
  • onRequestPermissionsResult 判斷是否給予權限
if (requestCode == SystemHandler.REQUEST_READ_EXTERNAL_STORAGE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 取得
} else {
// 未取得
}
return;
}

醒醒吧,不一定會有擴充程式檔

沒錯,即使完成了 Play Store 完整的上架手續,使用者點擊按鈕下載了程式,Play Store 也不保證使用者會能夠將程式與擴充程式檔都下載下來,有時候只會下載了主程式(推測可能是當手機空間不充裕或是網路狀況較差時)。另外,由於擴充程式檔位於 External Storage,所以也可能被使用者或其他 APP 有意無意的刪除。因此透過程式判斷擴充程式檔是否存在,甚至進一步確認完整性,變成了一個必要的程序。

預設的資源檔案位置存放在以下位置:

<shared-storage>/Android/obb/<package-name>/

您可以透過 getExternalStorageDirectory() 來取得外部儲存位址,進而得知完整的路徑;或是直接以 getObbDir() 取得路徑。然後便可在路徑中存取程式擴充檔。

當擴充程式檔和妹妹一樣不存在

當擴充程式檔不存在時,您必須讓程式也能正常的啟動,並進行下載擴充檔的程序,這部分通常需要特別設計一個簡單的介面來進行。

如果您確定您的程式只會透過 Google Play 來發行,那您可以透過 Google Play Application Licensing 來向 Play Store 取得臨時的資源檔案下載鏈結。但是,如果您的程式會透過 APK 散播,或是上架到不支援 Google Play 的國家(你懂的),那則建議您將自行 Hosting 程式擴充檔。

實作下載器可以參考各遊戲引擎,或是參考原生 Android 的官方範例

完整的起手式

當您使用了程式擴充檔,開啟程式時將會需要一套完整的確認和處理程序,包含了讀取權限確認與獲得、OBB 檔案存在確認、OBB 檔案完整性確認、寫入權限確認與獲得、OBB 下載器…等等。

老闆拖欠工資的起手式

相對於完整的起手式,在所有的確認與準備程序中,可先精簡到最少程序來進行測試開發:

  1. 省略權限的需求確認,統一都進行請求
  2. OBB 檔案存在確認,省略下載器,缺失檔案時直接引導使用者重新下載
  3. 直接省略完整性檢查

警告!這樣的做法非常不適合使用在能賺錢的上線產品中!當然,如果加班費沒發則另當別論。

超級好康,限時免費,歡迎下載 ~

《呆呆童書 — 我的家》衝到兒童榜第一名了!
感謝大家一起來支持台灣本土的原創內容

《呆呆童書 — 我的家》限時免費中!
慶祝雙平台上架,5/21~5/25 限時免費(原價90元),
之後還有更多故事會陸續更新,
快把好消息分享給親朋好友吧!

iOS 版本:https://bit.ly/DaiHomeA
Android 版本:https://bit.ly/DaiHomeG

--

--

Terry Huang
安郡尼爾筆記

Co-Founder of LiRise Co.,Ltd. In charge of innovative affairs development. Tags: Guitar, Golf, Photograph, Cocktail, Dance, Diving, Travel.