その2 Multiple APK Support (Google Play Distribution)
つづいてはMultiple APKです。ずーっとひとつのファイルに複数のAPKをまとめる機能かと思ってましたが全然違ったみたいです。
で、読んでみましたが、私にはまったく無縁の機能だというのがよくわかりました。 Googleさんもこの機能の利用を奨めていないってのがひしひしと伝わって来ます…
Multiple APK Support
Multiple APKは、異なるデバイス設定向けの複数のAPKファイルをGoogle Play上で公開するための機能。
それぞれのAPKは、完全で独立したバージョンコードを持つアプリケーションファイルだが、 Google Play上では同一のアプリケーションとして扱われる。また、それらは 同じパッケージ名を持ち、同じ証明書で署名されていなければならない。
Multiple APKは、単一のAPKで全ての端末をカバーしきれない時に有効な機能である。
通常アンドロイドアプリは、リソースを用いて単一のAPKで異なるデバイスに対応するが、 (例えば画面サイズ毎のレイアウトを使用する等) 多種多様なリソースはAPKファイルのサイズを膨らませ(APKには50MBの制限有)、他の技術的な試みを阻害したりもするため、シングルAPKでは全てのデバイスや設定に対応できない場合がる。
通常はシングルAPKで多くの端末に対応するアプリを開発し公開することを勧めるが、それが困難な場合ははMultiple APKを使って公開してもよい。
Multiple APKを使うと、APK毎に以下の対応が可能となる
- 異なるテクスチャの圧縮フォーマットへの対応
- 異なる画面サイズや密度への対応
- 異なるプラットフォームのバージョンへの対応
- 異なるCPUアーキテクチャへの対応
現時点ではMultipleAPKではこれらしか対応できない。 また、MultipleAPKを使う際には、シングルAPKでサイズが50MBを越える場合のみにするべきである。
Publishing Concepts
Google Playで公開する前に、Developer Consoleでの操作を理解する必要がある。
Active APKs
公開と保存
アプリの情報を編集しているとき、ページの右上には "公開/非公開"と"保存"の2つのボタンが表示される。
アプリが新規、もしくは非公開のときは、最初のボタンは"公開"になっており、それを押すとActiveなAPKがGoogle Play上で公開される。また、"保存"ボタンを押すと、アプリ情報やAPKなどの変更がGoogle Playに保持されるが、それらの情報は公開されることはない。これは、Google Playに対して情報を保存/更新するのみで、アプリを公開せずにコンソールからログアウトできることを意味する。
一方、アプリが公開状態の時は、最初のボタンは"非公開"となり、押すとアプリがGoogle Playで表示されなくなる。また、公開状態の時の保存は非公開の時と動作が異なり、全ての情報が保存されると共に、それがGoogle Play上にも反映される(数時間のタイムラグがある)
アプリを公開するには、アップロード済のactiveなAPKが必要で、 公開状態のアプリの場合、エラーが無ければactiveなAPKがGoogle Play上で表示されることになる。
Simple mode and advanced mode
Developer Consoleは、Simple/Advancedの2つのインターフェースを提供している。 ページの右上のリンクで、開発者は好きな方に切り替えられる。
Simpleモードは、一度に一つのAPKを使うこれまでのモード。SimpleモードではactiveなAPKはひとつだけで、新しいAPKをアップロードしてそれをactivateすると、それまでactiveだったAPKがdeactivateされる。(保存ボタンを押すまでこの状態は記録されない)
Advancedモードは、複数の端末設定に調整された複数のAPKをactiveにして、アプリを公開する事が許されている。しかし、どのAPKがどのようなmanifestの設定に基づいてどのデバイスに紐付けられるのかといったルールを決める必要があり、エラーが発生した場合には、それらが解決されるまでアプリの公開が不可能となる。
また、アプリが公開可能になったからといって、そのアプリが様々なデバイスで有効になるかどうかは保証されていない。
これらのルールは以下でさらに述べる。
How Multiple APKs Work
Multipe APKのコンセプトは、Google Play上でそのアプリは単一のエントリーだが異なるデバイスで異なるAPKをダウンロードできるようにすることにある。
- 商品説明(アプリの説明、アイコン、スクリーンショットなど)は1セットのみで、APK毎に異なる価格の設定はできない
- ユーザー(ある端末)がGooglePlay上で感知可能なアプリのバージョンはただひとつだけで、すでに"for Phone"や"for Tablet"という名前でアプリを公開していたとしても、混乱を招くことはない
- 全てのユーザーレビューはアプリ全体に対して行われる。異なるデバイスのユーザーが各々別のAPKを使っていても、書き込まれるレビューは共通の場所となる
- 対象とするOSのバーション毎にAPKを公開している状態で、ユーザーがシステムをアップデートした場合は、新しく対応したバージョンのAPKを入手する資格が与えられ、Google Playはそのユーザーのアプリケーションをアップデートしようとする。なお、SingleAPKと同じく、アプリに関連付けられた任意のシステムデータは保持される。
複数のAPKを一つのアプリケーションとして公開するには、Developer ConsoleをAdvancedModeで使う必要がある。以下よりMultipeAPKがどのように働くのかを述べる。
Supported filters
どのデバイスがどのAPKを受信するかは、各APKに含まれるmanifestファイルの要素によって決定されることになっている。
しかし、Google Playでは以下の場合に要素が異なるときのみMultiple APKを利用する事を許可している。
OpenGL texture compression formats
OpenGLでのテクスチャの圧縮フォーマット
manifestファイルの<supports-gl-texture> の要素に基づく
Screen size (and, optionally, screen density)
manifestファイルの<supports-screens>や<compatible-screens> の要素に基づく。両方の要素を使用するべきではなく、可能なら<supports-screen>だけを使うべきである。
例としては、normal sizeをサポートするAPKと、largeやxlargeをサポートするAPK。
- AndroidはSigleAPKで全てのスクリーン対応可能な強力な手法を用意しているため、SingleAPKで対応可能な場合は、MultipleAPKは使うべきではない
- デフォルトでは<supports-screens>要素は全ての属性がtrueとなる。しかし、minSdkVersionかtargetSdkVersionがAPI level 9より小さい場合は、xlargeScreensはfalseに設定される
- <supports-screens>と<compatible-screens>要素は、互いに干渉する可能性があるために両方をmanifestファイルで定義するべきではない。 どちらを使うかを決める手助けとして Distributing to Specific Screensを読むとよい。どうしても両方の使用を避けられない場合、競合したばあいはfalseの値が優先される。
API level
<uses-sdk>要素に基づくもので、minSdkVersionとmaxSdkVersionでサポート可能なAPI levelを指定する。
この値をMuitipleAPKのフィルターとして使用する場合、minSdkVersionの大きなAPKほど android:versionCodeを大きな値としなければならない。
未来のバージョンに対応するために、一般にmaxSdkVersionの使用はさけるべきである。
CPU architecture (ABI)
APKに含まれるnative libraryに基づく。これはNDKを利用する際にAplication.mkで宣言するアーキテクチャによって決定される。
Rules for multiple APKs
MultipleAPKでアプリを公開するなら、以下のルールを理解し守ること。
- 全てのAPKは同じパッケージ名で、同じ証明書を使って署名されていること
- 各APKは異なるバージョンコード(android:versionCode)を持つこと
各APKは互いに同一の設定ではない必要がある。上述のSupported Filtersの内容のいずれかが異なっていること
サポートする機能が重なっている場合には、通常、端末はより大きなバージョン番号を持つAPKを受信することになる
activate済のAPKを、それより小さいバージョンコードのAPKで置き換えることはできない
新しいAPIレベルを必要とするAPKほど、より大きなバージョンコードを持たなければいけない
これは、Google Playからアプリのアップデートを受信する際に、バージョンコードが端末内のそれよりも大きくなっているかどうかだけで判定されるため
バージョンコードがどれだけ大きくなるのかは関係なく、とにかく1でも大きければよい
これらのルールを守らない場合、Developer Consoleで警告やエラーが発生する。これらを解決しない限りはアプリを公開できない。
デバイスのサポートを縮める(たとえばscreen sizeのサポートを、normalとsmallからnormalだけにする)場合、単にsmallの設定を解除してしまうと、そのアプリが表示されなくなる端末が発生する
このような場合、normalだけをサポートする別のAPKを追加すれば、smallの端末でもこれまでのAPKは使用できることになる
サポートする機能が複数のAPKで重複する場合、ユーザーの端末に対しては、もっとも大きなバージョンコードを持つAPKが提供されることになる
Creating Multiple APKs
Multiple APKでの公開を決めたなら、おそらく個々のAPKのために適切にプロジェクトを分ける必要がある。コードの重複を避けるために、ライブラリプロジェクトを利用するのも一つの手。
Gradleのようなbuildシステムを使って一つのプロジェクトで済ませることも可能
同じアプリで複数のプロジェクトを作りときは、プロジェクト名をわかりやすいものにしておくとよい。(API レベル8以上対応のプロジェクトなら"Project_8"等)
Multiple APKで作成するAPKは、全て同じパッケージ名で、同じ証明書で署名する必要がある
Assigning version codes
各APKは異なるバージョンコードを持たなければならない。また、各APKのサポートする機能によっては、それらは注意して決定する必要がある。
Ordering version codes
より高いAPIレベルを必要とするAPKは、常に大きなバージョンコードを持たなければならない。
デバイスは大抵が複数の要求を満たすため、Multiple APKの中で重複して対象となるものが発生するが、端末に配布されるのは、その中でもっとも大きなバージョンコードを持つものとなる。 開発者はこのことに注意を払わねばならない。
Using a version code scheme
MultipleAPKを利用する場合、各APKのバージョンコードの間には、ある程度の余裕を持たせておくべきである。こうしておけば、特定のAPKのみに発生したバグを修正して公開するときに、このAPKのバージョンコードを他のAPKに干渉させずに変更可能となる。 (バージョンコードが更新されれば、そのAPKをインストールしているユーザーにアップデートが通知されるため、変更されていないAPKのバージョンコードを増やすべきではない)
バージョンコードの定義の方法として、以下の7桁のフォーマットすすめる。
- 先頭の2桁 - APIレベル
- 次の1桁 - サポートする最小のスクリーンサイズ(1:small, 2:normal,3:large,4:xlarge)
- 次の1桁 - サポートする最大のスクリーンサイズ(同上)
- 下3桁 - アプリケーションのバージョン
必ずこのフォーマットに従う必要はないが、どんなフォーマットにするにせよ、バージョンコードの設定は、注意深く設計しなければならない。
Using a Single APK Instead
Multiple APKは標準的な公開方法ではない。できればメインのボリュームゾーンに対してSingleAPKで公開されるのが望ましく、Googleとしてもそれを奨励する。
SingleAPKではどうしても困難な場合に、注意深く検討した上でMultipleAPKの使用を決断すること。
以下、SingleAPKのメリットをいくつか提示する
公開と管理が楽
同時に公開されるAPKはただ一つのみ。
ソースコードはひとつだけ
複数のソースコードを管理せずに済む。
デバイスの変更に対応可能
SingleAPKであるということは、内部に複数のリソースを持つことを意味する。これはアプリを再インストールなしに、実行時に柔軟にデバイスの変更に対応させられる可能性があるということでもある。
別の端末からのリストアが可能
他の端末でのデータを、別の端末でリストアして動かせる可能性があるということでもある。
Supporting multiple GL textures
Single APKで複数のOpenGL テクスチャ形式に対応する方法として、Web Serverからのリソースのダウンロードが考えられる。
初回起動時にのみ、データダウンロード処理を行うようにすればよい。
まずはETC1と非圧縮テクスチャに使用を試み、ETC1では不十分なときに PVRTCやATITC、DXTCの使用を検討すること。
String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
で、端末がサポートするフォーマットが取得可能。
Supporting multiple screens
APKが50MBを越えない限りは、SingleAPKで複数のスクリーンに対応するべきである。
また、サポートライブラリのFragmentも活用するとよい。
Supporting multiple API levels
古いバージョンのどこにまで対応するかは合理的な判断が必要だが、2.2以降に制限しても既に98%以上のシェアがある。(Platform Versions)
サポートライブラリを使えば、3.0より古い環境でもFragmentやLoaderが使えるようになるため、活用するとよい。
どうしても新しいAPIを利用したい場合、リフレクションを使うか、android.os.Build.VERSION.SDK_INTを利用してコンパイル時に使用するAPIを変えるという手もある。
Supporting multiple CPU architectures
Application.mk の中で、複数のCPUアーキテクチャをサポートする指定も可能。
発表を聞いた時は、バイナリが増えたらeclipseでリリースビルドするのにプロジェクトを分けるとかしないといけなくて面倒だよなぁ?とか思いましたが、今のGradleベースなAndroid Studioなら、かなり柔軟にbuildできるみたいだしそうでもないのかもしれません。
どちらにせよ、使用はAPKが50MBを越える時にするべきだ!とか書いてあるし、 Googleも管理とか面倒だからSingleAPK使えよなって言ってますので、この機能を私が使うことは無さそうです。
というよりも、50MB越えても次のExpansionFilesで大抵なんとかなるんじゃなかろうかとか思ったり。
実際に利用されているアプリってどの位あるのかちょっと知りたい気もします。