Android总结 - 网络请求总结
Posted Shen_JC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android总结 - 网络请求总结相关的知识,希望对你有一定的参考价值。
HttpURLConnection
建立连接
android在6.0之后只支持HttpURLConnection来做Http的请求。从crash时候的log里面看出HttpURLConnection底层已经开始使用OkHttp了。总结一下常用的使用方法。
使用流程如下:
1. 打开连接。通过URL.openConnection()来获取一个HttpURLConnection
2. 准备请求。一个请求的最主要的部分是URI。请求头部可以包含好多metadata比如:证书、优先内容类型和session cookies。
3. 可选的上传请求body。 如果包含一个请求body 实例,必须调用setDoOutput(true)来配置。 通过getOutputStream()获取输出流来发送数据。
4. 读取response响应 Response头部典型的包含metadata比如响应实体的content type和length,modified dates 和session cookies 。响应内容可以通过getInputStream()获取输入流来读取。如果response没有body,getInputStream()会返回一个空的流。
5. 关闭连接。response body被读完之后就应该disconnect()关闭HttpURLConnection。关闭连接可以释放相关的资源以便于他们可以被关闭或重新使用。
普通的get请求列子:
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in); // 自己实现读取数据并处理
finally
urlConnection.disconnect();
使用HTTPS做安全通信
Calling openConnection() on a URL with the “https” scheme will return an HttpsURLConnection, which allows for overriding the default HostnameVerifier and SSLSocketFactory. An application-supplied SSLSocketFactory created from an SSLContext can provide a custom X509TrustManager for verifying certificate chains and a custom X509KeyManager for supplying client certificates. See HttpsURLConnection for more details.
响应操作
HttpURLConnection 会跟踪5次HTTP重定向,它会跟踪从原始服务器到另一个。但是不支持重定向从HTTPS to HTTP or vice versa。
如果HTTP response指示有一个错误出现, getInputStream()会抛出 IOException异常。使用getErrorStream()来读取错误的response。响应头部headers还是可以通过正常的方法getHeaderFields()来读取。
发送内容
如果要上传数据到服务器,需要使用setDoOutput(true)来配置连接。
为了有最好的性能,当request body的长度提前已知的情况下,需要调用setFixedLengthStreamingMode(int);当request body的长度未知的情况下,要么就调用setChunkedStreamingMode(int)。否则HttpURLConnection会强制在内存中缓存整个request body在被传递之前,这样会浪费堆栈和增加延迟。
Post例子:
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0); // 参数0代表使用默认的chunk长度。
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
writeStream(out);
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally
urlConnection.disconnect();
执行效率
HttpURLConnection返回的输入和输出流是没有缓存的。使用者必须使用 BufferedInputStream or BufferedOutputStream来包装原始的流。只有当批量读写的时候才可以忽略使用缓存。
当传递大量数据到服务器或者从服务器获取大量数据的时候,使用streams来限制内存一次性可以加载多少数据。除非你是需要把entire body 一次性的加载到内存中,要不然就把它作为流来处理(而不是保存整个body为字节数组或者字符串)
为了降低延迟,HttpURLConnection会为多个请求/响应对而复用同一个底层Socket。因此,HTTP链接打开的时间会比必要的时间更长一点。调用 disconnect()可以把socket返回到已连接的sockets线程池中。在发送任何HTTP请求之前,通过设置“http.keepAlive”property为false,可以禁止这种行为。“http.maxConnections property ”可以用来控制每个服务器的最大空闲连接数。
默认情况下,HttpURLConnection 实现请求服务器使用gzip压缩发送并且会自动解压缩从getInputStream()获取的数据。这种情况下 Content-Encoding 和 Content-Length 的reponse headers会被清空(此时,getContentLength() 会返回 -1,如果想要使用getContentLength() 需要禁用gzip压缩)。Gzip压缩可以通过设置请求头部里面的“acceptable encodings”属性来禁止:
urlConnection.setRequestProperty("Accept-Encoding", "identity");
设置请求头部“Accept-Encoding”属性可以明确的禁用自动解压并保持response headers的完整性;如果需要的话,调用者可以根据response header中的“Content-Encoding”来进行解压。
getContentLength() 会返回被传输内容的字节数量,但是不能用来预测会有多少字节会从getInputStream()中读出来。反而,应用通过读取stream直到耗尽,比如read() 返回-1。
控制网络登录
有些Wifi网络需要通过一个登陆界面登陆之后才能访问网络。这种类似的登陆界面通常都是使用了HTTP的重定向。可以通过使用getURL() 来测试我们的connection 是否被意外的重定向了。在response headers被接收到之前这种检查不可用,而response headers可以通过调用 getHeaderFields()或者getInputStream()来触发得到。
例子,检测response是否被意外重定向到别的host:
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
if (!url.getHost().equals(urlConnection.getURL().getHost()))
// we were redirected! Kick the user out to the browser to sign on?
...
finally
urlConnection.disconnect();
HTTP Authentication
Sessions with Cookies
为了在客户端和服务端建立和维持一个潜在的长session,HttpURLConnection包含一个可扩展的cookie管理器。使用 CookieHandler and CookieManager来启动VM-wide cookie management:
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
默认的,CookieManager只接受原始服务器过来的cookies,除此之外还有两种其他的两种策略:ACCEPT_ALL 和ACCEPT_NONE,通过实现CookiePolicy 去定义一个自定义的policy。
这个默认的CookieManager 在内存中保留着所有可接受的cookies。这个cookies会被遗忘当VM退出的时候。可以通过继承CookieStore来自定义cookie store。
除了被HTTP responses设置过的cookies,其他的cookies需要自己手动设置。为了包含在HTTP的请求头部中,cookies必须设置domain 和 path 属性。
默认的,HttpCookie 实例只能与支持“RFC 2965 ”cookies的服务器一起工作。好多服务器只支持就的规则“RFC 2109”。为了与大部分服务器兼容,设置cookie version为0。
举例, 接收“ www.twitter.com” in French:
HttpCookie cookie = new HttpCookie("lang", "fr");
cookie.setDomain("twitter.com");
cookie.setPath("/");
cookie.setVersion(0);
cookieManager.getCookieStore().add(newURI("http://twitter.com/"), cookie);
HTTP Methods
HttpURLConnection默认使用GET方法,通过调用“setDoOutput(true)” 来使用POST方法。其他的HTTP方法(OPTIONS, HEAD, PUT, DELETE and TRACE)可以用调用”setRequestMethod(String)“来使用。
Proxies
HttpURLConnection默认是直接连接。当然也可以通过HTTP或者SOCKS代理来建立连接。通过调用URL.openConnection(Proxy) 来建立代理连接。
以上是关于Android总结 - 网络请求总结的主要内容,如果未能解决你的问题,请参考以下文章