android 网络编程
来源:互联网 发布:lte mrr弱覆盖优化 编辑:程序博客网 时间:2024/04/30 14:05
安卓和Java应用开发少不了要提交HTTP请求,而基本上目前有两个实现方式:HttpUrlConnection(即URL.openConnection)和HttpClient。 HttpClient是apache的开源实现,而HttpUrlConnection是安卓标准实现。
1. HttpURLConnection
Android 2.2版本之前,HttpURLConnection一直存在着一些令人厌烦的bug。比如说对一个可读的InputStream调用close()方法时,就有可能会导致连接池失效了。那么我们通常的解决办法就是直接禁用掉连接池的功能。所以在Android 2.2版本以及之前的版本使用HttpClient是较好的选择,而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择,它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。另外在Android 6.0版本中,HttpClient库被移除了。
1.1 Get
首先需要获取到 HttpURLConnection 的实例,一般只需 new 出一个 URL 对象,并传入 目标的网络地址,然后调用一下 openConnection()方法即可。得到了 HttpURLConnection 的实例之后,我们可以设置一下 HTTP 请求所使用的方法。 常用的方法主要有两个,GET 和 POST。GET 表示希望从服务器那里获取数据,而 POST 则 表示希望提交数据给服务器。接下来就可以进行一些自由的定制了,比如设置连接超时、读取超时的毫秒数,以及服 务器希望得到的一些消息头等。这部分内容根据自己的实际情况进行编写。之后再调用 getInputStream()方法就可以获取到服务器返回的输入流了,剩下的任务就是 对输入流进行读取。接着利用 BufferedReader 对服务器 返回的流进行读取,并将结果存放到了一个 Message 对象中。这里为什么要使用 Message 对 象呢?当然是因为子线程中无法对 UI 进行操作了。我们希望可以将服务器返回的内容显示 到界面上,所以就创建了一个 Message 对象,并使用 Handler 将它发送出去。之后又在 Handler 的 handleMessage()方法中对这条 Message 进行处理。最后可以调用 disconnect()方法将这个 HTTP 连接关闭掉。
private void connectWithHttpURLConnection() { new Thread( new Runnable() { @Override public void run() { HttpURLConnection connection = null; try { // 调用URL对象的openConnection方法获取HttpURLConnection的实例 URL url = new URL("http://www.cnblogs.com/gzdaijie"); connection = (HttpURLConnection) url.openConnection(); // 设置请求方式,GET或POST connection.setRequestMethod("GET"); // 设置连接超时、读取超时的时间,单位为毫秒(ms) connection.setConnectTimeout(8000); connection.setReadTimeout(8000); // getInputStream方法获取服务器返回的输入流 InputStream in = connection.getInputStream(); // 使用BufferedReader对象读取返回的数据流 // 按行读取,存储在StringBuider对象response中 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } Message message = new Message(); message.what = SHOW_RESPONSE; // 将服务器返回的结果存放到Message中 message.obj = response.toString(); handler.sendMessage(message); } catch (Exception e){ e.printStackTrace(); } finally { if (connection != null){ // 结束后,关闭连接 connection.disconnect(); } } } }).start();}
1.2 Post
注意需要对中文进行设置编码格式
URLEncoder.encode(nickname.getText().toString(), “utf-8”)
public void send() { String target = "http://192.168.1.66:8081/blog/dealPost.jsp"; //要提交的目标地址 URL url; try { url = new URL(target); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); // 创建一个HTTP连接 urlConn.setRequestMethod("POST"); // 指定使用POST请求方式 urlConn.setDoInput(true); // 向连接中写入数据 urlConn.setDoOutput(true); // 从连接中读取数据 urlConn.setUseCaches(false); // 禁止缓存 urlConn.setInstanceFollowRedirects(true); //自动执行HTTP重定向 DataOutputStream out = new DataOutputStream(urlConn.getOutputStream()); // 获取输出流 String param = "nickname=" + URLEncoder.encode(nickname.getText().toString(), "utf-8") + "&content=" + URLEncoder.encode(content.getText().toString(), "utf-8"); //连接要提交的数据 out.writeBytes(param);//将要传递的数据写入数据输出流 out.flush(); //输出缓存 out.close(); //关闭数据输出流 // 判断是否响应成功 if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) { InputStreamReader in = new InputStreamReader(urlConn.getInputStream()); // 获得读取的内容 BufferedReader buffer = new BufferedReader(in); // 获取输入流对象 String inputLine = null; while ((inputLine = buffer.readLine()) != null) { result += inputLine + "\n"; } in.close(); //关闭字符输入流 } urlConn.disconnect(); //断开连接 } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
2. HttpClient
HttpClient是Apache提供的库,提供了高效的、最新的支持HTTP协议的工具包,封装了众多的http请求、响应等方法,但有个缺点就是太重量级了,API太多了。
2.1 Get
首先你需要知道,HttpClient 是一个接口,因此无法创建它的实例,通常情况下都会创 建一个 DefaultHttpClient 的实例。接下来如果想要发起一条 GET 请求,就可以创建一个 HttpGet 对象,并传入目标的网络 地址,然后调用 HttpClient 的 execute()方法即可。执行 execute()方法之后会返回一个 HttpResponse 对象,服务器所返回的所有信息就会包 含在这里面。通常情况下我们都会先取出服务器返回的状态码,如果等于 200 就说明请求和响应都成功了。接下来在这个 if 判断的内部取出服务返回的具体内容,可以调用 getEntity()方法获取到 一个 HttpEntity 实例,然后再用 EntityUtils.toString()这个静态方法将 HttpEntity 转换成字符串 即可。注意如果服务器返回的数据是带有中文的,直接调用 EntityUtils.toString()方法进行转换 会有乱码的情况出现,这个时候只需要在转换的时候将字符集指定成 utf-8 就可以了。
// 创建DefaultHttpClient实例 HttpClient httpClient = new DefaultHttpClient(); //传入网址,然后执行 HttpGet httpGet = new HttpGet("http://www.cnblogs.com/gzdaijie"); HttpResponse httpResponse = httpClient.execute(httpGet); // 由状态码判断请求结果, // 常见状态码 200 请求成功,404 页面未找到,关于HTTP的更多状态码直接GOOGLE if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 请求成功,使用HttpEntity获得返回数据 // 使用EntityUtils将返回数据转换为字符串 HttpEntity entity = httpResponse.getEntity(); String response = EntityUtils.toString(entity); //如果是中文,指定编码 //==>String response = EntityUtils.toString(entity, "utf-8"); //或者生成一个BufferedReader BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())); }
2.2 Post
HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost("http://www.cnblogs.com/gzdaijie"); // 使用NameValuePair(键值对)存放参数 List<NameValuePair> data = new ArrayList<NameValuePair>(); // 添加键值对 data.add(new BasicNameValuePair("stu_no", 12345)); data.add(new BasicNameValuePair("stu_name", "Tom")); // 使用setEntity方法传入编码后的参数 httpPost.setEntity(new UrlEncodedFormEntity(data, "utf-8")); // 执行该POST请求 HttpResponse httpResponse = httpClient.execute(httpPost); // .....省略处理httpResponse的代码,与GET方式一致
3. 用回调函数实现网络编程
3.1 定义接口HttpCallbackListener,为了实现回调
在接口中定义了两个方法,onFinish()方法表示当服务器成功响应我们请 求的时候调用,onError()表示当进行网络操作出现错误的时候调用。这两个方法都带有参数, onFinish()方法中的参数代表着服务器返回的数据,而 onError()方法中的参数记录着错误的 详细信息。
// 定义HttpCallbackListener接口// 包含两个方法,成功和失败的回调函数定义public interface HttpCallbackListener { void onFinish(String response); void onError(Exception e);}
3.2 定义类HttpUtil,为了网络助手类
先给 sendHttpRequest()方法添加了一个 HttpCallbackListener 参数,并在方法的内 部开启了一个子线程,然后在子线程里去执行具体的网络操作。注意子线程中是无法通过 return 语句来返回数据的,因此这里我们将服务器响应的数据传入了 HttpCallbackListener 的 onFinish()方法中,如果出现了异常就将异常原因传入到 onError()方法中。
/* 创建一个新的类 HttpTool,将公共的操作抽象出来 * 为了避免调用sendHttpRequest方法时需实例化,设置为静态方法 * 传入HttpCallbackListener对象为了方法回调 * 因为网络请求比较耗时,一般在子线程中进行, * 为了获得服务器返回的数据,需要使用java的回调机制 */public class HttpTool { public static void sendHttpRequest(final String address, final HttpCallbackListener listener) { new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; try { URL url = new URL(address); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setReadTimeout(8000); InputStream in = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } if (listener != null) { // 回调方法 onFinish() listener.onFinish(response.toString()); } } catch (Exception e) { if (listener != null) { // 回调方法 onError() listener.onError(e); } } finally { if (connection != null) { connection.disconnect(); } } } }).start(); }}
3.3 调用网络助手类
这样的话,当服务器成功响应的时候我们就可以在 onFinish()方法里对响应数据进行处 理了,类似地,如果出现了异常,就可以在 onError()方法里对异常情况进行处理。如此一来, 我们就巧妙地利用回调机制将响应数据成功返回给调用方了。
另外需要注意的是,onFinish()方法和 onError()方法最终还是在子线程中运行的,因此 我们不可以在这里执行任何的 UI 操作,如果需要根据返回的结果来更新 UI,则仍然要使用异步消息处理机制(Handler)。
//使用该HttpTool发起GET请求String url = "http://www.cnblogs.com/gzdaijie";HttpTool.sendHttpRequest(url,new HttpCallbackListener(){ @Override public void onFinish(String response) { // ...省略对返回结果的处理代码 } @Override public void onError(Exception e) { // ...省略请求失败的处理代码 } });
- Android 的网络编程
- Android 的网络编程
- Android 的网络编程
- Android 的网络编程
- Android 说说网络编程
- Android 的网络编程
- Android网络编程
- 探讨 Android 网络编程
- Android网络编程
- Android 的网络编程
- Android 的网络编程
- Android网络编程
- android之网络编程
- Android网络编程
- Android网络编程
- Android 网络编程应用
- Android 网络编程初步
- android network网络编程
- Apache Ambari 02
- 互斥锁与条件变量
- 局部内部类
- 排序算法--冒泡排序
- Ubuntu 14.04 caffe的Python环境配置
- android 网络编程
- Stereo Matching文献笔记之(九):经典算法Semi-Global Matching(SGM)之神奇的HMI代价计算~
- 初学java整理
- 求两单链表交点
- POJ 2010 Moo University
- 反射基础(一)
- 上传项目到GitHub时遇到的问题
- Android studio 代码混淆使用 —— ProGuard
- VS2015 快捷键