APK Analyzer でビルドを分析する

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


APK Analyzer では次のことができます。

  • アプリ内のファイル(DEX ファイルや Android リソース ファイルなど)の絶対サイズと相対サイズを表示する。
  • DEX ファイルの構成を把握する。
  • アプリ内のファイル(AndroidManifest.xml ファイルなど)の最終版をすぐに表示する。
  • 2 つの APK または App Bundle を対照比較する。

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

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

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

APK は ZIP ファイル形式のファイルです。APK Analyzer では、各ファイルまたはフォルダはエンティティとして表示され、それらを開いてフォルダに移動することができます。エンティティの階層は、APK ファイル内でのファイルとフォルダの構造を反映しています。

図 1 に示すように、APK Analyzer には、各エンティティの圧縮されたファイルサイズ(または「RAW ファイルサイズ」)とダウンロード ファイルサイズの値が表示されます。Raw File Size は、APK の合計サイズに占めるエンティティの割合を表します。[Download Size] は、Google Play によって配信されるエンティティの推定圧縮サイズを表します。[% of Total Download Size] は、APK の総ダウンロード サイズのうちエンティティが占める割合を示します。

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

AndroidManifest.xml の表示

プロジェクトに複数の AndroidManifest.xml ファイル(プロダクト フレーバー用のファイルなど)が含まれている場合、または、マニフェスト ファイルを提供するライブラリが含まれている場合、それらはアプリ内の単一のファイルにマージされます。このマニフェスト ファイルは、通常は APK または App Bundle 内のバイナリ ファイルですが、APK Analyzer で選択すると、そのエンティティが XML 形式で再構築されて表示されます。

このビューアを使用すると、ビルド時にアプリに加えられた可能性がある変更をすべて把握できます。たとえば、アプリが依存するライブラリの AndroidManifest.xml ファイルが最終の AndroidManifest.xml ファイルにどのようにマージされているかを確認できます。

さらに、このビューアにはいくつかの lint 機能も装備されており、警告またはエラーが右上隅に表示されます。図 2 は、選択したマニフェスト ファイルでエラーが 1 つレポートされたことを示しています。

図 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 ファイルのいずれか 1 つで定義されているメソッドのみの数を示します。つまり、この数は [Referenced Methods] の一部です。

図 3. 中規模のアプリ

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

図 4 に示すように、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 マッピング アイコンがあります。ProGuard アイコンは、DEX ビューアに機能を追加する ProGuard マッピング ファイルのセットを読み込むまで、グレー表示されます。そのような機能(マッピング ファイル)には、名前の難読化解除(mapping.txt)、削除されたノードの表示(usage.txt)、削除できないノードの指定(seeds.txt)などがあります。

インポートする ProGuard マッピング ファイルは、コード圧縮を有効にして DEX ファイルを生成したビルドと同じビルドからのものである必要があります。

図 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 バイトコード表現を表示します。

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

Find Usages: 図 7 に示すように、選択したクラスまたはメソッドへの参照を含む DEX コードの他の部分を表示します。seeds.txt を読み込んだ場合は、ProGuard 構成によって圧縮時の削除から保護されるノードが太字で表示されます。

図 7. MyClass への参照

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

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

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

アプリ内の最終エンティティは、さまざまなビルドタスクによって変更されます。たとえば、ProGuard 圧縮ルールによって最終的なコードが変更されたり、プロダクト フレーバー内のリソースによって画像リソースがオーバーライドされたりすることがあります。

APK Analyzer でファイルの最終バージョンを確認するには、図 9 に示すように、エンティティをクリックしてテキストまたは画像エンティティをプレビューします。

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

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

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

ファイルの比較

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

更新されたアプリを公開する前に、以下の操作を行います。

  1. 公開しようとしているアプリのバージョンを APK Analyzer に読み込みます。
  2. APK Analyzer の右上隅にある [Compare with previous APK...] をクリックします。
  3. 選択ダイアログで、ユーザーに前回公開したアーティファクトを選択して [OK] をクリックします。

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

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

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