Drowsy Dog's Diary

any note, any thought

2014年8月22日
by kazoo
1 Comment

[android] APK Expansion Files

Play Store に登録する Android アプリのサイズ上限は 50MB。
これを超えるサイズのアプリを登録したい場合は、APK Expansion Files という仕組みを使って、別ファイルにアプリを分割することで、最大 4GB までのアプリを登録できる。
こないだ超えてしまったのでこれについて調べた。

先に結論言うとかなりめんどいので、できるだけやらない方がよいと思う。

最近のゲームでよくあるように、小さな APK で起動して、自前のサーバと自前のダウンローダで必要なデータを都度取ってくる仕組みが用意できるなら、もちろん必要はない。

拡張ファイルについて

2種類ある。main と patch。それぞれ最大 2GB。
patch 拡張ファイルはオプション的に、main 拡張ファイルに対して小さな更新を担うイメージ。使うのは main だけでもよい。

それぞれ独立して Google Play に登録でき、APK から使用する拡張ファイルのバージョンを指定できるが、「拡張ファイルだけ」を更新することはできない。拡張ファイルを更新するときは、APK(のバージョンコード)の更新も必要。

拡張ファイルのフォーマットは ZIP, PDF, MP4, etc.何でも可能。また、jobb というコマンドツールが用意されており、これを使ってファイルセットを .obb というひとつの暗号化ディスクイメージのファイルにまとめることができる。obb は Opaque Binary Blob の略。

jobb コマンドは下記にあり、

<ANDROID_SDK_DIR>/tools/jobb

という感じで使う。

  • -pn: アプリのパッケージ名
  • -pv: パッケージのバージョン。ここで指定したものより大きなバージョン(android:versionCode)のアプリが、これをマウントできる
  • -d: 入力ディレクトリ名。これで指定したディレクトリ以下のファイルとサブディレクトリがひとつの obb にまとめられる。-d resource としたとき、解凍すると resource ディレクトリそのものは無いので注意
  • -k: obb を暗号化する場合のパスワードを設定
  • -o: 出力ファイル。名前はなんでもよい

Google Play に拡張ファイルをアップロードすると、ファイルタイプに関係無く以下のフォーマットにリネームされる。

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

上記の例だと、main.4.com.hogehoge.pkgname.obb となる。

拡張ファイルのダウンロード先とマウント

以下に、ダウンローダのサンプルとヘルパーライブラリが用意されている。ファイルパスの取得などはヘルパーを使うのが楽。

<ANDROID_SDK_DIR>/extras/google/play_apk_expansion/downloader_sample/
<ANDROID_SDK_DIR>/extras/google/play_apk_expansion/downloader_library/

ダウンロードされた拡張ファイルは、
<shared-storage>/Android/obb/<package-name>/

以下に保存される。
<shared-storage> は、getExternalStorageDirectory() で取得できるパス。一般的には /sdcard になると思う。<package-name> は前述のパッケージ名と同じ。

アプリは自分が必要な拡張ファイルのバージョンを知っているので、まずこの obb ファイルを探しに行き、StorageManager を使ってこれをマウントする。ざっくり書くとこんな感じ。

マウントに成功すると、onObbStateChange(String, int)が、/mnt 以下のそのパスを教えてくれる。

ダウンロードの保証

ほとんどの場合、拡張ファイルはアプリ本体と一緒にダウンロードされる。ユーザからは Google Play 上の(50MB より大きな)ひとつのアプリとしか見えない。

しかし、まれに拡張ファイルのみダウンロードに失敗したり、ユーザが手動でファイルを削除したりする場合がある。このケースについてもアプリは最初に拡張ファイルの存在を確認し、無い場合には自前でダウンロードできるのが望ましい。

…が、実際 50MB をちょっと超えるくらいであれば、そうそうダウンロードに失敗することは無いのではと思われる。ストレージが足りないときに起こるのかもしれないが、手元では一度も確認できなかった。ここは割り切って拡張ファイルが無ければエラー終了でも良いのではとも思われる(公式ドキュメントにはもちろん must be able to と書かれているが)。

で、先述のダウンローダライブラリと、

<ANDROID_SDK_DIR>/extras/google/play_licensing/library/

に用意されているライセンス用ライブラリを import して、Google Play から拡張ファイルのダウンロードを行うことができる。この方法も先のサンプルにほぼ書かれていますが力尽きたので後略。。。気が向けばまた書きます。

参考:
APK Expansion File | Android Developers
APK拡張ファイルの使用 | Android デベロッパー ヘルプ

Expansion Files について | キノコの自省録