キノコの自省録

テクノロジーとコンテンツの融合を目指して

Expansion Filesについて(3) - obbダウンロード編

前回の続き。↓前回
http://d.hatena.ne.jp/kinokorori/20130715/1373861196


拡張ファイルをGoogle Playからダウンロードする方法の解説です。


APKの拡張ファイルは、
APK本体ダウンロード時に、「基本的に」一緒にダウンロードされます。
しかし、容量や回線の都合によって、ダウンロードできない場合があります。
その場合は、アプリケーション起動時に、拡張ファイルをダウンロードしにいく必要があります。
その制御はアプリケーション提供者が書かなければいけません。

APKが公開状態ではなくても、Google Playからのダウンロードテストは可能です。
まずは、Google PlayにAPKを登録して、拡張ファイルをアップロードしましょう。
拡張ファイルがダウンロード可能となるためには、
「APK」、「ストアの掲載情報」、「価格と販売/配布地域」の3つの設定を埋めて、
公開が可能な状態にしておく必要があります。
なお、アップロードはChromeを使った方が無難です。他のブラウザではアップロードに失敗することがあります。

  • 手動ダウンロード実装上の注意

ダウンロードには、Android SDKの拡張ライブラリであるDownloader Libraryを利用します。
(Android SDK)/extras/google/play_apk_expansion/downloader_library
もちろん、使わなくても実装はできますが、当然ながら面倒くさいです。
http://developer.android.com/google/play/expansion-files.html 
ここのDownloading the Expansion Filesセクションの中ほどに、
気にしなければならない事項が書いてあります。

  • Downloader Libraryのインポート

Eclipseの場合、
1.Import→Existing Android Code Into Work Spaceを選択
2.(Android SDK)/extras/google/play_apk_expansion/downloader_libraryを指定
3.Downloader Libraryを利用する自分のアプリケーションのプロパティを開く
4.Android→Libraryに先ほど追加したDownloader Libraryを追加
で、利用可能となります。


Downloader LibraryはLVL(Licensing Verification Library)を要求するので、これもインポートします。
手順はDownloader Libraryと同様で、場所は、
(Android SDK)/extras/google/play_licensing/library
になります。
なお、LVLは、Google Playの購入証明に用いるライブラリです。


Downloader LibraryもLVLも見つからない!という人は、
Android SDK Managerから、Extrasパッケージをダウンロードしてあるか確認してください。

  • ダウンロードの実行

Downloader Libraryを利用して、実際に拡張ファイルをダウンロードします。
Downloader Libraryの利用方法は、サンプルを見るのが一番早いです。
サンプルは、
(Android SDK)/extras/google/play_apk_expansion/downloader_sample
にあります。


まず、公式ドキュメントの、
Declaring user permissions
Implementing the downloader service
Implementing the alarm receiver
の実装をそのままコピペします。


Downloader Serviceでは、RSA公開鍵を適切に設定する必要があります。
RSA公開鍵は、Google Playのアプリケーションページ内に「サービスとAPI」という項目がありますので、
そこからコピペします。
ソルト(SALT)も自動でも手動でもどちらでも構わないので、デフォルト値からは絶対に書き換えましょう。


次に、DownloaderClientMarshallerを介して、ダウンロードを開始します。
これも、サンプルを参考にすればすぐ実行できます。
以下のコードも、サンプルをほぼそのまま拝借しています。

Intent launchIntent = getIntent();
Intent intentToLaunchThisActivityFromNotification = new Intent(this, this.getClass());
intentToLaunchThisActivityFromNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentToLaunchThisActivityFromNotification.setAction(launchIntent.getAction());

if (launchIntent.getCategories() != null) {
  for (String category : launchIntent.getCategories()) {
    intentToLaunchThisActivityFromNotification.addCategory(category);
  }
}

PendingIntent pendingIntent = PendingIntent.getActivity(this,
  0, intentToLaunchThisActivityFromNotification,
  PendingIntent.FLAG_UPDATE_CURRENT);

//ExpansionDownloaderServiceは、DownloaderServiceの実装クラス
int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
  pendingIntent, ExpansionDownloaderService.class);
  • Downloader Libraryの構成

Downloader Libraryは、
(1)com.google.android.vending.expansion.downloader
(2)com.google.android.vending.expansion.downloaderimpl
の2パッケージで構成されています。
(2)のdownloaderimplは、挙動について深く知る必要がある場合を除いて、
利用者が中身を知る必要はありません。

  • Downloader Library利用のポイント

1. IDownloaderClientは、自分のクラス(例えばアクティビティ)で継承して実装する
2. IStubはDownloaderClientMarshallerのcreateProxyで生成できる。onCreateですぐ生成して構わない
3. IDownloaderServiceは、DownloaderServiceMarshallerのcreateProxyで生成できる


3についてはもう少し詳しく説明します。
IDownloaderServiceは、ダウンロードの一時停止や再開、中断に用いるためのインタフェースです。
IDownloaderServiceは、IDownloaderClientの仮想メソッドである、
public void onServiceConnected(Messenger m)
にて、DownloaderServiceMarshaller.createProxyを呼び出して生成します。
具体的には、以下のようになります。

private IDownloaderService mDownloadService = null;
public void onServiceConnected(Messenger m) {
  mDownloadService = DownloaderServiceMarshaller.CreateProxy(m);
  mDownloadService.onClientUpdated(m);
}

メソッド内2行目の、mDownloadService.onClientUpdated(m)を呼び出さないと、
IDownloaderServiceが有効にならないばかりか、
IDownloaderClientの実装クラスにダウンロードの進捗や状態変化が通知されないので注意してください。


Downloader Libraryの中には、Helpersというクラスが用意されています。
Helpersクラスは、文字通りヘルパーメソッド群です。
必ずしも使う必要はありませんが、便利なメソッドが揃っているので、一通り目を通しておくと良いでしょう。

  • その他の注意

なお、ダウンロードした拡張ファイルは、移動、削除、リネームしないようにしましょう。
拡張ファイルをダウンロードしていないものとして、毎回ダウンロードを試行してしまいます。


拡張ファイルをアップロードしたのに、
IDownloaderClient.onDownloadStateChangedで、IDownloaderClient.STATE_FAILED_FETCHING_URLが返って来ることがあります。
拡張ファイルの更新は、すぐに反映されるわけではありませんので、少し待ちましょう。
しばらく待ってもSTATE_FAILED_FETCHING_URLが返って来る場合は、
Google Playのアプリケーション情報に必要情報を記入し終えているか確認してみましょう。