2011年10月4日火曜日

Android Apache HTTP Client と HttpURLConnection どっちを使うべき?

Android Developer's Blog にちょっと面白い記事があったのでまとめてみた。

Android Developers Blog: Android’s HTTP Clients -

Android のフレームワークは HTTP 通信をするための HTTP client の実装が2つあります。

1つが HttpURLConnection (java.net パッケージ) で、もう1つのが Apache HTTP Client (org.apache.http パッケージ) です。

Apache HTTP Client

 DefaultHttpClient とそれのサブクラスの AndroidHttpClient は Web ブラウザに適応した拡張された HTTP Client です。そのため、大きくてフレキシブルな API を持っています。これらの実装は安定していますが、いくつかのバグも含まれています。

巨大な API は互換性を破らずに改善することがとても難しく、Android チームは Apache HTTP Client に対してアクティブに活動していません。


HttpURLConnection

 HttpURLConnection ほとんどのアプリケーションに適応する汎用的で軽量な HTTP Client です。API が絞られているので、徐々に改善していきやすいです。

Froyo 以前では、HttpURLConnection には幾つかのイライラするバグがありました。とくに、close() を読み込み可能な InputStream で呼ぶことで connection pool を汚染することがありました。connection pooling を無効にすることでこの問題を回避するには
private void disableConnectionReuseIfNecessary() { // HTTP connection reuse which was buggy pre-froyo if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { System.setProperty("http.keepAlive", "false"); } }
のようにします。

Gingerbread では、transparent response compression が追加されました。HttpURLConnection は自動的にリクエストにヘッダを追加し、対応するレスポンスを処理します。

Accept-Encoding: gzip

Web server が圧縮レスポンスを利用できるクライアントに対してそれを返すように設定することで、この利点を生かすことができます。もし圧縮レスポンスで問題がある場合は、クラスのドキュメントに無効にする方法がのっています。

HTTP の Content-Length ヘッダは圧縮されたサイズを返すので、非圧縮データ用のバッファサイズとして getContentLength() で取得した値を使うとエラーになります。InputStream.read() が -1 を返すまで読みようにしてください。

Gingerbread での HTTPS も幾つか改善されています。HttpsURLConnection は IP アドレスを共有する複数の HTTPS host を許可する Servier Name Indication (SNI) に接続を試みます。これは圧縮とセッションチケットを有効にします。コネクションが失敗した場合は、自動でこれらの機能を省いてリトライします。これは HttpsClientConnection が過去のサーバーと互換性を保ちながら最新のサーバーと接続するのに効果的です。

Ice Cream Sandwich では、レスポンスキャッシュが追加されます。インストールされたキャッシュに対して、次の3つのなかのいずれかの方法で HTTP リクエストが完了します。

  • 完全にキャッシュされたレスポンスがローカルストレージから直接提供される。ネットワーク接続がない場合、このようなレスポンスがすぐに返ってくることが必要であるため。
  • 条件付きでキャッシュされたレスポンスはウェブサーバーによって新しさが検証されます。クライアントは "もし機能から変更されていたら /foo.png をください” のようなリクエストを送り、サーバーはアップデートがあるかどうかに応じて 304 Not Modified status かコンテンツを返します。つまり、コンテンツが変わっていなければダウンロードされません!
  • キャッシュされていないレスポンスは Web から提供されます。これらのレスポンスは後でレスポンスキャッシュに保存されます。


HTTP レスポンスのキャッシュをサポートしている端末で有効にするにはリフレクションを使います。例えば、以前のリリースに影響を与えずに、Ice Create Sandwich の端末でキャッシュ機能を有効にするには次のようにします。

private void enableHttpResponseCache() { try { long httpCacheSize = 10 * 1024 * 1024; // 10 MiB File httpCacheDir = new File(getCacheDir(), "http"); Class.forName("android.net.http.HttpResponseCache") .getMethod("install", File.class, long.class) .invoke(null, httpCacheDir, httpCacheSize); } catch (Exception httpResponseCacheNotAvailable) { } }

もちろん、HTTP レスポンスにキャッシュヘッダをセットするよう Web server を設定する必要があります。

Which client is best? どっちのクライアントがいい?

Eclair と Froyo では Apache HTTP client のほうがバグがすくないので、こちらがベストです。

Gingerbread 以降では、HttpURLConnection がベストです。API がシンプルでサイズも小さいので Android に適しています。Transparent compression とレスポンスキャッシュはネットワークの利用を減らし、速度やバッテリーのもちを改善します。

---

# さらっと Ice Cream Sandwich のことが書かれてたね。

0 件のコメント:

コメントを投稿