Android网络编程之HttpUrlConnection
2016-10-21 11:07
381 查看
相关知识点延伸:
JAVASE中HttpUrlConnection介绍和使用
Android Thread Pool(线程池)
上一篇介绍JavaSe中HttpUrlConnection使用情况,在Android中使用HttpUrlConnection还是存在一些差别的。
Android中HttpUrlConnection的使用:
1. 使用说明:
Secure Communication with HTTPS(使用HTTPS进行安全通信):
Response Handling(相应处理):
Posting Content(传递内容):
Performance(性能):
内存性能:
这类返回的输出流和输入流不进行缓冲。大多数开发者应该使用BufferedOutputStream或者BufferedInputStream进行缓存。使用批量读取或者写入操作的使用者可以忽略缓冲。
传输大量数据到服务器或者从服务器中读取大量数据时,使用流的操作,同时应该进行限制内存中数据量的操作。
除非你需要一次性将内容存储到内存中,将它作为流处理,而不是将整个内容作为单独一个btye数据或者单独一个String进行存储。
处理时间:
为了减少延迟,这类进行多个请求/响应对的操作时,会重用相同的地城socket.因此,Http连接开着时间可能比所需时间,调用disconnect()可以将返回一个socket添加到连接的socket池中。
这种行为是可以被禁止的。通过设置http.keepAlive属性为false,在发送http请求前。
http.maxConnections属性可以用于控制与每个服务器保持多少个空闲连接。
默认情况:
默认情况下,HttpURLConnection 的实现请求,服务器将数据使用Gzip压缩后再返回,HttpUrlConnection会自动解压数据通过回调getInputStream().
在这种情况下,Content-Encoding 和Content-Length response headers 是清除的。
Gzip压缩可以被禁止。通过设置请求的header上接受的编码格式: urlConnection.setRequestProperty(“Accept-Encoding”, “identity”);
设置请求的标头上的Accept-Encoding属性禁止自动解压,且保留响应的标头。使用者必须根据响应的标头上的Content-Encoding来处理所需要的解压。
注意点:
getContentLength():返回传输的字节数,但是不能用于预测可以读出多少字节数。
getInputStream(): 获取压缩流。相反,读取这流直到耗尽,即read()返回-1.
Handling Network Sign-On:
某些wifi网络操作会阻止互联网访问,直到用户点击登录页面。
这种登录页面通常呈现是通过使用htttp重定向。可以使用getURL来测试连接是否意外重定向。
在连接操作的响应标头被接受后,这种测试才是有效的。可以调用getHeaderFields() or getInputStream()来触发响应的标头。这里的案例:检查响应是否意外重定向到其他主机:
HTTP Authentication(http验证):
HttpURLConnection支持 HTTP basic authentication。 使用 Authenticator 来设置 the VM-wide authentication handler:
除非与https配对,这种机制不是用户身份验证的安全机制。特别是,用户名,密码和请求和响应都是没有在加密情况下通过网络传输的。
Sessions with Cookies:
为了在客户端与服务器间建立和维护一个潜在的长期session,HttpURLConnection 包含一个可以扩展的coockie管理器。
使用CookieHandler 和CookieManager来开启VM范围中coockie 管理:
默认情况下,CookieManager只接受起始服务的coockie.还包括其他两个策略:ACCEPT_ALL and ACCEPT_NONE
实现CookiePolicy以定义自定义策略。
默认的CookieManager 会将接受到coockie保存到内存中,当VM退出时,会消除这些coockie. 实现CookieStore以定义自定义Cookie存储
除了由Http响应设置的Cookie之外,还可以通过编码方式来设置Cookie.要包含在Http 请求的标头中,Cookies必须要设置域和路径的属性
默认情况下,HttpCookie的新实例与只支持RFC 2965 cookies的服务器工作。许多web服务器仅支持旧的RFC 2109。
为了与大多数web服务器兼容,需将cookie版本设置为0。
一个案例:用法语来接收www.twitter.com
HTTP Methods:
HttpURLConnection 默认的请求方式是get. 若是使用post请求,则应该调用setDoOutput(true) 。
改变请求方式(OPTIONS, HEAD, PUT, DELETE and TRACE),调用setRequestMethod(String)来设置.
Proxies(代理):
默认情况下,这类是直接连接起始服务器。它也能通过http或者socks代理连接。
要使用代理,在创建连接的时候调用URL.openConnection(Proxy)。
IPv6 Support:
这类包含IPv6的支持。对于具备IPv4和IPv6地址的主机,它将会尝试连接到每一个主机的地址,知道建立连接。
Avoiding Bugs In Earlier Releases:
在android 2.2之前,这里存在一些错误。特别是,在一个可读的InputSteam中调用clos()会危害连接池,应该禁止使用连接池来解决问题。
每一个HttpURLConnection 实例可以用于一个请求/响应对。这个类的实例不是线程安全的。
android 官方关于HttpUrlConnection的链接:
https://developer.android.com/reference/java/net/HttpURLConnection.html
2. 其API和使用方式:请阅读JAVASE中HttpUrlConnection介绍和使用
3. 异步线程中使用案例:
在IntentService中长期执行网络任务,周期性读取服务器数据的案例。
案例思路: 周期性从服务器获取到信息,然后Gson解析Json数据,手机震动,Notification提醒,最后编辑信息标记为已读。
4. Android模拟器连接本地电脑服务器的注意点:
在电脑模拟器上访问本地电脑服务器时,报错java.net.ConnectException: localhost/127.0.0.1:8080 - Connection refused
解决方式:
StackOverFlow上的解决方式:
http://stackoverflow.com/questions/5495534/java-net-connectexception-localhost-127-0-0-18080-connection-refused
JAVASE中HttpUrlConnection介绍和使用
Android Thread Pool(线程池)
上一篇介绍JavaSe中HttpUrlConnection使用情况,在Android中使用HttpUrlConnection还是存在一些差别的。
Android中HttpUrlConnection的使用:
1. 使用说明:
Secure Communication with HTTPS(使用HTTPS进行安全通信):
使用一个https方案的URL调用penConnection(),将会返回一个HttpsURLConnection,这允许覆盖默认的HostnameVerifier 和 SSLSocketFactory。 一个运用提供的SSLSocketFactory创建是通过一个SSLContext, SSLSocketFactory 能够提供自定义的用于验证证书链的X509TrustManager 和自定义的用于提供客户端证书的X509TrustManager 。
Response Handling(相应处理):
HttpURLConnection 最多可以跟踪5个Http重定向。它将会跟随重定向,从一个起始服务器到其他服务器。 这种重定向的跟随实现,不会支持从Https服务器跳转到http的服务器重定向。反过来,也是一样的。
Posting Content(传递内容):
1. 上传数据到web服务器 ,输出的链接需配置setDoOutput(true)。 2. 为了最佳性能。 2. 1 若是知道这内容长度,可以调用setFixedLengthStreamingMode(int) 。 反之,调用setChunkedStreamingMode(int)。 2. 2 若是没有进行上一步设置操作,HttpURLConnection将会在内存中强制缓存整个请求的body,直到被传输完。 这种后果是导致浪费(可能消耗完)堆,增加迟缓时间。
Performance(性能):
内存性能:
这类返回的输出流和输入流不进行缓冲。大多数开发者应该使用BufferedOutputStream或者BufferedInputStream进行缓存。使用批量读取或者写入操作的使用者可以忽略缓冲。
传输大量数据到服务器或者从服务器中读取大量数据时,使用流的操作,同时应该进行限制内存中数据量的操作。
除非你需要一次性将内容存储到内存中,将它作为流处理,而不是将整个内容作为单独一个btye数据或者单独一个String进行存储。
处理时间:
为了减少延迟,这类进行多个请求/响应对的操作时,会重用相同的地城socket.因此,Http连接开着时间可能比所需时间,调用disconnect()可以将返回一个socket添加到连接的socket池中。
这种行为是可以被禁止的。通过设置http.keepAlive属性为false,在发送http请求前。
http.maxConnections属性可以用于控制与每个服务器保持多少个空闲连接。
默认情况:
默认情况下,HttpURLConnection 的实现请求,服务器将数据使用Gzip压缩后再返回,HttpUrlConnection会自动解压数据通过回调getInputStream().
在这种情况下,Content-Encoding 和Content-Length response headers 是清除的。
Gzip压缩可以被禁止。通过设置请求的header上接受的编码格式: urlConnection.setRequestProperty(“Accept-Encoding”, “identity”);
设置请求的标头上的Accept-Encoding属性禁止自动解压,且保留响应的标头。使用者必须根据响应的标头上的Content-Encoding来处理所需要的解压。
注意点:
getContentLength():返回传输的字节数,但是不能用于预测可以读出多少字节数。
getInputStream(): 获取压缩流。相反,读取这流直到耗尽,即read()返回-1.
Handling Network Sign-On:
某些wifi网络操作会阻止互联网访问,直到用户点击登录页面。
这种登录页面通常呈现是通过使用htttp重定向。可以使用getURL来测试连接是否意外重定向。
在连接操作的响应标头被接受后,这种测试才是有效的。可以调用getHeaderFields() or getInputStream()来触发响应的标头。这里的案例:检查响应是否意外重定向到其他主机:
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(http验证):
HttpURLConnection支持 HTTP basic authentication。 使用 Authenticator 来设置 the VM-wide authentication handler:
Authenticator.setDefault(new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password.toCharArray()); } });
除非与https配对,这种机制不是用户身份验证的安全机制。特别是,用户名,密码和请求和响应都是没有在加密情况下通过网络传输的。
Sessions with Cookies:
为了在客户端与服务器间建立和维护一个潜在的长期session,HttpURLConnection 包含一个可以扩展的coockie管理器。
使用CookieHandler 和CookieManager来开启VM范围中coockie 管理:
CookieManager cookieManager = new CookieManager(); CookieHandler.setDefault(cookieManager);
默认情况下,CookieManager只接受起始服务的coockie.还包括其他两个策略:ACCEPT_ALL and ACCEPT_NONE
实现CookiePolicy以定义自定义策略。
默认的CookieManager 会将接受到coockie保存到内存中,当VM退出时,会消除这些coockie. 实现CookieStore以定义自定义Cookie存储
除了由Http响应设置的Cookie之外,还可以通过编码方式来设置Cookie.要包含在Http 请求的标头中,Cookies必须要设置域和路径的属性
默认情况下,HttpCookie的新实例与只支持RFC 2965 cookies的服务器工作。许多web服务器仅支持旧的RFC 2109。
为了与大多数web服务器兼容,需将cookie版本设置为0。
一个案例:用法语来接收www.twitter.com
HttpCookie cookie = new HttpCookie("lang", "fr"); cookie.setDomain("twitter.com"); cookie.setPath("/"); cookie.setVersion(0); cookieManager.getCookieStore().add(new URI("http://twitter.com/"), cookie);
HTTP Methods:
HttpURLConnection 默认的请求方式是get. 若是使用post请求,则应该调用setDoOutput(true) 。
改变请求方式(OPTIONS, HEAD, PUT, DELETE and TRACE),调用setRequestMethod(String)来设置.
Proxies(代理):
默认情况下,这类是直接连接起始服务器。它也能通过http或者socks代理连接。
要使用代理,在创建连接的时候调用URL.openConnection(Proxy)。
IPv6 Support:
这类包含IPv6的支持。对于具备IPv4和IPv6地址的主机,它将会尝试连接到每一个主机的地址,知道建立连接。
Avoiding Bugs In Earlier Releases:
在android 2.2之前,这里存在一些错误。特别是,在一个可读的InputSteam中调用clos()会危害连接池,应该禁止使用连接池来解决问题。
private void disableConnectionReuseIfNecessary() { // Work around pre-Froyo bugs in HTTP connection reuse. if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { System.setProperty("http.keepAlive", "false"); } }
每一个HttpURLConnection 实例可以用于一个请求/响应对。这个类的实例不是线程安全的。
android 官方关于HttpUrlConnection的链接:
https://developer.android.com/reference/java/net/HttpURLConnection.html
2. 其API和使用方式:请阅读JAVASE中HttpUrlConnection介绍和使用
3. 异步线程中使用案例:
在IntentService中长期执行网络任务,周期性读取服务器数据的案例。
案例思路: 周期性从服务器获取到信息,然后Gson解析Json数据,手机震动,Notification提醒,最后编辑信息标记为已读。
public class MessageIntentSerce extends IntentService { public static final String TAG = MessageIntentSerce.class.getSimpleName(); private String token; private String url1, url2; public boolean isStop = false; public NotificationManager notificationManager; public Vibrator vibrator; public static final int MESSAGENOTIFICATION_ID = 100; public static Intent openMessageServce(Context context, Bundle bundle) { Intent intent = new Intent(context, MessageIntentSerce.class); intent.putExtras(bundle); return intent; } private ThreadManager threadManager; public MessageIntentSerce() { super(TAG); url1 = Constants.COOMPANYTEST + Constants.UPDATAMESSAG; url2 = Constants.COOMPANYTEST + Constants.MESSAGEFINISH; threadManager = ThreadManager.getInstances(); } @Override public void onCreate() { super.onCreate(); LogController.i(TAG,"service onCreate"); //初始化相关配置 notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE); } /** * 后台线程,以工作队列线程进行 * * @param intent */ @Override protected void onHandleIntent(Intent intent) { LogController.i(TAG,"service onHandleIntent"); Bundle bundle = intent.getExtras(); token = bundle.getString(MessageIntentSerce.TAG); if (token == null) { return; } //停止的标志 while (threadManager.getStart()) { try { getMessageFromServce(); Thread.sleep(20 * 1000); } catch (Exception e) { e.printStackTrace(); } } } @Override//释放资源 public void onDestroy() { LogController.i(TAG,"service destroy"); notificationManager.cancelAll(); vibrator.cancel(); super.onDestroy(); } public void getMessageFromServce() { try { HttpURLConnection urlConnection = createConnection(url1); String result = getStreamContent(urlConnection); LogController.i(TAG, "messagelist" + result); if (result == null) { return; } JsonBean_UpdataMessage message = parseJson(result, JsonBean_UpdataMessage.class); if (message != null && message.errcode == 0) { if (message.replydata != null && message.replydata.messagelist != null && message.replydata.messagelist.size() > 0) { for (JsonBean_UpdataMessage.MessageList.Message msg : message.replydata.messagelist) { notifi(msg.msubject, msg.mcontent); updataMSG(msg.mpid); } vibrator.vibrate(1000); } } } catch (Exception e) { e.printStackTrace(); } } /** * 创建httpUrlConnection对象,指定request的属性 * * @param url * @return */ public HttpURLConnection createConnection(String url) { HttpURLConnection urlConnection = null; try { urlConnection = (HttpURLConnection) new URL(url).openConnection(); urlConnection.setConnectTimeout(10 * 1000); urlConnection.setReadTimeout(10 * 1000); //数据编码格式,这里utf-8 urlConnection.setRequestProperty("Charset", "utf-8"); //添加cookie,cookie规则需开发者自定 urlConnection.setRequestProperty("Cookie", Constants.COOCKIE_KEY + token); //设置返回结果的类型,这里是json urlConnection.setRequestProperty("accept", "application/json"); //这里设置post传递的内容类型,这里json urlConnection.setRequestProperty("Content-Type", "application/json"); //设置这个,避免android低版本报错误 if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { System.setProperty("http.keepAlive", "false"); } } catch (Exception e) { e.printStackTrace(); } return urlConnection; } /** * 添加http参数 * * @param urlConnection * @param jsonObject */ public void addParameter(HttpURLConnection urlConnection, JSONObject jsonObject) { try { //设置post请求方式 urlConnection.setRequestMethod("POST"); //允许往流中写入数据 urlConnection.setDoOutput(true); //借助BufferedOutputStream提高速度 OutputStream outputStream = new BufferedOutputStream(urlConnection.getOutputStream()); byte[] body = jsonObject.toString().getBytes("utf-8"); outputStream.write(body, 0, body.length); //刷新数据到流中 outputStream.flush(); //关闭流 outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取HttpUrlConnection的返回内容 * * @param urlConnection * @return */ public String getStreamContent(HttpURLConnection urlConnection) { ByteArrayOutputStream byteArrayOutputStream = null; BufferedInputStream bufferedInputStream = null; String result = null; try { //开启客户端与Url所指向的资源的网络连接 urlConnection.connect(); if (200 == urlConnection.getResponseCode()) {//HTTP_OK 即200,连接成功的状态码 if (urlConnection.getContentLength() > 0) { bufferedInputStream = new BufferedInputStream(urlConnection.getInputStream()); byteArrayOutputStream = new ByteArrayOutputStream(); //httpUrlConnection返回传输字节的长度,创建一个byte 数组。 byte[] b = new byte[urlConnection.getContentLength()]; int length; while ((length = bufferedInputStream.read(b)) > 0) { byteArrayOutputStream.write(b, 0, length); } result = byteArrayOutputStream.toString("utf-8"); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (byteArrayOutputStream != null) { byteArrayOutputStream.close(); } if(bufferedInputStream!=null){ bufferedInputStream.close(); } if (urlConnection != null) { //解除连接,释放网络资源 urlConnection.disconnect(); } } catch (Exception e) { e.printStackTrace(); } } return result; } /** * 解析json数据,这里Gson解析 * * @param json * @param cls * @param <T> * @return */ public <T> T parseJson(String json, Class<T> cls) {//解析基本的json(json) T t = null; try { Gson gson = new Gson(); t = gson.fromJson(json, cls); return t; } catch (Exception e) { e.printStackTrace(); return null; } } public int i = 1; //弹出Notification public void notifi(String title, String content) { notificationManager.notify(MESSAGENOTIFICATION_ID + (i++), NotificationBuidler.createMessageNotifaction(MessageIntentSerce.this, title, content)); } public void updataMSG(int mid) { JSONObject jsonObject = null; try { jsonObject = new JSONObject(); jsonObject.put("mpid", mid); HttpURLConnection httpURLConnection = createConnection(url2); addParameter(httpURLConnection, jsonObject); String result = getStreamContent(httpURLConnection); LogController.i(TAG, "msgfinish" + result); } catch (Exception e) { e.printStackTrace(); } } }
4. Android模拟器连接本地电脑服务器的注意点:
在电脑模拟器上访问本地电脑服务器时,报错java.net.ConnectException: localhost/127.0.0.1:8080 - Connection refused
解决方式:
android模拟器是在虚拟内部运行,这里127.0.0.1或者localhost是模拟器自己的环回路径。 因此,应该使用http://10.0.2.2:8080/来访问。
StackOverFlow上的解决方式:
http://stackoverflow.com/questions/5495534/java-net-connectexception-localhost-127-0-0-18080-connection-refused
相关文章推荐
- android网络编程之HttpUrlConnection的讲解--GET请求
- Android网络编程 HttpUrlConnection HttpClient AsyncTask
- Android 网络编程之HttpURLConnection
- Android网络编程原理及HttpURLConnection 用法
- android网络编程之HttpUrlConnection的讲解--POST请求
- Android 网络编程之---HttpClient 与 HttpURLConnection 共用cookie
- Android通过HttpURLConnection和HttpClient接口实现网络编程
- HttpURLConnection----Android网络编程
- Android之使用HttpURLConnection进行网络编程
- Android网络编程之URLConnection&HttpURLConnection
- Android网络编程---HttpURLConnection
- android HttpURLConnection编程详解,获取网络图片,html代码查
- android网络编程之HttpUrlConnection的讲解--DownLoadManager基本用法
- Android 的网络编程(3)-HttpURLConnection接口
- Android通过HttpURLConnection和HttpClient接口实现网络编程
- android网络编程之HttpUrlConnection的讲解--POST请求
- Android 网络编程之HttpURLConnection运用
- Android网络编程之URLConnection和HttpClient访问服务器
- Android 网络编程之HttpURLConnection(conn.getResponseCode() != 200,从url读取写入数据)
- android网络编程--HttpURLConnection(结合Handler和子线程)