むらかみの雑記帳

Android とか iOS とかソフトウェア開発に関するネタ帳

Android 版EX予約で予約がうまく行かない件

Android版EX予約で予約がうまく行かない件について。さんざん調査をして試行錯誤を繰り返したのですが、正直改善の見込み薄です。AndroidWebKit 内でエラーが発生しており、エラーから復旧できる見込みがない。

こちらにも解析されている方がいらっしゃいますが、あまり解決には至っていない様子。

一応、これまでの経緯をメモしておきます。

何が問題となっているのか

Android版EX予約で予約をすすめると、予約途中で「次へ」ボタンを押したときにエラー画面に遷移し、戻れなくなります。

私が試した限りでは、時刻指定画面で「次へ」ボタンを押したときにこの現象になることが多いようです。

原因追求

問題がおきたときの Android 側のログには以下のように表示されていました。

07-06 23:09:49.676: WARN/System.err(319): java.io.IOException: SSL shutdown failed: I/O error during system call, Broken pipe
07-06 23:09:49.716: WARN/System.err(319):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeclose(Native Method)
07-06 23:09:49.766: WARN/System.err(319):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:958)
07-06 23:09:49.766: WARN/System.err(319):     at android.net.http.AndroidHttpClientConnection.close(AndroidHttpClientConnection.java:245)
07-06 23:09:49.776: WARN/System.err(319):     at android.net.http.HttpsConnection.closeConnection(HttpsConnection.java:387)
07-06 23:09:49.806: WARN/System.err(319):     at android.net.http.Connection.httpFailure(Connection.java:450)
07-06 23:09:49.806: WARN/System.err(319):     at android.net.http.Connection.processRequests(Connection.java:247)
07-06 23:09:49.816: WARN/System.err(319):     at android.net.http.ConnectionThread.run(ConnectionThread.java:113)
07-06 23:10:08.497: DEBUG/ExYoyaku(319): WebViewClient: error, url='https://shinkansen1.jr-central.co.jp/RSV_P/pC2/ClientService;jsessionid=oV0oYs4GA0SB7lE32gK0nxM';, desc=The Web page contains an error.

SSL の例外が起きて、スタックトレースが表示されています。これは HTTP 通信スレッド内で起こった例外です。

SSL 例外は別に問題ではなく、真の問題は android.net.http.Connection.httpFailure() が呼ばれていること。つまり、HTTPエラーが起こっているわけです。

Androidコア側のソースを repo で取り出して内容を追ってみましたが、HTTPのやりとりをしているときに例外が発生するとここに来るようです。ソースを見る限りでは1回はリトライをして、2回失敗したらコネクションをクローズ(HttpsConnection.closeConnection)に行くようになっていました。

どのような HTTP 例外が起こっているのかは不明ですが、SSL で Broken Pipe が起こっているところから見て、TCP コネクション自体が切れているように見えます。一度、Wireshark でログを見てみようかと思ってますが。

ちなみに、このエラー、最新の Android 2.2 (Froyo) でも発生します。

対処について

エラーが起こったら、復帰するのは難しいです。前のページに戻るような実装を入れようかと思ったのですが、EX予約のサイトは「戻る」ボタンを殺しています(戻るをやろうとすると、ログインしなおし)。当然、リロードもダメ。

HTTP リクエストをもう一度やり直すのが正しいのですが、それは WebKit 内部の話なので難しいです。

つーか、リトライが1回だけってのは少ないような気がする。この回数を増やせればいいのですが、残念ながらこの回数は Java の private かつ final 宣言されてるので変更できません。変更するための API もありません。

あと、ページの完全ロードが終わるまで操作させない、という処理はいれてはみたのですが、あまり改善しませんでした。

そんなこんなで、改善の目処はしばらく立ちそうにありません。。。