Androidの便利なデバッグ手法


Android Advent Calendar 3日目の投稿です

3日目の今日はAndroidアプリ開発でよく利用するのデバッグのTipsを紹介します
(Android Studioの機能をメインに紹介していますが、恐らくEclipseでも同様の機能はあると思います)

## Logクラスを使ったprintfデバッグ


Logクラスを知らない人はまずいないと思うので、サクッと

```java
Log.e(TAG, error);
Log.w(TAG, warn);
Log.i(TAG, info);
Log.d(TAG, debug);
Log.v(TAG, verbose);
```
Logクラスの情報はLogcatと呼ばれるコンソールに出力されます
"TAG"は識別できればなんでもいいですが、クラス名が使われることが多いです

```java
private final static String TAG = ClassName.class.getSimpleName();
```


* AndroidStudio

AndroidStudioの場合は、[View] -> [ToolWindows] -> [Android]を選択するとLogcatを表示できるDDMS(Dalvik Debug Monitor Server)が下に表示されます
<img width=400 src="http://i.gyazo.com/3fdd335baa3da9ac36f89d5252d40e83.png">

* DDMS

DDMSは単体でも起動できて、AndroidSDKのtoolsにいます 例えばこんな感じのパスを叩くと起動します

```shell
/Applications/Android\ Studio.app/sdk/tools/ddms
```

* shellでlogcatをみる

いわゆるcui環境も用意されていて、事前にadbのパスを通しておく必要がありますが、

```shell
adb logcat
```

