これは下記コマンドが実行された時に、サービスの状態をダンプするメソッドです。
$ adb shell dumpsys activity service <yourservicename>Service.dump
http://developer.android.com/reference/android/app/Service.html#dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[])
dumpメソッドにはPrintWriterインスタンスが引数として渡されます。
これにサービスの情報を入力すれば、ログとしてそれが出力されます。
・動作サンプル
$ adb shell dumpsys activity service yuki.test.messenger/.MyMessengerMyMessenger.java
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] options) {
pw.println("MyMessenger dump!!!");
}
-出力結果-SERVICE yuki.test.messenger/.MyMessenger 41fa2ef0 pid=6151 Client: MyMessenger dump!
Service.dumpメソッドを提供することで、開発者はサービスの情報を好きなタイミングで取得することが可能です。
※ただし、対象のサービスが実行中であることが前提です
ActivityManagerServiceもこのメソッドを提供しています。
ActivityManagerServiceをdumpすればデバッグ時に有益な情報を確認できます。
⇒http://yuki312.blogspot.jp/2012/04/androidactivity.html
Object.toStringのそれと同じく、Service.dumpは非常に有益なメソッドです。
toStringをオーバライドする際の一般契約と同じように、dumpする内容は"簡素であり、読みやすく、有益な表現"であるべきでしょう。
●サンプルコード
Service.dumpの第三引数 options にはコマンド引数が格納されます。$ adb shell dumpsys activity service yuki.test.messenger/.MyMessenger -a -b -cであれば
options[0] = "-a"
options[1] = "-b"
options[2] = "-c"
といった具合です。
これらを活用すれば、必要に応じたダンプ情報を得ることができます。
また、よくある"ヘルプコマンド"も実装可能です。
下記はそのサンプルコードです。
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] options) {
boolean dumpAll = false;
boolean dumpClient = false;
boolean dumpMessage = false;
boolean dumpState = false;
int optionIndex = 0;
while (optionIndex < options.length) {
String option = options[optionIndex];
if (TextUtils.isEmpty(option) || option.charAt(0) != '-') {
break;
}
optionIndex++;
if ("-a".equals(option) || "-all".equals(option)) {
dumpAll = true;
} else if ("-c".equals(option) || "-client".equals(option)) {
dumpClient = true;
} else if ("-m".equals(option) || "-message".equals(option)) {
dumpMessage = true;
} else if ("-s".equals(option) || "-state".equals(option)) {
dumpState = true;
} else if ("-h".equals(option) || "-help".equals(option)) {
pw.println("MyMessenger dump options:");
pw.println(" [-a] [-c] [-m] [-s]");
pw.println(" a[ll]: dump all info.");
pw.println(" c[lient]: reply target.");
pw.println(" m[essage]: handle message log.");
pw.println(" s[tate]: service state change log.");
return;
} else {
pw.println("Unkown argument: " + option + "; use -h for help.");
}
}
pw.println("Service state");
pw.println(" Service create time is " + new Date(mOnCreateTime));
pw.println(" " + mCurrentState);
pw.println();
if (dumpClient || dumpAll) {
pw.println("Client(" + mClients.size() + ")");
for (ClientRecord cr : mClients.keySet()) {
pw.println(" " + cr);
}
pw.println();
}
if (dumpMessage || dumpAll) {
pw.println("Message Logs");
for (MessageLog log: mMessageLogs) {
pw.println(" " + log);
}
pw.println();
}
if (dumpState || dumpAll) {
pw.println("ServiceState Logs");
for (ServiceState.ServiceStateLog log: mCurrentState.getStateLogs()) {
pw.println(" " + log);
}
pw.println();
}
}
-出力結果-・引数無し
$ adb shell dumpsys activity service yuki.test.messenger/.MyMessenger SERVICE yuki.test.messenger/.MyMessenger 41fd0950 pid=6151 Client: Service state Service create time is Sun Jan 06 03:58:13 GMT+00:00 1980 Current service state is RUNNING・引数指定(-c:クライアント情報出力, -m:メッセージ履歴出力)
$ adb shell dumpsys activity service yuki.test.messenger/.MyMessenger -c -m
SERVICE yuki.test.messenger/.MyMessenger 41fa2ef0 pid=6151
Client:
Service state
Service create time is Sun Jan 06 03:58:28 GMT+00:00 1980
Current service state is BLOCKED
Client(2)
ClientRecord [ PackageName=test.pkg1, ID=1, hash=b6f4c7b1 ]
ClientRecord [ PackageName=test.pkg2, ID=1, hash=b6f4c7b2 ]
Message Logs
03:58:44.570: { what=3 when=-1ms }
03:58:44.339: { what=2 when=-1ms }
03:58:28.681: { what=1 when=-5ms }
・引数指定(-a:全情報出力)
$ adb shell dumpsys activity service yuki.test.messenger/.MyMessenger -a
SERVICE yuki.test.messenger/.MyMessenger 41fa2ef0 pid=6151
Client:
Service state
Service create time is Sun Jan 06 03:58:28 GMT+00:00 1980
Current service state is BLOCKED
Client(2)
ClientRecord [ PackageName=test.pkg1, ID=1, hash=b6f4c7b1 ]
ClientRecord [ PackageName=test.pkg2, ID=1, hash=b6f4c7b2 ]
Message Logs
03:58:44.570: { what=3 when=-1ms }
03:58:44.339: { what=2 when=-1ms }
03:58:28.681: { what=1 when=-5ms }
ServiceState Logs
03:58:44.571: { RUNNING => BLOCKED }
03:58:44.340: { NEW => RUNNING }
・引数指定(-h:ヘルプ)$ adb shell dumpsys activity service yuki.test.messenger/.MyMessenger -h SERVICE yuki.test.messenger/.MyMessenger 41fa2ef0 pid=6151 Client: MyMessenger dump options: [-a] [-c] [-m] [-s] a[ll]: dump all info. c[lient]: reply target. m[essage]: handle message log. s[tate]: service state change log.・引数指定(-p:サポートしない引数)
$ adb shell dumpsys activity service yuki.test.messenger/.MyMessenger -p SERVICE yuki.test.messenger/.MyMessenger 41fa2ef0 pid=6151 Client: Unkown argument: -p; use -h for help. Service state Service create time is Sun Jan 06 03:58:28 GMT+00:00 1980 Current service state is BLOCKED
便利ですね。好きなタイミングで実行できるのが強力です。
注意すべき点として、、、
ログ出力の場合と同じく、dump情報で出力する情報には注意が必要です。
# Service.dumpで出力される情報はbugreportにも出力されます。
開発時以外に必要ないのであれば、ビルドタイプでdump情報を絞る等の対応を考えます。
以上です。