読者です 読者をやめる 読者になる 読者になる

Androidはワンツーパンチ 三歩進んで二歩下がる

Android卵プログラマーの記録ブログ

特定の端末でhttpResponseをEntityUtils.toStringしようとするとSocketExceptionが発生した

Android

先日発生した事象です。出先で端末をお借りしてデバッグしたのであまり追求できなかったのですが、何だこれよくわからんと思ったので、メモしておきます。

現象
特定の端末(305SH)でHttp通信を行った際、レスポンスをStringにする箇所でSocketExceptionが発生してしまう。

コード

        String jsonResponse = null;
        try {
            HttpEntity entity = new StringEntity(obj);
            HttpClient httpClient = new DefaultHttpClient();
            HttpDeleteWithBody httpDeleteWithBody = new HttpDeleteWithBody(url);
            httpDeleteWithBody.setEntity(entity);
            httpDeleteWithBody.setHeader(HttpConst.HEADER_LOGIN_TOKEN_KEY,
                    HttpConst.HEADER_LOGIN_TOKEN);
            httpDeleteWithBody.setHeader(HttpConst.HEADER_UID_KEY, Pref.getPrefString(
                    MyApplication.getContext(), HttpConst.HEADER_UID_KEY));

            HttpResponse response = httpClient.execute(httpDeleteWithBody);
            int statusCode = response.getStatusLine().getStatusCode();
            httpClient.getConnectionManager().shutdown();
            jsonResponse = EntityUtils.toString(response.getEntity(), "UTF-8");//ここで発生!


その時のログはこんな感じです。

06-18 15:05:01.059  14503-16653/jp.co.hoge D/logDebug﹕ jp.co.hoge.task.DeleteHogeTask.doInBackground(DeleteHogeTask.java:73):  start...
06-18 15:05:01.519  14503-16653/jp.co.hoge W/System.err﹕ java.net.SocketException: Socket closed
06-18 15:05:01.529  14503-16653/jp.co.hoge W/System.err﹕ at libcore.io.Posix.recvfromBytes(Native Method)
06-18 15:05:01.529  14503-16653/jp.co.hoge W/System.err﹕ at libcore.io.Posix.recvfrom(Posix.java:141)
06-18 15:05:01.529  14503-16653/jp.co.hoge W/System.err﹕ at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
06-18 15:05:01.529  14503-16653/jp.co.hoge W/System.err﹕ at libcore.io.IoBridge.recvfrom(IoBridge.java:506)
06-18 15:05:01.529  14503-16653/jp.co.hoge W/System.err﹕ at java.net.PlainSocketImpl.read(PlainSocketImpl.java:489)
06-18 15:05:01.539  14503-16653/jp.co.hoge W/System.err﹕ at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
06-18 15:05:01.539  14503-16653/jp.co.hoge W/System.err﹕ at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:241)
06-18 15:05:01.539  14503-16653/jp.co.hoge W/System.err﹕ at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
06-18 15:05:01.539  14503-16653/jp.co.hoge W/System.err﹕ at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:191)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:220)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:183)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:155)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:159)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at java.io.InputStreamReader.read(InputStreamReader.java:233)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at java.io.Reader.read(Reader.java:141)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at org.apache.http.util.EntityUtils.toString(EntityUtils.java:135)
06-18 15:05:01.549  14503-16653/jp.co.hoge W/System.err﹕ at jp.co.hoge.task.DeleteHogeTask.doInBackground(DeleteHogeTask.java:89)

問題の箇所は
jsonResponse = EntityUtils.toString(response.getEntity(), "UTF-8");
の行です。
うーん、Xperia ZL2やNexus5では全くエラーにならないのですが、 何でしょうね〜(´ε`;)ウーン…

EntityUtils.javaのコードを見てみました。↓
src/org/apache/http/util/EntityUtils.java - platform/external/apache-http - Git at Google

もしかして何となくこのあたり?(超適当)

String charset = getContentCharSet(entity);


そこで、"UTF-8"と指定している箇所を下記のように修正したらエラーにならなくなり、全く問題なく
処理を行うことが出来ました。
"UTF-8"の書き方自体は間違っていないと思います。↓も確認しましたので。

GC: HTTP - org.apache.http.protocol.HTTP (.java) - GrepCode Class Source

機種依存っぽいような、サーバーからのレスポンス(ここに載せてなくてごめんなさい。でもよくあるステータスコード程度のレスポンスです)が何かおかしいっぽいようなよくわからない結果なのですが、
本当にどなたか知恵者の方に教えていただければ嬉しいです。


実際にうまく動いたソース


        String jsonResponse = null;
        try {
            HttpEntity entity = new StringEntity(obj);
            HttpClient httpClient = new DefaultHttpClient();
            HttpDeleteWithBody httpDeleteWithBody = new HttpDeleteWithBody(url);
            httpDeleteWithBody.setEntity(entity);
            httpDeleteWithBody.setHeader(HttpConst.HEADER_LOGIN_TOKEN_KEY,
                    HttpConst.HEADER_LOGIN_TOKEN);
            httpDeleteWithBody.setHeader(HttpConst.HEADER_UID_KEY, Pref.getPrefString(
                    MyApplication.getContext(), HttpConst.HEADER_UID_KEY));

            HttpResponse response = httpClient.execute(httpDeleteWithBody);
            HttpEntity resEntityGet = response.getEntity();

            if (resEntityGet != null) {
                try {
                    jsonResponse= new String(EntityUtils.toString(resEntityGet));
                } catch (ParseException exc) {
                    exc.printStackTrace();
                } catch (IllegalStateException exc) {
                    exc.printStackTrace();
                }
            }