View on GitHub
mixi-inc/AndroidTraining
デバッグと自動ビルド(Eclipse)
この章では、Android アプリのデバッグに利用する様々なツールと、アプリの自動ビルドについて解説します。

目次

デバッグ

Android では、様々なデバッグの手段が提供されています。
ここでは、各種デバッグツールの使い方について解説します。

DDMS パースペクティブ

Eclipse には、パースペクティブと呼ばれる、目的に応じた画面構成があります。
この中でも、Android のデバッグに特化したパースペクティブが、DDMS パースペクティブです。

DDMS Perspective

DDMS パースペクティブには、以下のビューが含まれています。

  • Devices
    • 接続されているデバイスの一覧と、そのデバイスで動作中のデバッグ可能なプロセスの一覧です
  • Threads
    • スレッドのプロファイラのビューです
  • Heap
    • プロセスで使用しているヒープ領域のプロファイラのビューです
  • Allocation Tracker
    • メモリ領域の確保状況を表示するビューです
  • Network Statistics
    • ネットワークの通信状況を表示するビューです
  • File Explorer
    • 端末のファイルシステムを表示するビューです
  • Emulator Control
    • エミュレータへの、通話や位置情報の通知を行うビューです
  • System Information
    • CPU やメモリなど、ハードウェアリソースの使用状況を表示します
  • LogCat
    • Logクラスによるログ出力です

これらのビューは、Android SDK に含まれる各種ツール群を Eclipse に組み込んだものになっています。

TraceView

DDMS パースペクティブの Threads ビューと同じものです。
スレッドごとのメソッドの実行時間を計測し、グラフ化するためのプロファイラの 1 つです。

Android SDK 内の toolsには、traceviewコマンドが用意されていますが、現在はその使用が推奨されていません。
かわりに、monitorコマンドから、Android Device Monitor を利用することが推奨されています。

使い方は DDMS パースペクティブのものも、Android Device Monitor のものも同じですので、詳細は Android Device Monitor で解説します。

Hierarchy Viewer

Hierarchy View パースペクティブとして、Eclipse に組み込まれています。

hierarchyviewerコマンドが SDK に同封されていますが、traceviewコマンド同様、その使用は推奨されなくなりました。
かわりに、monitorコマンドから、Android Device Monitor を利用します。

使い方は DDMS パースペクティブのものも、Android Device Monitor のものも同じですので、詳細は Android Device Monitor で解説します。

Andorid Device Monitor

Android SDK r20 で導入された、新しいデバッグ・プロファイリングツールです。

Android Device Monitor

Eclipse の DDMS パースペクティブが切りだされ、単体のアプリケーションとして動作しています。
このほか、Hierarchy View パースペクティブ、Pixel Perfect パースペクティブ、Tracer for OpenGL ES パースペクティブもこの中に含まれています。

スレッドのプロファイリング

スレッドの実行時間を計測するには、Devices ビューから、プロファイリングするプロセスを選択します。

Profiling Threads

このビューの、Devices タブの右横にあるアイコンのうち、左から 6 番目の、矢印と赤丸のアイコンが、プロファイリングを開始するボタンとなります。
開始すると、赤丸が黒丸に変わります。
プロファイリングを停止するタイミングでもう一度アイコンをクリックすると、プロファイリングの結果が出力されます。

Profiling result

この表示では、各メソッドごとに、呼び出しにかかった総計の時間や、メソッド単体でかかった時間が下の表にまとめられ、その時間をグラフ化したものが画面上部に表示されるようになっています。

このうち、Incl CPU Time は、あるメソッドでかかったすべての時間で、Excl CPU Time は、あるメソッド単体でかかった時間を表します。
よって、Excl CPU Time が掛かっているメソッドほど、ボトルネックとなっていることになります。 メソッドの実行時間のほか、メソッドの呼ばれた回数と、再帰呼び出しの回数をみることもできます。

レイアウトの階層構造を見る

Hierarchy Viewer パースペクティブを開くと、下記のような画面が表示されます。

Profiling result

Hierarchy Viewer は、root 権限のあるデバイスでしか利用できないため、エミュレータを活用します。

