2011年6月22日水曜日

【Android】DDMSのタグフィルターを正規表現で絞っちゃいなよ(配布もあるよ)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
タグの絞り込みで正規表現使えたらいいかもなーくらいに思っていたのでやりました。
ちょっと長いけど導入自体は超簡単です。うんちくが長いだけです。

※利用は自己責任でヨロシクお願いします☆

タグで正規表現


こんな感じ。suffixが"Service"であるタグを絞り込みする例

配布物


ddms_add.jarってのを使います。ていうか作りました。
https://sites.google.com/site/goatprog/android/androidproject/ddms_add.jar?attredirects=0&d=1

試す人はとりあえず落として下さい。


どーやったか


DDMSはJavaの住人です。もうなんでもありです。日本語対応の時も書いた気がするな・・・。
という事で、以下の手順でいい感じにクラスを上書きしています。

  1. エントリポイントになるクラスを作ってDDMSのMainの代わりに実行
  2. DDMSのMainを呼ぶ前に書き換えたいクラスをClass.forName()で読み込む。
  3. DDMSのMainを呼び出す。

こんだけです。クラスパスがポイントですね。書き換えたいクラスを含むパスを前に持って来るだけでおk。
Androidのmasterブランチから持ってきたDDMSのソースをいじってビルドして出来たクラスを使っています。


改造内容


いじったのはたったの一行です。
$ANDROID_HOME/sdk/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogFilter.java
boolean accept(LogMessage logMessage) {
        // do the regular filtering now
        if ((mMode & MODE_PID) == MODE_PID && mPid != logMessage.data.pid) {
            return false;
        }

        if ((mMode & MODE_TAG) == MODE_TAG && (
                logMessage.data.tag == null ||
                //logMessage.data.tag.equals(mTag) == false)) {
             logMessage.data.tag.matches(mTag) == false)) { //ここ
            return false;
        }
      -----略-----
    }

このクラスはlogcatをフィルタリングする際の各種条件を保持しているクラスです。
logcatから新たなログが送られてくると、各タブは各自が持つLogFilterのaccept(LogMessage)メソッドを呼び出して、
自分の領域にログを表示するかどうか判定をします。
タグの部分は元々equals(Object)で判定されていました。それをmatches(String)に変えただけです。
本当はPattern#compile(regex)して出来たPatternを保持した方が毎回String#matches(String)を実行するよりいいのですが、修正範囲が広がるのでやめました。動作上全く影響ないです。


課題


実は今まで知らなかったのですが、フィルターは":"と"|"が使えません。
どうもEclipseのプラグイン上のDDMSや、DDMS単体のタブ情報を保存する為に、":","|"をセパレータとして使っているみたいです。
なので今回の修正では完全な正規表現は使えません。

LogFilterにはLogFilterの中身を書きだすtoString()とStringからLogFilterを復元するloadFromString(String)があります。
ここを改造してあげる必要があるんですねーーーー。

@Override
    public String toString() {
        StringBuilder sb = new StringBuilder(mName);

        sb.append(':');
        sb.append(mMode);
        if ((mMode & MODE_PID) == MODE_PID) {
            sb.append(':');
            sb.append(mPid);
        }

        if ((mMode & MODE_LEVEL) == MODE_LEVEL) {
            sb.append(':');
            sb.append(mLogLevel);
        }

        if ((mMode & MODE_TAG) == MODE_TAG) {
            sb.append(':');
            sb.append(mTag);
        }

        return sb.toString();
    }

    public boolean loadFromString(String string) {
        String[] segments = string.split(":"); //$NON-NLS-1$
        int index = 0;

        // get the name
        mName = segments[index++];

        // get the mode
        mMode = Integer.parseInt(segments[index++]);

        if ((mMode & MODE_PID) == MODE_PID) {
            mPid = Integer.parseInt(segments[index++]);
        }

        if ((mMode & MODE_LEVEL) == MODE_LEVEL) {
            mLogLevel = Integer.parseInt(segments[index++]);
        }

        if ((mMode & MODE_TAG) == MODE_TAG) {
            mTag = segments[index++];
        }

        return true;
    }
こんな感じで":"使ってますね。各値をBase64か何かでエンコード/デコードすりゃいいんじゃね、と思います。
今回はやりません。


導入手順 Windows編


簡単です。
ddms_add.jarを以下の場所に配置してください。つーかddms.jarがある所と同じ場所。
$ANDROID_SDK_HOME/tools/lib/
そしてddms.batをちょっといじります。
とりあえずddms.batをコピーしてddms_add.batとかにでもして下さい。
やる事は
  • クラスパスを追加
  • メイン呼び出しを書き換え
です。
ddms.batの一番下でjavaを実行しています。これをちょっと書き換えます。

call %java_exe% %java_debug% -Dcom.android.ddms.bindir=%prog_dir% -classpath "%jarpath%;%swt_path%\swt.jar" com.android.ddms.Main %*
          ↓
call %java_exe% %java_debug% -Dcom.android.ddms.bindir=%prog_dir% -classpath "./lib/ddms_add.jar;%jarpath%;%swt_path%\swt.jar" jp.dip.sys1.android.ddms.Main %*

こんだけ。あとは"ddms_add"をコマンドプロンプトで叩くとか。


導入手順 Mac編


Windows編とほぼ同じです。略します。
ddms.batの代わりにddms.shか何かがいるはずです。それを書き換えます。

#exec "$javaCmd" -Xmx256M $os_opts $java_debug -Dcom.android.ddms.bindir="$progdir" -classpath "$jarpath:$swtpath/swt.jar" com.android.ddms.Main "$@"
          ↓
exec "$javaCmd" -Xmx256M $os_opts $java_debug -Dcom.android.ddms.bindir="$progdir" -classpath "lib/ddms_add.jar:$jarpath:$swtpath/swt.jar" jp.dip.sys1.android.ddms.Main "$@"

最後に


【緩募】
もうちょい色々検討した上でpatchを投げたいとか思っているわけですが、
その辺全くしらないので手とりナニとり教えてくれる有識者の方教えて下さい・・・。


追記2011/6/22 14:18
今すぐフォローすべきAndroid界のスーパーエンジニア@keiji_ariyamaさんからadt-devのメーリングリストで聞け!というアドバイスを頂きました!やってみたいと思います。
ありがとうございました真・今すぐフォローすべきAndroid界のスーパーエンジニア@keiji_ariyamaさん!

2 件のコメント:

  1. これはEclipseのプラグインの方にも適応できたりは… するのでしょうか?

    ddmsをいちいち立ち上げるのがめんどくさいのと、デバッグをeclipseからしなおしたときにににddmsがアタッチしてしまってeclipseでデバッグできなくなってしまうのです。

    もし情報などありましたら、ご教示いただければと思います。

    返信削除
  2. こんにちは!

    Eclipse側はADT Plugin for EclipseというEclipse用のプラグインとして独立して作られているので今回の改造を利用する事はできません。

    ADT Plugin for Eclipse用に別途ddms.jarの様なものが存在しているのでそれを改造してやる必要がありますがめんどうかもしれないですね。

    返信削除