Android的HTTP客户端

原文地址:

http://android-developers.blogspot.com/2011/09/androids-http-clients.html

[本文由来自Dalvik团队的Jesse Wilson提交。--Tim Bray]

大多数需要网络连接的Android应用都会使用HTTP来传输数据。Android自带了两个HTTP客户端:HttpURLConnection和Apache HTTP Clinent。它们都支持HTTPS,文件上传下载,配置超时,

IPV6及连接池。

Apache HTTP Client

DefaultHttpClient及其相似的AndroidHttpClient都是HttpClient的扩展适用于Web浏览器。它们有丰富的可扩展的API,同时也很稳定没有什么Bug。

但是这里重量级的API让我们难以修改后保证它的兼容性,因为Android团队在Apache HTTP Client中并没有什么开发者。


HttpURLConnection

HttpURLConnection是一个通用的,轻量级的适用于绝大多数应用的HTTP客户端。这个类比较底层,但我们可以很容易的稳步修改它的关键的API。

在Froyo(2.2)之前,HttpURLConnection有几个烦人的Bug,特别是,在一个可读的InputStream中调用close()会

污染连接池,一个解决方案就是在低android版本中禁用连接池。


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(2.3)中,我们添加了隐式的压缩响应。HttpURLConnection将自动将以下的请求头部添加到连接请求中,然后处理相应的请求:


Accept-Encoding:gzip


为了充分利用这一点,你需要配置你的服务器为支持这一请求头的客户端开启压缩响应。如果压缩响应有问题,

你可以参考HttpURLConnection来禁用它。

因为HTTP客户端的Content-Length头部返回的是压缩后的大小,所以使用getContentLength()来获得解压后的数据块的大小是错误的。你应该从响应中读取字节直到InputStream.read()返回-1。

同时我们对在Gingerbread中的HTTPS连接做了一些优化,当HttpsURLConnection尝试连接SNI(Server Name Indication)将允许多个hosts共享一个IP地址。同样支持压缩和Session tickets。如果连接失败,将自动重试(it is automatically retried without these features)。这使得HttpURLConnection在连接新的服务器时更有效,同时不破坏向下兼容。

在Ice Cream Sandwich(4.X)中,我们添加了响应缓存。有了缓存,HTTP请求就会满足下面三种方式:

(1)完全缓存的响应将直接从本地存在中获得。因为无需进行网络连接 ,这样的响应可以马上获得。

(2)条件缓存的响应必须到服务器验证是否过期,客户端发送一个请求如"给我 /foo.png 如果从昨天后发生了改变的话",然后服务器响应返回更新的内容 或者一个304 Not Modified状态。如果内容没有更新,则将不会下载 。

(3)非缓存的响应将从web端获得,这些请求会存储在响应缓存中以务后用。


可以利用反射来在支持的设备中开启HTTP 响应缓存 。下面的代码将在4.0之后的版本的开启响应缓存 。而不会影响之前的版本。


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响应中设置缓存头部。


哪一个客户端最好?

在Eclair(2.1)和Froyo(2.2)中,Apache HTTP Client(相比HttpURLConnection)没有什么Bug,

对于这些发行版,它是最好的选择。

对于 Gingerbread(2.3)及之后的版本。HttpURLConnection是最好的选择。它的简单轻量最适合android。

压缩,缓存响应以减少网络连接,提升速度,省电,新的应用应该使用HttpURLConnection,它也是我们将着力点。

PS:决定为HttpURLConnection写一点封装,所以看了下官方博客,见没有翻译,觉得还不错,就翻译了下。

考虑到有些同学不能访问原文,原文如下:


Android’s HTTP Clients

[This post is byJesse Wilsonfrom the Dalvik team. —Tim Bray]


Most network-connected Android apps will use HTTP to send and receive data. Android includes two HTTP clients: HttpURLConnection and Apache HTTP Client. Both support HTTPS,streaminguploads and downloads, configurable timeouts, IPv6 and connection pooling.

Apache HTTP Client

DefaultHttpClientand its siblingAndroidHttpClientare extensible HTTP clients suitable for web browsers. They have large and flexible APIs. Their implementation is stable and they have few bugs.

But the large size of this API makes it difficult for us to improve it without breaking compatibility. The Android team is not actively working on Apache HTTP Client.

HttpURLConnection

HttpURLConnectionis a general-purpose, lightweight HTTP client suitable for most applications. This class hashumblebeginnings, but itsfocusedAPI has made it easy for us to improvesteadily.

Priorto Froyo, HttpURLConnection had somefrustratingbugs. In particular, callingclose()on a readable InputStream couldpoisonthe connection pool. Work around this by disabling 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");   } }

In Gingerbread, we addedtransparentresponse compression. HttpURLConnection will automatically add this header tooutgoingrequests, and handle the corresponding response:

Accept-Encoding: gzip

Take advantage of this by configuring your Web server to compress responses for clients that can support it. If response compression is problematic, theclass documentationshows how to disable it.

Since HTTP’sContent-Lengthheader returns the compressed size, it is an error to usegetContentLength()to size buffers for the uncompressed data. Instead, read bytes from the response untilInputStream.read()returns -1.

We also made several improvements to HTTPS in Gingerbread.HttpsURLConnectionattempts to connect withServer Name Indication(SNI) which allows multiple HTTPS hosts to share an IP address. It also enables compression and sessiontickets. Should the connection fail, it is automatically retried without these features. This makes HttpsURLConnection efficient when connecting to up-to-date servers, without breaking compatibility with older ones.

In Ice Cream Sandwich, we are adding a response cache. With the cache installed, HTTP requests will be satisfied in one of three ways:

  • Fully cached responses are served directly from local storage. Because no network connection needs to be made such responses are available immediately.

  • Conditionally cached responses must have their freshness validated by the webserver. The client sends a request like “Give me /foo.png if it changed since yesterday” and the server replies with either the updated content or a304NotModifiedstatus. If the content is unchanged it will not be downloaded!

  • Uncached responses are served from the web. These responses will get stored in the response cache for later.

Use reflection to enable HTTP response caching on devices that support it. This sample code will turn on the response cache on Ice Cream Sandwich without affecting earlier releases:

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) {   } }

You should also configure your Web server to set cache headers on its HTTP responses.

Which client is best?

Apache HTTP client has fewer bugs on Eclair and Froyo. It is the best choice for these releases.

For Gingerbread and better, HttpURLConnection is the best choice. Its simple API and small size makes it great fit for Android.Transparentcompression and response caching reduce network use, improve speed and save battery. New applications should useHttpURLConnection; it is where we will be spending our energy going forward.



更多相关文章

  1. Ubuntu下连接Android设备
  2. Android与PC通过USB连接通信(一)
  3. Android(安卓)性能优化系列总篇 (五)
  4. Android(安卓)IPC机制(五)用Socket实现跨进程聊天程序
  5. Android菜单详解(二)——创建并响应选项菜单
  6. android menu详解
  7. android网络编程——使用Android中的网络连接
  8. android与蓝牙通讯记录
  9. Andriod AOA协议通信总结

随机推荐

  1. Android环境搭建自己的总结~~(Windows下的
  2. Android中尺寸单位杂谈
  3. android开发每日汇总【2011-10-09】
  4. Android(安卓)AndroidManifest.xml 结构
  5. android 软件安装-更新-卸载
  6. Android(安卓)Surface 使用总结
  7. android手势操作&&实现滑动切换activity
  8. React-Native-StatusBar
  9. android 对pdf文件的下载、缓存、显示,包
  10. Android高手秘笈之自定义View的属性