デバイスが接続されると、起動中のプロセスと画面がリストアップされます。

Windows View

この中から、レイアウトの階層構造を解析したい画面を選択すると、解析が始まります。
解析が終わると、Tree View に階層構造がグラフ化されて表示されます。

Layout Tree View

この Tree View のノードを選択すると、レイアウトの大きさの計算に要した時間や、レイアウトの構成に要した時間、描画に要した時間と、そのノードが持つビュー全体が表示されます。

Node information

このツールを用いて、不要なレイアウトの階層を減らしたり、階層構造が深すぎる部分を特定したりなどを行います。

Memory Analyzer Tool

メモリ使用量を解析したり、メモリリークの可能性を探ったりするための、メモリ解析ツールです。
メモリのプロファイリングは、DDMS パースペクティブでヒープ領域のプロファイリングを実行し、ダンプ結果を出力させます。
Memory Analyzer Tool は、このダンプ結果を元に解析を行い、グラフ表示などをしてくれます。

Memory Analyzer Tool は、スタンドアロン型のソフトウェアと、Eclipse のプラグインの 2 種類があります。

この項では、Eclipse のプラグインのセットアップと使い方、実際のメモリリークへの対処の一例を扱います。

Eclipse プラグインのインストール

Memory Analyzer Toolから、最新版を配布している更新サイトの URL を探して、Eclipse に入力します。
2013 年 5 月時点では、下記で最新版の配布をしています。

  • http://download.eclipse.org/mat/1.2/update-site/

メニューの Help > Install New Software… で、更新サイトからプラグインをインストールするウィザードを開始します。
Work with に、更新サイトの URL を入力してください。
入力すると、更新サイトからプラグインの情報を引いてきて、どのような内容のものをインストールするか尋ねられます。

Install MAT Plugin

今回は、両方を選択してインストールします。

Install Details

Finish すると、インストールが始まります。
インストールが終わったら、Eclipse を再起動する旨のダイアログが表示されるので、再起動します。

ヒープのダンプを取る

現在のヒープの様子を見るには、Devices View から、Update Heap を選択します。
すると、DDMS パースペクティブの Heap ビューで、ヒープ領域の使用率などが表示されるようになります。

Heap Status

ここで、Cause GC ボタンを押すと、GC を発生させ、ヒープ領域の表示が更新されます。

画面回転などを起こしても、ヒープ使用量が増え続ける場合、メモリリークが発生してる可能性が高いと判断出来ます。 ここで、メモリリークを調べるために、Devices View から、Dump HPROF file を選択します。

しばらくすると、ヒープのダンプファイルが生成され、Memory Analyzer Tool が起動します。

Getting Started

ここで、メモリリークを調べる場合は、Leak Suspects Report を選択し、Finish します。

Leak Suspects Graph

このグラフでは、リークが疑われているオブジェクトの一覧が表示されています。
実際にリークしているかどうかは、この状態ではわからないので、Dominator Tree の表示で確認します。

Dominator Tree

この中で、同じクラスのオブジェクトが意図せず複数存在する場合は、メモリリークの可能性があります。
そのオブジェクトがどこから参照されたかを辿るには、一覧からオブジェクトを選択して、右クリックメニューから、Path to GC Root を選びます。

Path To GC Root Menu

With all references を選択すると、下記のように、参照元が表示されます。

Path To GC Root

これで、どこでメモリリークが発生しているかが調査できます。

Android Lint

Android 特有の作法や流儀、規約に従っているかどうかを静的解析するツールです。
Java と XML の両方について解析を行います。

Android Lint はデフォルトで、変更したファイルに対して自動で解析を実行します。

自動ビルド

Android は、公式に自動でプロジェクトをビルドして apk を作成するプロセスをサポートしています。

ant

ant は Android にかぎらず、Java のプロジェクトの為のビルドツールです。
XML によってビルド手順を記述し、ant はその手順を読み取って実行することで、自動でビルドが実行される仕組みです。

build.xml を生成する

ant のビルド手順は、build.xmlに記述します。
Android は標準で ant のビルドをサポートしているので、コマンドで簡単に ant のビルド手順を適用することができます。

