Edited at

CLIでAndroidアプリのデバッグをするためにStetho Custom dumpapp Pluginsを作る

More than 3 years have passed since last update.

Stethoが便利なので、より活用するべく、Custom dumpapp Pluginsの作り方を調べてみました。

スクリーンショット 2015-05-28 21.54.46.png


Stethoについて

まず、Stethoについてですが、Chrome DevTools上でのAndroidアプリのデバッグを可能としてくれるFacebook製ソフトウェアです。

Stetho

Stethoを使うと以下のようなことができるようになる。


Network Inspection

スクリーンショット 2015-05-28 21.55.28.png

Chrome DevToolsのNetwork Inspection(JSONレスポンスhelperや画像プレビュー、HARフォーマットでのエクスポートなど)をAndroidアプリの通信においても使えるようになる。


Database Inspection

スクリーンショット 2015-05-28 22.07.17.png

SQLiteやPreferenceの値を、Chrome DevToolsの使い慣れたUIで、確認したり書き換えたりできるようになる。


View Hierarchy

スクリーンショット 2015-05-28 21.54.33.png

Chrome DevToolsの見慣れた画面で、アプリのView hierarchyを確認することができる。

「Copy XPATH」とかも使えるので、Appiumとかでテストするときも便利そう。


dumpapp

スクリーンショット 2015-05-28 22.16.54.png

これは他と少し毛色の違う機能で、dumpappはChrome DevToolsを使ってではなく、コマンドライン上からのAndroidアプリのデバッグを可能としてくれる。

さらにdumpappは拡張することができる(Custom dumpapp Plugins)。

そのCustom dumpapp Pluginsの作リ方に関しては、「See the stetho-sample project for more details.」と書いてあるのみで、他に説明は無いっぽいので、サンプルを参照しながら、実際に作ってみることにする。


Stethoの導入


build.gradle


build.gradle

compile 'com.facebook.stetho:stetho:1.1.1'

// 以下はNetwork inspectionする場合に必要
// OkHttpを使う場合
compile 'com.facebook.stetho:stetho-okhttp:1.1.1'
// UrlConnectionを使う場合
compile 'com.facebook.stetho:stetho-urlconnection:1.1.1'


Applicatioクラス

public class MyApplication extends Application {

public void onCreate() {
super.onCreate();
Stetho.initialize(
Stetho.newInitializerBuilder(this)
// dumpappを有効にする
.enableDumpapp(
Stetho.defaultDumperPluginsProvider(this))
// Chrome DevToolsでのデバッグを有効にする
.enableWebKitInspector(
Stetho.defaultInspectorModulesProvider(this))
.build());
}
}


Network Inspection機能を使う場合

OkHttp

OkHttpのNetworkInterceptorsにStethoInterceptorを追加するだけでOK。

OkHttpClient client = new OkHttpClient();

client.networkInterceptors().add(new StethoInterceptor());

HttpURLConnection

HttpURLConnectionの場合は、ちょっと面倒。

以下のサンプルのように実装する必要がある。

Networker.java


dumpappを使う場合

dumpappコマンド(stethoのリポジトリに含まれている)のパスを環境変数に追加

export PATH=$PATH:/path/to/stetho/scripts”

※ Python 3がインストールされてない場合はインストールが必要。


Stethoが提供するdumpapp Plugins

最初から、いくつかのdumpapp Pluginsが提供されているので、調査がてら見てみる。

Stetho.defaultDumperPluginsProvider(this)で使えるようになるのは、以下の3つ。


Stetho.java

plugins.add(new HprofDumperPlugin(context));

plugins.add(new SharedPreferencesDumperPlugin(context));
plugins.add(new CrashDumperPlugin());

Stetho.java


SharedPreferencesDumperPlugin

SharedPreferenceの値を出力したり書き換えたりできる。

SharedPreferencesDumperPlugin.java

write

# dumpapp prefs write <path> <key> <boolean|int|long|float|string|set> <value>

dumpapp prefs write shikato shikatokey string shikatoval

print

dumpapp prefs print

# 以下のように出力される
# shikato:
# shikatokey = shikatoval


CrashDumperPlugin

クラッシュを意図的に発生させることができる。

CrashDumperPlugin.java

引数で指定(デフォルトはjava.lang.Error)した例外を発生させる。(simulates a program crash)

dumpapp crash throw java.lang.NullPointerException

System.exitを使う。(simulates an abnormal Android exit strategy)

dumpapp crash exit

