特定の端末でhttpResponseをEntityUtils.toStringしようとするとSocketExceptionが発生した
先日発生した事象です。出先で端末をお借りしてデバッグしたのであまり追求できなかったのですが、何だこれよくわからんと思ったので、メモしておきます。
現象
特定の端末(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(); } }