android update project -p <Project Path> -n <Project Name>
$ android update project -p ./main -n MyMainProject

テストプロジェクトに ant のビルド手順を適用するには、下記のコマンドを使用します。

android update test-project -p <Project Path> -m <Target Project Path>
$ android update test-project -p ./test -m ./main

ビルドコマンドを実行する

Android の ant でサポートされているコマンドには、下記のものがあります。
ant にビルドをさせる場合には、これらのコマンドを組み合わせてビルドの指示をします。

コマンド 意味
debug デバッグビルドを実行
release リリースビルドを実行
install 端末にビルド成果物をインストール
test テストの実行
emma テストカバレッジを計測する
$ ant debug install test

Gradle

ant に代わる自動ビルドツールです。
こちらは xml ではなく、Groovy で記述します。

Android のビルドについて(Gradle)を参照してください

ProGuard

ProGuard は、ソースコードの難読化と最適化を行うツールです。
apk に含まれる中間コードを逆コンパイルしても、プログラムの意味を人間にとって理解しにくい形にしておくことで、ソースコードの流出を防ぎます。
また、ソースコードの最適化において、不要なクラスを削除したり、インライン化を行ったりすることで、apk 自体のサイズが小さくなります。

難読化は、署名済みのリリースビルド版を生成するときに自動で実行されます。
実行後、プロジェクトディレクトリ内に、proguardというディレクトリが生成され、難読化に用いられた情報や、難読化前と難読化後の対応関係を示すマッピング情報などが保存されます。

設定ファイル

Android はデフォルトで、<sdk-root>/proguard/proguard-android.txt にある設定を読み、これを元に難読化・最適化をコントロールしています。
プロジェクト毎に固有の設定をしたい場合は、プロジェクトディレクトリの中にあるproguard-project.txtを編集します。

# MySampleClass の public なメンバを難読化しないようにする
-keepclassmembers class jp.mixi.sample.MySampleClass {
   public *;
}

また、project.propertiesファイルに、下記の文を記述します。

## 通常であれば、デフォルトでコメントアウトされたものがあるので、コメントアウトを外すだけで良い
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

アノテーション

設定ファイルの代わりにアノテーションを用いて難読化の設定を行うこともできます。

アノテーションで難読化の設定をする場合は、アノテーション用の jar ファイルを導入する必要があります。
<sdk-root>/tools/proguard/examples/annotations/libの中に、annotations.proannotations.jarの 2 つのファイルがありますので、両方共を、プロジェクトのlibsディレクトリに配置し、プロジェクトの設定で、annotations.jarへのパスを設定します。

// クラス名を難読化しない
@Keep
public class MySampleClass {
    public String mHogehoge; // このフィールドは難読化される
    @KeepName
    public String mFugafuga; // このフィールドは難読化されない
}

再トレース

難読化の影響は、コードそのものだけでなく、スタックトレースにも及びます。
このため、例外のスタックトレースの出力もまた、難読化された状態で出力されます。

例外のスタックトレースの内容を解析して、実際のコード上のどこで例外が発生したかを捉えたい場合、
ProGuard の retrace という機能を用いて、難読化を復元することができるようになっています。

ProGuard は、Android SDK の tools に含まれています。
この中の、proguard/bin/proguardgui.shを実行すると、GUI アプリケーションとして、ProGuard が起動します。

ProGuard

このアプリケーションの、ReTrace タブに、再トレースしたいスタックトレースと、難読化のマッピング情報を含むmapping.txtを渡すと、サイトレースが出来るようになります。

Retrace

実習・課題

デバッグ

  1. (実習) 実習プロジェクトDebugPracticeをビルド・インストールし、起動してから画面が立ち上がるまでのメソッドのプロファイリングを実行し、どのメソッドに時間がかかっているかレポートしてください。

自動ビルド

  1. (実習) リポジトリにある好きなプロジェクトを 1 つに、ant を適用してください。
  2. (実習) 適用したプロジェクトを ant でビルドし、ログを見て、ビルドに必要な手順をレポートしてください。