コマンドラインから標準Javaで動作するが、4.2を実行しているGalaxy NexusのAndroidでは動作しない次のコードに頭を悩ませています。http://cleverbot.com/webserviceminへの投稿を試みた 2 つのバリエーションを含めます。元の投稿ロジックは、chatterbot APIから取得したもので、修正されたロジックは、Java で利用可能なさまざまな Http API を使用する試みでした。これは、chatterbot APIをテスト プロジェクトに含める単純な試みです。どちらのバージョンも Android では動作しませんが、オリジナルは標準の Java を使用して cmd ラインのメイン アプリから動作します。
private static String revisedPostLogic(String url, Map<String, String> parameters) throws IOException {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(parameters.size());
for(Map.Entry<String,String>eachEntry : parameters.entrySet())
nameValuePairs.add(new BasicNameValuePair(eachEntry.getKey(),eachEntry.getValue()));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpClient.execute(httpPost);
ByteArrayOutputStream rawResponse = new ByteArrayOutputStream();
response.getEntity().writeTo(rawResponse);
return rawResponse.toString();
}
private static String old_post_logic(String url, Map<String, String> parameters) throws Exception {
URLConnection connection = new URL(url).openConnection();
((HttpURLConnection) connection).setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
OutputStreamWriter osw = new OutputStreamWriter(connection.getOutputStream());
osw.write(parametersToWWWFormURLEncoded(parameters));
osw.flush();
osw.close();
Reader r = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringWriter w = new StringWriter();
char[] buffer = new char[1024];
int n = 0;
while ((n = r.read(buffer)) != -1) {
w.write(buffer, 0, n);
}
r.close();
return w.toString();
}
修正されたロジックではサーバー例外からの応答がなく、元のロジックでは EOFException が発生します。
アップデート
Android とデスクトップ Java からこれを実行しようとしましたが、矛盾が生じます。
new java.net.URL("http://cleverbot.com/webservicemin").openConnection().getResponseCode()
デスクトップ Java では応答コード 200 が返されます (ストリームを読み取ろうとしたことはありませんが、"DENIED" というテキストが返されると思います) Android では "EOFException" が返されます。デスクトップ Java (現在は Groovy をショートカットとして使用) で、応答コード、ヘッダー、および応答コンテンツをダンプすると、次のようになります。
response code: 200
Headers: [null:[HTTP/1.1 200 OK], SC:[6870], RPS:[server52054], MIME-Version:[1.0], Content-Length:[29], Expires:[Mon, 18 Feb 2013 20:07:20 GMT], Set-Cookie:[RPS=server52054, JSESSIONID=6C765C93A085F67D69F800D9EB76646C; Path=/], Connection:[keep-alive], Server:[Jabberwacky], RLM:[2416], Cache-Control:[no-cache;no-store], Pragma:[no-cache], Date:[Mon, 18 Feb 2013 19:56:42 GMT], Content-Type:[text/html;charset=iso-8859-1]]
Response: DENIED
Androidで同じことを試みても、応答コードを渡すことができません。問題なくパスなしでルート URL に接続できます。これは、GET または POST で EOFException を取得したときに、ルート URL からパスをヒットしようとしたときです。また、outputstreamwriter close() 呼び出しを最後に移動して、出力ストリームを閉じる前に応答コードを読み取れるようにしました。この場合でも EOFException が発生します。(モバイルアプリで出力ストリームを途中で閉じると、接続全体がシャットダウンされる可能性があることを経験から学びました。)