Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

APK Analyzer でのビルドの分析

Android Studio に付属の APK Analyzer では、ビルドプロセスの完了後に APK の構成をすぐに分析できます。APK Analyzer を使用すると、DEX ファイルやアプリ内のリソースに関する問題のデバッグにかかる時間を短縮できるほか、APK のサイズを縮小することもできます。APK Analyzer は、コマンドラインから apkanalyzer で実行することもできます。

APK Analyzer では以下を行うことができます。

  • APK 内のファイル(DEX ファイルや Android リソース ファイルなど)の絶対サイズと相対サイズを表示する。
  • DEX ファイルの構成を把握する。
  • APK 内のファイル(AndroidManifest.xml ファイルなど)の最終バージョンをすばやく表示する。
  • 2 つの APK を対照比較する。

プロジェクトが開いているときに APK Analyzer にアクセスする方法には次の 3 つがあります。

  • Android Studio の [Editor] ウィンドウに APK をドラッグする。
  • [Project] ウィンドウを [Project] 表示に切り替えて、デフォルトの build/output/apks/ ディレクトリにある APK をダブルクリックする。
  • メニューバーで [Build] > [Analyze APK] を選択し、APK を選択する。

ファイルとサイズに関する情報の表示

APK は ZIP ファイル形式のファイルです。APK Analyzer では、各ファイルまたはフォルダが、フォルダへの移動に使用できる拡張機能を備えたエンティティとして表示されます。エンティティの階層は、APK ファイルのファイルとフォルダの構造を反映したものです。

図 1 に示すように、APK Analyzer には、各エンティティの未加工のファイルサイズとダウンロード ファイルサイズの値が表示されます。[Raw File Size] にはディスク上でのエンティティの解凍サイズが表示されるのに対し、[Download Size] には Google Play から配信される際のエンティティの推定圧縮サイズが表示されます。[% of Total Download Size] は、エンティティが APK の総ダウンロード サイズに占める割合を示します。

図 1. APK Analyzer に表示されるファイルサイズ

AndroidManifest.xml の表示

プロジェクトに複数の AndroidManifest.xml ファイル(プロダクト フレーバー用など)が含まれている場合、または、マニフェスト ファイルを提供するライブラリが含まれている場合、それらは APK 内の 1 つのファイルに統合されます。このマニフェスト ファイルは、通常は APK 内ではバイナリ ファイルですが、APK Analyzer で選択すると、このエンティティが XML 形式に再構築されて表示されます。このビューアを使用すると、ビルド中にアプリに対して行われた変更をすべて把握できます。たとえば、アプリケーションが依存するライブラリの AndroidManifest.xml ファイルが最終的な AndroidManifest.xml ファイルにどのように統合されたかを確認できます。

また、このビューアには lint 機能がいくつか搭載されており、右上隅に警告やエラーが表示されます。図 2 では、選択したマニフェスト ファイルにエラーがあることが示されています。

図 2. 選択したマニフェスト ファイルに対するエラーアイコンが右端に表示されている

DEX ファイルの表示

APK Analyzer の DEX ファイル ビューアを使用すると、アプリの DEX ファイルに関する基本情報に直接アクセスできます。ビューア内にクラス数、パッケージ数、総参照数、宣言数が表示され、これらを基にして、multidex を使用すべきかどうかについてや、依存関係を削除して 64K の DEX の制限を超えないようにする方法を決定できます。

図 3 は、64K の DEX の制限を下回る中規模のアプリを示しています。DEX ファイル内の各パッケージ、クラス、メソッドの数が、[Defined Methods] 列と [Referenced Methods] 列に示されています。[Referenced Methods] 列は、DEX ファイルによって参照されているメソッドの総数です。これには通常、コード、依存関係ライブラリで定義されたメソッドと、コードで使用される標準の Java および Android パッケージで定義されたメソッドが含まれます。これらのメソッドは、各 DEX ファイルの 64K のメソッドの制限にカウントされます。[Defined Methods] 列は、DEX ファイルのいずれかで定義されたメソッドのみの数です。つまりこの数は、[Referenced Methods] の部分集合です。依存関係を APK にパッケージ化すると、依存関係で定義されたメソッドが両方のメソッド数に加算されます。また、軽量化や コード圧縮により、ソースコードのコンパイル後に DEX ファイルの内容が大幅に変更されることがあります。

図 3. 中くらいのサイズのアプリ

DEX ファイル ツリービューのフィルタ

APK Analyzer では、[Class] リストのすぐ上にあるフィルタを、選択した DEX ファイルの内容の表示に適用できます。

図 4. BuildConfig のフィールドとメソッドを表示するように設定した DEX フィルタ

フィルタを使用してクラス内のすべてのメソッドとフィールドを表示する手順は次のとおりです。

  1. [File] リストで classes.dex ファイルを選択します。
  2. [Class] リストで、特定のクラスに移動して選択します。
  3. 選択したクラスを展開します。
  4. フィールドを表示ボタン で、クラス フィールドの表示と非表示を切り替えます。
  5. メソッドを表示ボタン で、クラスメソッドの表示と非表示を切り替えます。
  6. 参照されているメソッドやフィールドをすべて表示ボタン で、参照されているパッケージ、クラス、メソッド、フィールドの表示と非表示を切り替えます。ツリービュー内の斜体で示されたノードは、選択した DEX ファイルで定義されていない参照です。

    DEX ファイルからは、別のファイルで定義されているメソッドとフィールドを参照できます。たとえば System.out.println() は、Android フレームワークの println() への参照です。

