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:以下のコードは適当に書いているので、本当にちゃんと動作するかはわかりません。が、恐らく動くと思います