ProcessBuilderを使ってkillコマンドを実行。(simulates the low memory killer)

dumpapp crash kill


HprofDumperPlugin

Heap dump(HPROF)を、stdoutに出力したり、Android端末内のファイルに書き込んだりできる。

HprofDumperPlugin.java

dumpapp hprof -


Custom dumpapp Pluginsの作り方

HelloWorldなサンプル dumpapp Plugin。


HelloWorldDumperPlugin.java

// DumperPluginをimplementsする

public class HelloWorldDumperPlugin implements DumperPlugin {
private static final String NAME = "hello";

// getNameで返す値がdumpappp実行時のコマンドとなる
// ex.) appdump {{NAME}}
@Override
public String getName() {
return NAME;
}

// getNameで指定したコマンドを実行したときに呼ばれるメソッド
@Override
public void dump(DumperContext dumpContext) throws DumpException {
PrintStream writer = dumpContext.getStdout();
// {{NAME}}以降の引数が返ってくる
// appdump {{NAME}} hoge huga
Iterator<String> args = dumpContext.getArgsAsList().iterator();

String helloToWhom = args.hasNext() ? args.next() : null;
if (helloToWhom != null) {
doHello(writer, helloToWhom);
} else {
doUsage(writer);
}
}

private void doHello(PrintStream writer, String name) throws DumpUsageException {
if (TextUtils.isEmpty(name)) {
// This will print an error to the dumpapp user and cause a non-zero exit of the
// script.
throw new DumpUsageException("Name is empty");
}

writer.println("Hello " + name + "!");
}

private void doUsage(PrintStream writer) {
writer.println("Usage: dumpapp " + NAME + " <name>");
}
}


HelloWorldDumperPlugin.java

作ったCoustom dumpapp Pluginを有効にするには以下の様に実装する。


SampleDebugApplication.java

  @Override

public void onCreate() {
super.onCreate();

long startTime = SystemClock.elapsedRealtime();
final Context context = this;
Stetho.initialize(
Stetho.newInitializerBuilder(context)
// DumperPluginsProviderをimplementsしたクラスを渡す
.enableDumpapp(new SampleDumperPluginsProvider(context))
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(context))
.build());
long elapsed = SystemClock.elapsedRealtime() - startTime;
Log.i(TAG, "Stetho initialized in " + elapsed + " ms");
}

// DumperPluginsProviderをimplementsしたクラスを用意する
private static class SampleDumperPluginsProvider implements DumperPluginsProvider {
private final Context mContext;

public SampleDumperPluginsProvider(Context context) {
mContext = context;
}

@Override
public Iterable<DumperPlugin> get() {
ArrayList<DumperPlugin> plugins = new ArrayList<DumperPlugin>();
for (DumperPlugin defaultPlugin : Stetho.defaultDumperPluginsProvider(mContext).get()) {
plugins.add(defaultPlugin);
}
// 有効にしたいPluginを追加する
plugins.add(new HelloWorldDumperPlugin());
plugins.add(new APODDumperPlugin(mContext.getContentResolver()));
return plugins;
}
}


SampleDebugApplication.java

HelloWorldDumperPluginを実行すると、こんな感じに出力される。

スクリーンショット 2015-05-28 22.32.16.png


InfoDumperPlugin

簡単に作れそうなので、実際に作ってみる。

作ってみたのは、dpiやBuildConfigの値など、コマンドライン上から確認できると便利そうな値を出力するプラグイン。

info-dumper

screen gif

今のところ以下のような情報を表示できる。

Command
Action

buildconf
BuildConfig fields.

id
AndroidID, UUID, Advertising ID.

dpi
dpi info.

memory
Memory info

network
Network info.

permission
Required permissions.

lastupdate
Lastupdate time.

error
Error state info.

tel
TelephonyManager info.

appinfo
android.content.pm.ApplicationInfo fields.

osbuild
android.os.Build fields.

all
all.


最後に

Stethoかなり便利。dumpappもっと活用していきたい。

せっかく作ったInfoDumperPluginも、もうちょっと便利にしたい。


メモ

DevToolsにdumpappが組み込まれるかも?

lynfogeek commented on 23 Feb

The DumperPlugins are great, but it would be even better to embed them into the DevTools.
One solution could be to create a new tab (like this extension does) , and list there all the enable plugins. Whenever the user click on one of them, it pulls the data and display it.

(commented on 23 Febとなってるので望み薄かもだけど)

https://github.com/facebook/stetho/issues/68