HttpClientを利用したAndroidのネットワーク通信
Androidでは、いくつかネットワーク通信する方法があるようですが、org.apache.http パッケージの DefaultHttpClient とかを利用する方法が比較的一般的なようです。
基本的に同期通信なので、データを取得の際にはスレッドを立てるのが良さそうです。
Androidではスレッドを立てる方法もいくつかあるようですが、通常のJavaと同様にRunnableインターフェースを実装して云々するのが簡単でしょう。
ただし、ダウンロード後にGUIを更新したい、というような場合、Activityと同じスレッドでないと例外が出るようになっているので、Handlerを利用する必要があります、、、といつかこれらについてもメモするかもしれません。
手抜きネットワーク通信メソッド
ネットワーク通信は例外処理とかが意外と面倒なので、以下のような手抜きメソッドを作って使いまわしてます。
private String fetch(HttpClient client, HttpUriRequest request) { try { return client.execute(request, new ResponseHandler<String>() { @Override public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException { switch (response.getStatusLine().getStatusCode()) { case HttpStatus.SC_OK: return EntityUtils.toString(response.getEntity(), "UTF-8"); case HttpStatus.SC_NOT_FOUND: throw new RuntimeException("Not found."); default: throw new RuntimeException("Something connection error."); } } }); } catch (ClientProtocolException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } }
はい、例外処理とかあまりに適当すぎですね。
HttpClientインターフェースはDefaultHttpClientやAndroidHttpClientで実装されています。
HttpUriRequestインターフェースはHttpGet/Post/Put/Deleteで実装されています。
ということで、一応ある程度使いまわせるはずです。
それと、HttpClientは使い終わったら
client.getConnectionManager().shutdown();
するのを忘れずに。
GETのパラメータの指定
GETなのでURLにパラメータを入れれば良いだけなのですが、URLを構成する際に面倒なのがエンコードです。Androidでは、ありがたいことにUri.Builderというものが利用できます。
ただし、Uri.Builderではスキーム・ドメイン・パス等をバラバラにセットしなければなりません。どうせなら、"http://www.google.com/"まではそのまま利用して、パラメータだけ、Builderに頑張ってもらいたいものです。
で、実はその方法があります*1。
Uri.Builder builder = Uri.parse("https://www.google.co.jp/search").buildUpon(); builder.appendQueryParameter("q", "なまはげ"); String url = builder.build().toString();
Uri.parse().buildUpon()がポイントです。
POSTのパラメータの指定
POSTは以下の様な感じで出来ます。若干面倒ですね。
HttpPost request = new HttpPost(url); List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("client_id", clientId_)); request.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
特にnew BasicNameValuePair
の辺りが非常に冗長な感じがするのですが、手軽な方法とかないんでしょうかね…。
*1:以下のコードは適当に書いているので、本当にちゃんと動作するかはわかりません。が、恐らく動くと思います