2012年7月30日月曜日

HTTP logging

Android上で行われるHTTP通信のログを取りたいことがあります。主にデバッグとか。動作確認とか。
カスタムROMを作ればアプリのコードに手を入れなくてもヘッダくらいはロギングできます。
(ストリームに手を入れれば送受信データもロギングできますが、サイズが大きかったりバイナリデータだったりするのでファイル出力するなどの対応が必要でしょう。今回はリクエストヘッダだけをlogcatに出力します)

Android上で主に使われるHTTP通信は2種類あります。(参考

Apache HTTP Client
/external/apache-http にソースがあります。
org.apache.http.client.HttpClient はただのinterfaceなので、必要な実装は org.apache.http.impl.client.AbstractHttpClient やそのサブクラスで行われています。
execute() の本体でログを出力することにしました。差分

HttpURLConnection
こちらは /libcore にソースがあります。
java.net.HttpURLConnection やそのスーパークラス java.net.URLConnection には通信関連のコードはなくて、サブクラス libcore.net.http.HttpURLConnectionImpl から作られる libcore.net.http.HttpEngine が通信のキモです。
sendRequest() でリクエストヘッダの準備をした後でログを出してみました。差分

毎度全部ログを出すのは無駄なので、必要なときだけロギングできるように if (true) のところを適宜いじるといいでしょう。(設定でON/OFFできるようにしてSystemProperties.getBoolean()とか)

ログは
frameworks/base/core/java/android/util/Log.java
frameworks/base/core/jni/android_util_Log.cpp android_util_Log_println_native()
system/core/liblog/logd_write.c __android_log_buf_write() write_to_log()
とソースを追っていくと /dev/log/main に出力していることがわかります。
(LOGGER_LOG_MAIN は system/core/include/cutils/logger.h で "log/main")

system/core/liblog/logprint.c android_log_processLogBuffer() で
    /*
     * format: <priority:1><tag:n>\0<message:n>\0
     *
     * tag str
     *   starts at buf->msg+1
     * msg
     *   starts at buf->msg+1+len(tag)+1
     *
     * The message may have been truncated by the kernel log driver.
     * When that happens, we must null-terminate the message ourselves.
     */
というフォーマットも見つけて、それに則る形で /dev/log/main に出力すればlogcatが拾ってくれます。

※アプリ内で直接Socketを使っていたりする場合はロギングできません。あくまで Apache HTTP Client や HttpURLConnection を使っている場合のロギングです。
※自己責任でご利用ください。

0 件のコメント:

コメントを投稿