这两天因为项目需要,和后台服务器打交道比较多,包括向服务器端发送数据,接收来自服务器端的数据,所以会用到一些网络操作相关的知识,接下来就简单总结下Http网络操作的相关知识,并记录在实际操作过程中遇到的一些错误,方便以后总结复习
Android中网络操作的方式主要是Scoket方式和Http方式,关于Scoket方式和http方式的比较,见服务器和客户端的交互方式(Socket,http协议)和各自特点和适用范围
通过Http协议实现网络操作有两种选择:
使用java的标准库URLConnection(java.net.URLConnection)中的HttpURLConnection:
使用apache 的开源框架httpClient(org.apache.http.client),HttpClient是基于URLConnection的一个封装,增加了很多方便使用的API。
下面是整理的结构图:
通过HttpURLConnection实现网络操作
使用GET方法的实例
1.新建一个Android项目, 在AndroidManifest.xml文件中添加网络操作相关权限:
1
2.在MainActivity.java中创建一个String类型常量myURL用于存放URL地址:
private final String myURL="http://www.ibookpa.com/mobileFilter?action=login";1
这里的URL地址,就根据自己的实际情况来写,我这里使用的是他们写好的一个地址,用于传输一个json格式数据,用浏览器打开这个链接的效果如下:
也就是说我通过这个URL链接,将获取到这一串json数据
3.新建一个线程类重写其run方法
这里需要注意的是,Android中所有的网络操作都不能直接在MainThread中进行,必须在其他线程中执行网络相关操作:
private class myThread extends Thread {
@Override
public void run() {
super.run();
}
}1
2
3
4
5
6
4.在run方法中新建URL类的对象
传入一个字符串类型参数,这里的参数可以是定义好的URL地址,也可以是构造出来的地址,灵活性很大,本例中是使用定义好的URL地址:myURL
private class myThread extends Thread {
@Override
public void run() {
super.run();
try {
URL url = new URL(myURL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
5.创建HttpURLConnection类的对象,用于获取通过URL得到的网络连接:
HttpURLConnection conn = (HttpURLConnection)url.openConnection();1
6.通过inputStream得到输入流
可以有很多方式,这里使用BufferedReader来获取输入流:
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));1
2
3
7.接下来就是获取输入流
通过循环读取BufferedReader中的内容,来赋值给一个String类型的变量,就能实现获取输入流中的String类型数据:
String result = "";
String res = null;
while ((res = br.readLine()) != null) {
result += res;
}
System.out.println("-->result : " + result);1
2
3
4
5
6
8. 最后,记得关闭BufferedReader,InputStream和HttpURLConnection:
br.close();
is.close();
conn.disconnect();1
2
3
9. 最最后,在onCreate()方法中实例化线程类,并运行:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new myThread().start();
}1
2
3
4
5
6
7
以上,完整代码如下:
package com.example.urlconnection_test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private final String myURL = "http://www.ibookpa.com/mobileFilter?action=login";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new myThread().start();//启动线程,进行网络操作
}
private class myThread extends Thread {
@Override
public void run() {
super.run();
try {
URL url = new URL(myURL);
HttpURLConnection conn= (HttpURLConnection)url.openConnection();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String result = "";
String res = null;
while ((res = br.readLine()) != null) {
result += res;
}
System.out.println("-->result : " + result);
br.close();
is.close();
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
运行效果如下:
以上,是一个简单的通过HttpURLConnection实现的从网络获取数据的例子,其中需要注意的是,网络操作不能在MainThread中进行,否则会出现NetworkOnMainThreadException错误。
使用POST的实例
1.新建项目,命名为URLConnection_Post_test:
2.在AndroidManifest.xml中添加网络操作相关权限
1
3.构造URL
在mainActivity.java中创建String型变量myURL用于存放URL地址:
private final String myURl="http://www.ibookpa.com/mobileFilter?action=login";1
4.创建线程类,用于网络操作
private class myThread extends Thread {
@Override
public void run() {
super.run();
}
}1
2
3
4
5
6
5.创建URL类的对象,用于构造网络访问地址,并创建HttpURLConnection类的对象用于建立连接:
private class myThread extends Thread {
@Override
public void run() {
super.run();
URL url;
try {
url = new URL(myURl);
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
6.设置HttpURLConnection的相关属性
主要属性包括:
- void setDoOutput(boolean) : 设置是否向该HttpURLConnection连接输出
- void setDoInput(boolean) : 设置是否向该HttpURLConnection连接输入
- void setReadTimeout(int) : 设置请求超时时间,单位 ms
- void setRequestMethod(String) : 设置请求方式 ,默认为GET,这里需要设置成POST
- void setUseCaches(boolean) : 设置是否使用缓存,在POST方式中不能使用缓存
- void setRequestProperty(String,String) : 设置请求正文的类型
以下为代码实现:
huc.setDoOutput(true);
huc.setDoInput(true);
huc.setReadTimeout(1000);
huc.setRequestMethod("POST");
huc.setUseCaches(false);
huc.setRequestProperty("Content-Type", "application/x-www-from-urlencoded");
//由于在构造的URL正文中的内容使用URLEncoder.encode来进行编码,所以设置如上,表示正文是urlencoded编码过的form参数1
2
3
4
5
6
7
7.进行连接
huc.connect();1
至此,通过HttpURLConnection的网络连接已经建立,接下来就是通过这个连接进行上传数据和下载数据
上传数据,通过DataOutputStream类来完成
下载数据,通过DataInputStream类或者BufferedReader类来完成
8.上传数据
//创建输出流,通过获取到HttpURLConnection的实例对象huc的输出流进行数据写出
DataOutputStream dos=new DataOutputStream(huc.getOutputStream());
//构造输出的内容,这里是构造一个String类型的数据,也就是这个String类数据将被传输到服务器端
String content="action="+URLEncoder.encode("1234567", "utf-8");
//执行输出操作
dos.writeBytes(content);
//执行刷新操作
dos.flush();
//执行完毕记得关闭输出流
dos.close();1
2
3
4
5
6
7
8
9
10
11
9.下载数据
下载数据有两种方式读取数据:DataInputStream类和BufferedReader类
之前说过POST方式不能使用缓存来着,可是这里使用BufferedReader也能获取到数据,有点不太明白,有待解决
下面是使用DataInputStream的示例:
//创建输入流,通过获取到HttpURLConnection的实例对象huc的输入流进行数据读取
DataInputStream dis = new DataInputStream(huc.getInputStream());
//创建String类变量用户存储读取到的数据
String result = "";
//下面这是读取数据的一种方法
int i = 0;
while ((i = dis.read()) != -1) {
result += (char) i;
}
//打印显示读取到的数据
System.out.println("--result :" + result);
//关闭输入流
dis.close();1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
下面是使用BufferedReader的示例:
//创建缓存输入流,通过获取到HttpURLConnection的实例对象huc的输入流进行数据读取
BufferedReader br=new BufferedReader(new InputStreamReader(huc.getInputStream()));
//创建String类型变量,用于存储读取的数据
String result="";
//下面是读取数据的方式
String res=null;
while((res=br.readLine())!=null){
result+=res;
}
System.out.println("--result is:"+result);
br.close();
huc.disconnect();1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
以上两种方式都能实现读取数据并将其打印显示出来
10.在onCreate()方法中创建线程类的实例并运行
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new myThread().start();
}1
2
3
4
5
6
7
到此,通过POST方式进行的网络操作就完成了,下面贴上完整代码:
package com.example.urlconnection_post_test;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
private final String myURl = "http://www.ibookpa.com/mobileFilter?action=login";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new myThread().start();
}
private class myThread extends Thread {
@Override
public void run() {
super.run();
URL url;
try {
url = new URL(myURl);
HttpURLConnection huc = (HttpURLConnection) url
.openConnection();
huc.setDoOutput(true);
huc.setDoInput(true);
huc.setReadTimeout(1000);
huc.setRequestMethod("POST");
huc.setUseCaches(false);
huc.setRequestProperty("Content-Type",
"application/x-www-from-urlencoded");
// 由于在正文中的内容使用URLEncoder.encode来进行编码,所以设置如上,表示正文是urlencoded编码过的form参数
huc.connect();
// 创建输出流,通过获取到HttpURLConnection的实例对象huc的输出流进行网络传输
DataOutputStream dos = new DataOutputStream(
huc.getOutputStream());
// 构造输出的内容,这里是构造一个String类型的数据,也就是这个String类数据将被传输到服务器端
String content = "action="
+ URLEncoder.encode("1234567", "utf-8");
// 执行输出操作
dos.writeBytes(content);
// 执行刷新操作
dos.flush();
// 执行完毕记得关闭输出流
dos.close();
// //创建输入流,通过获取到HttpURLConnection的实例对象huc的输入流进行数据读取
// DataInputStream dis = new DataInputStream(huc.getInputStream());
// //创建String类变量用户存储读取到的数据
// String result = "";
//
// //下面这是读取数据的一种方法
// int i = 0;
// while ((i = dis.read()) != -1) {
// result += (char) i;
// }
//
// //打印显示读取到的数据
// System.out.println("--result :" + result);
//
// //关闭输入流
// dis.close();
//
// huc.disconnect();
//创建缓存输入流,通过获取到HttpURLConnection的实例对象huc的输入流进行数据读取
BufferedReader br=new BufferedReader(new InputStreamReader(huc.getInputStream()));
//创建String类型变量,用于存储读取的数据
String result="";
//下面是读取数据的方式
String res=null;
while((res=br.readLine())!=null){
result+=res;
}
System.out.println("--result is:"+result);
br.close();
huc.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
通过HttpClient实现网络操作
HttpClient相比传统的URLConnection,增加了易用性和灵活性,它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。
使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。
1. 创建HttpClient对象。
2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
6. 释放连接。无论执行方法是否成功,都必须释放连接
使用GET方法的实例
1.新建一个项目,命名为HttpClient_test
2.在AndroidManifest.xml文件中添加网络操作相关权限
1
3.具体操作步骤上面已经说过,这里就不再赘述,贴上完整代码:
package com.example.httpclient_test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private final String myURL = "http://www.ibookpa.com/mobileFilter?action=login";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new myThread().start();
}
private class myThread extends Thread {
@Override
public void run() {
super.run();
//创建HttpClient对象
HttpClient hc = new DefaultHttpClient();
//创建请求方法的实例,这里用的是get方法,并传入了定义好的URL地址
HttpGet httpGet = new HttpGet(myURL);
//创建HttpResponse对象
HttpResponse hr = null;
try {
//调用HttpClient对象的execute()方法,返回一个HttpResponse实例,赋值给创建好的HttpResponse对象
hr = hc.execute(httpGet);
//调用HttpResponse的getEntity()获得HttpEntity对象,通过HttpEntity对象获取数据
HttpEntity he = hr.getEntity();
//当获取到的数据不为空时
if (he != null) {
//获取HttpEntity的内容,并进行答应输出操作
InputStream is = he.getContent();
//读取数据
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String result="";
String res=null;
while((res=br.readLine())!=null){
result+=res;
}
System.out.println("--> result is: "+result);
//关闭缓存输入流
br.close();
//中止网络请求
httpGet.abort();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
使用POST方法的实例
注: Android开发中和Java开发中通过Post上传数据的方法稍有不同,这里不深入研究,给出代码演示在Android中的操作方法即可
1.新建一个项目,命名为HttpClient_Post_test
2.在AndroidManifest.xml文件中添加网络操作相关权限
1
3.具体操作步骤上面已经说过,这里就不再赘述,贴上完整代码:
package com.example.httpclient_post_test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private final String myURL = "http://www.ibookpa.com/mobileFilter?action=login";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new myThread().start();
}
private class myThread extends Thread {
@Override
public void run() {
super.run();
HttpClient hc = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(myURL);
try {
// 使用NameValuePair来保存要传递的Post参数
List postParameters = new ArrayList();
// 添加要传递的参数
postParameters.add(new BasicNameValuePair("username", "测试君"));
postParameters.add(new BasicNameValuePair("userpwd", "ceshijun"));
// 实例化UrlEncodedFormEntity对象
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(
postParameters);
// 使用HttpPost对象来设置UrlEncodedFormEntity的Entity
httpPost.setEntity(formEntity);
System.out.println("--上传的URL链接为: " + httpPost.getURI());
// 到此,通过Post方法进行上传完成
// 以下是通过Post方式进行数据读取,步骤和Get方法类似
HttpResponse hr = hc.execute(httpPost);
HttpEntity he = hr.getEntity();
if (he != null) {
// 获取HttpEntity的内容,并进行答应输出操作
InputStream is = he.getContent();
// 读取数据
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
String result = "";
String res = null;
while ((res = br.readLine()) != null) {
result += res;
}
System.out.println("--> result is: " + result);
// 关闭缓存输入流
br.close();
// 中止网络请求
httpPost.abort();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
以上,总结了通过URLConnection类和HttpClient类进行网络操作的相关知识,是比较基础的操作,但是所有复杂的操作都是简单基础操作的结合,所以通过以上几个实例,加以理解,能应付一般的网络操作需求了