ProGuard マッピングの読み込み

フィルタ アイコンの横には ProGuard マッピング アイコンがあります。これらのアイコンは、名前の難読化解除(mapping.txt)、削除されたノードの表示(usage.txt)、削除できないノードの指定(seeds.txt)など、DEX ビューアに機能を追加する一連の ProGuard マッピング ファイルを読み込むまでグレー表示されています。インポートする ProGuard マッピング ファイルは、コード圧縮を有効にして APK を生成したビルドからのものである必要があります。詳細については、アプリの圧縮、難読化、最適化をご覧ください。

図 5. ProGuard マッピングの読み込み

ProGuard マッピング ファイルを読み込む手順は次のとおりです。

  1. [Load Proguard mappings] をクリックします。
  2. マッピング ファイルが格納されているプロジェクト フォルダに移動し、すべてのファイル、ファイルの組み合わせ、またはファイルが格納されているフォルダを読み込みます。

    通常、マッピング ファイルは project/app/build/outputs/mappings/release/ にあります。 ファイル選択ツールによりこのプロジェクト構造が検出されると、デフォルトで release フォルダが表示されます。ファイル選択ツールでは、まず mapping.txtseeds.txtusage.txt と完全に一致するファイル名があるかがチェックされます。次に、mappingusageseeds のようなテキストを含むファイル名や、.txt で終わるファイル名があるかがチェックされます。 たとえば、release-seeds-1.10.15.txt は一致します。

以下は、各マッピング ファイルの説明です。

  • seeds.txt: ProGuard の設定により圧縮時に削除されないノードが太字で表示されます。
  • mapping.txt: 名前を難読化解除ボタン を有効にすると、R8 によって難読化されたノードの元の名前を復元できます。たとえば、abc のように難読化されたノード名を MyClassMainActivitymyMethod() に復元できます。
  • usage.txt: 削除されたノードの表示ボタン を有効にすると、圧縮時に R8 によって削除されたクラス、メソッド、フィールドを表示できます。復元されたノードは取り消し線付きで表示されます。

    R8 を使用してコードの難読化や圧縮を行う方法について詳しくは、アプリの圧縮、難読化、最適化をご覧ください。

バイトコードの表示、使用箇所の検索、保持ルールの生成

[Class] リストに表示されたノードのコンテキスト メニューには、下記のオプションがあります。このメニューからは、バイトコードの表示、使用箇所の検索、ProGuard ルール(選択したノードにコピー&ペースト可能)を表示するダイアログの表示が可能です。[Class] リスト表示で任意のノードを右クリックすると、そのコンテキスト メニューを表示できます。

Show Bytecode: 選択したクラス、メソッド、フィールドを逆コンパイルし、次のようにダイアログに smali(Java コードではない)バイトコード表現を表示します。

図 6. init メソッドの DEX バイトコード

Find Usages: 選択したクラスまたはメソッドが、他のどの部分の DEX コードから参照されているかを表示します(図 7)。 seeds.txt を読み込んだ際に太字で表示されるノードは、ProGuard の設定により圧縮時に削除されません。

図 7. MyClass への参照

Generate Proguard keep rule: ProGuard ルールを表示して、プロジェクトの ProGuard 構成ファイルにコピー&ペーストできます。そうすることで、コード圧縮フェーズ中に特定のパッケージ、クラス、メソッド、またはフィールドが削除されないよう保護することができます(図 8)。 詳しくは、保持するコードのカスタマイズをご覧ください。

図 8. ダイアログから ProGuard 構成ファイルにコピーできる ProGuard ルール

コードおよびリソース エンティティの表示

APK ファイル内の最終エンティティはさまざまなビルドタスクによって変更されます。たとえば、ProGuard 圧縮ルールによって最終的なコードが変更されることがあります。また、画像リソースがプロダクト フレーバーのリソースによって上書きされることもあります。 APK Analyzer では、ファイルの最終バージョンを簡単に表示できます。エンティティをクリックすると、図 9 に示すように、テキストまたは画像のエンティティのプレビューが表示されます。

図 9. 最終的な画像リソースのプレビュー

APK Analyzer では、各種のテキスト ファイルやバイナリ ファイルも表示できます。 たとえば、resources.arsc エンティティ ビューアを使用すると、文字列リソースの言語翻訳など、設定固有の値を表示できます。図 10 では、各文字列リソースの翻訳が表示されています。

図 10. 翻訳された文字列リソースのプレビュー

APK ファイルの比較

APK Analyzer では、2 つの APK ファイル内のエンティティのサイズを比較できます。この機能は、以前のリリースに比べてアプリのサイズが大きくなった理由を把握する必要がある場合に役立ちます。更新された APK を公開する前に、以下の操作を行います。

  1. 公開しようとしている APK のバージョンを APK Analyzer にロードします。
  2. APK Analyzer の右上にある [Compare With] をクリックします。
  3. 選択ダイアログで、ユーザーに前回公開した APK を選択して [OK] をクリックします。

    図 11 のようなダイアログが表示され、更新版がユーザーに与える影響を評価できます。

図 11 は、特定のアプリのデバッグビルドとリリースビルドの違いを示しています。これらのビルドタイプ間で異なるビルド オプションが使用されていると、基盤となるエンティティが別々に変更されます。

図 11. デバッグ APK とリリース APK の違い