で起動します
Logcatをpythonスクリプトで見やすく加工した[JakeWharton/pidcat](https://github.com/JakeWharton/pidcat)というツールもあります!

<img width=400 src="https://github.com/JakeWharton/pidcat/raw/master/screen.png">

Logcatでjsonを表示する場合は、こちらが便利です
[[Android] JSONの整形ってこんなに簡単にできるの！？ 〜ログが劇的に見やすくなる魔法の引数〜(クラスメソッド株式会社)](http://dev.classmethod.jp/etc/android-json-reformat/)

## Android Studioでブレークポイントを仕込んで止める

AndroidStudioではブレークポイントを仕込み、実行中のアプリを止めて状態を確認しながら動作検証することが出来ます
ブレークポイントはエディタスペースの左側のラインをクリックして設定します
(何箇所でも可能ですが空行には設定できません)
<img width=600 src="http://i.gyazo.com/29a7e3964ab30a51dc8ed5ec7adbdefd.png">

ムシっぽいアイコンをクリックすると 通常のビルドと同様アプリケーションが端末にインストールされます

<img  src="http://i.gyazo.com/a6f0cbd23e0fbee343b84255ffb73c65.png">

アプリが起動するとDebuggerとAttachするまで待機画面が表示されます(デバッグ時はアプリが少し重くなります)

<img width=200 src="http://i.gyazo.com/407c31194f832caabab215d76d7e2fa0.png">

アプリがブレークポイントで止まると、下のような画面が表示されます
表示されない場合はDDMSと同様に[View] -> [ToolWindows] -> [Debug]を選択すると表示されます
<img width=500 src="http://i.gyazo.com/f7e1549be2fa3f1a7c123d16bb9baa5f.png">

この画面でよく使うのは、

* 左上の緑色の再生ボタン(次のブレークポイントまで実行)
* 二つ下の停止ボタン(デバッグの停止)
* Logcatタブの2つ右の逆コの字ボタン(ステップオーバー[行ごとにステップ実行])
* 一番右側の電卓ボタン(ブレークポイント地点で任意のコードを評価)

また、Debuggerとの接続が切れてしまった場合、ムシの右側のボタン[Attach debbuger to Android Process]で再度Attach出来ます
<img src="http://i.gyazo.com/745d7bed8b7de3c80a29eec34e3a39b5.png">



## プロキシサーバーを使って通信内容を確認する

アプリのソースコードレベルで問題が解決しなかった場合apiサーバーとの通信内容を調べます
例えば開発中はちゃんとstagingサーバーを向いているか、ヘッダーの情報や返ってきたjsonの構造などを確認します

<img src="http://i.gyazo.com/d5dccf80c5c0660d8a6131607649f1d2.png">

Charlesを使うと開発用のプロキシサーバーを簡単に用意することが出来ます

* セットアップ

Charlesは[こちら](http://www.charlesproxy.com/download/)からDL出来ます
無料版は30日間利用できて30分おきにアプリが終了するような仕様だったかと
有料版は5000円くらいしますが、値段以上の価値はあると思いました

[端末側の対応]

* ブラウザからhttp://charlesproxy.com/charles.crt にアクセスし、証明書をインストールします
* wifi設定からプロキシホスト名(開発機のローカルip)とポート(デフォルトは8888)を設定します

<img width=300 src="http://i.gyazo.com/631cdf3c560235ec11d720eaa260527a.png">

[開発機側の対応]

* Charlesを起動し、proxyからproxysettingsを開き、SSLタブからLocationsに*を追加します
<img width=400 src="http://i.gyazo.com/09466e5f23eeeed4fd8259386e2d34fb.png">


* 実際の画面

正常にキャプチャ出来ているとこのような画面になります

<img width=600 src="http://i.gyazo.com/ae54a8aeb855336bb9fbb2b6dc2b0d70.png">

下のタブで返ってきたjsonやヘッダ情報が確認できます
<img width=700 src="http://i.gyazo.com/190accf3829fb1b38cbd2f7e347e0a28.png">

*  mitmproxyについて

Charlesとほとんど同じ機能が使えるmitmproxyというcuiベースのツールもあります
mitmproxyについては[iOS実機のSSL通信をプロキシによって傍受したり改ざんする方法](http://qiita.com/yimajo/items/c67cb711851f747c35e5)に詳しく紹介されています
もちろんAndroidでも利用可能です

## Webviewのデバッグ

webviewのデバッグは地獄のように大変だったりしますが、Android4.4以上の端末をお持ちならリモートデバッグが可能です

どこでもいいんですが(Applicationクラスとかがよさそう)、以下のコードを埋め込みアプリをビルドします

```
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      WebView.setWebContentsDebuggingEnabled(true);
  }
```

端末を接続した状態でChromeで[chrome://inspect](chrome://inspect)を開くとこんな画面が出ます

<img width=500 src="http://i.gyazo.com/fbc5a21842da706b56cfe64113e5329c.png">

inspectを押すと見慣れたインスペクタが表示されます 選択された部分はAndroidでもハイライトされます

<img width=800 src="http://i.gyazo.com/39f7c1df7bccdb38ceadc0389aac4570.png">


## デバッグ時の小ネタ

* ビルドを止めたい  

今だにAndroidStdioでビルドを止めるがわからないのですが (プロジェクトルートに移動し)gradlew --stopで止まるようです

```shell
./gradlew --stop
```

* 既にビルドしたapkを端末にインストールする

adbコマンドを使うと再ビルドすることなく既にビルドされたapkを端末に入れることが出来ます
(こちらもプロジェクトルートに移動して)

```shell
adb install -r app/build/outputs/apk/app-debug.apk
```

* adbの複数端末接続問題

adbは複数端末が繋がれているとオプションでデバイスIDを渡さないとエラーになるんですが
そこら辺の煩わしい問題をpecoを使って解決する方法が以下のエントリーで紹介されています
[複数のAndroid端末を同時につないで困ってませんか？それadb-pecoで選択できるよ！](http://techlife.cookpad.com/entry/2014/09/09/172449)

僕が普段やるデバッグ作業はこんな感じなのですが(あとはapiサーバー側のデバッグ)、
なにか他の素晴らしい方法がありましたら教えて下さい