android Http网络获取数据

本文介绍的使用HttpUrlConnectionHttpClient的使用,因为httpClient后面的版本都不建议使用了,所以介绍的少,加上相对于HttpUrlConnection来说,这方面的资料也比较多吧。

使用HttpUrlConnecction连接

步骤:

  1. 通过URL得到HttpUrlConnecction实例
1
2
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  1. 设置请求方式
    2.1 Get请求,直接获取数据
1
connection.setRequestMethod("GET");

2.2 Post请求,发送数据提交给服务器。注意:每条数据都要以键值对的形式存在,数据与数据之间用&符号隔开
注意:必须先设置两个方法:

1
2
3
4
5
// 发送POST请求必须设置如下两行  ,需要在connect  之前设定好
connection.setRequestMethod("POST");
urlConnect.setDoOutput(true);
urlConnect.setDoInput(true);
urlConnect.connect();//需要连接成功后,才可以post发送数据

这里的connect必须在这两个方法之后,这两个方法的对应解释为:

  • URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;最后进行下面设置进行post请求:
1
2
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=admin&password=123456");
  1. 选项设置:连接超时、读取超时的毫秒数,以及服务器希望得到的一些消息头等
1
2
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
  1. 获取网络返回的数据流
1
InputStream in = connection.getInputStream();
  1. 关闭连接
1
connection.disconnect();

其他设置

  • 返回状态码:

    1
    httpURLConnection.getResponseCode()
  • Post方式,设置非缓存

    1
    httpURLConnection.setUseCaches(false);

HttpURLConnection在设置Http Header

都使用同一个方法:

1
httpURLConnnection.setRequestProperty(key,value);

参考:Adding header for HttpURLConnection

一些问题:

HttpURLConnection设置cookie(需要在connect之前)

代码如下:(注意key=Cookie

1
2
httpURLConnnection.setRequestMethod("POST");
httpURLConnnection.setRequestProperty("Cookie", firstCookie);

参考:HttpURLConnection重定向,获取及设置cookie

另一种方式:通过自定义CookieStore进行自动设置cookie.

引用参考:How do I persist cookies when using HTTPUrlConnection?

  • MyCookieStore是实现CookieStore接口.并在内部使用SharePreference进行存储数据(添加的时候),在生成实例的时候进行获取数据。详细点击链接参考代码。
  • 通过CookieManager进行设置
    1
    2
    CookieManager cmrCookieMan = new CookieManager(new MyCookieStore(this.objContext), CookiePolicy.ACCEPT_ALL);
    CookieHandler.setDefault(cmrCookieMan);

这里的MyCookieStore是实现CookieStore接口

得到Header部分

得到头部信息很简单。代码为:

1
Map<String, List<String>> map = httpUrlConnection.getHeaderFields();

得到cookie

通过得到http header cookie这种方式,可以得到cookie来作为登录凭证

对应的代码:

  • httpURLConnection.connect()链接之前:
1
2
3
4
5
6
java.net.CookieManager manager = new java.net.CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);

或者
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
  • 需要在httpURLConnection.connect()或者httpURLConnection.getInputStream()执行以后:
1
2
3
4
5
System.out.println("Headers-------start-----");
for (int i = 1; (key = conn.getHeaderFieldKey(i)) != null; i++) {
System.out.println(key + ":" + conn.getHeaderField(i));
}
System.out.println("Headers-------end-----");

当你获取cookie的时候,是当key="Set-Cookie"的时候,则value对应的值就是cookie的值。

另外一种方式,得到cookie

结合CookieStore,CookieManager

参考:android HttpURLConnection ,HttpClient设置Cookie,点击看详细代码。

步骤:

  • 跟前面一样设置cookieManager,再加入CookieHandler.setDefault(cookieManager);

  • 初始化HttpConnectionconnect.最后connection.getHeaderFields();得到头部操作

  • 最后通过CookieManager得到CookieStore;

1
CookieStore store = manager.getCookieStore();

接着对store进行处理得到httpCookie即:cookie对应信息的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void responseUpdateCookieHttpURL(CookieStore store) {
boolean needUpdate = false;
List<HttpCookie> cookies = store.getCookies();
HashMap<String, String> cookieMap = null;
if (cookieMap == null) {
cookieMap = new HashMap<String, String>();
}
for (HttpCookie cookie : cookies) {
String key = cookie.getName();
String value = cookie.getValue();
if (cookieMap.size() == 0 || !value.equals(cookieMap.get(key))) {
needUpdate = true;
}
cookieMap.put(key, value);

System.out.println(cookie.getName() + "---->" + cookie.getDomain()+ "------>" + cookie.getPath());
}
}

你可以通过connection.getHeaderFields()逐个遍历输出,关注Set-Cookie的值,去感受下得到的值是什么。

开启GZIP压缩

对于文本数据,特别是json数据或者html网页数据,最好使用gzip进行压缩,理论上文本数据可以压缩为原来的1/3,效果很明显,压缩之后应该使用gzip流进行解压缩!

注意:HttpURLConnection发请求时,默认request hearder里会加上 Accept-Encoding: gzip。但这是(android 2.3.3) 版本以后才加上,需要注意。
来源:[原]Android HttpURLConnection Accept-Encoding: gzip 版本问题

使用步骤
  • 在请求头进行设置:

    1
    conn.setRequestProperty("Accept-Encoding", "gzip"); //设置头参数
  • 对返回的数据流使用GZIPInputStream进行解压

    1
    2
    3
    4
    5
    InputStream is = new BufferedInputStream(conn.getInputStream());  
    String encoding = conn.getContentEncoding();
    if(encoding!=null && encoding.contains("gzip")){//首先判断服务器返回的数据是否支持gzip压缩,
    is = new GZIPInputStream(is); //如果支持则应该使用GZIPInputStream解压,否则会出现乱码无效数据
    }

参考来源:Android_HttpURLConnection_Get和Post请求

错误记录:

android4.0中HttpURLConnection抛异常java.io.FileNotFoundException,这个是android4的错误,当httpCon.setDoOutput(true)的时候,默认使用post方式,这里应该置为false.

注意:setDoOutput的使用:

网上查到的解释是,设置true,表示你发送的请求,会把body的内容发送至server端,即POST和PUT才需要使用。GET完全可以不用设置

使用HttpClient连接

步骤:

  1. HttpClient为接口,需要DefaultHttpClient得到
1
HttpClient httpClient = new DefaultHttpClient();
  1. 设置请求的方式:(统一使用方法execute请求)
    2.1 使用get请求,需要通过HttpGet对象进行请求
1
2
HttpGet httpGet = new HttpGet("http://www.baidu.com");
httpClient.execute(httpGet);

2.2 使用post请求,需要创建httpPost对象,再使用NameValuePair存放到List集合来存储键值。具体如下

1
2
3
4
5
6
7
8
9
 //存储键值
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("username", "admin"));
params.add(new BasicNameValuePair("password", "123456"));
//转换编码
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "utf-8");
//设置
httpPost.setEntity(entity);
httpClient.execute(httpPost);//最后一步执行
  1. 通过execute()方法之后会返回一个 HttpResponse 对象,当状态码==200说明请求成功
1
2
3
if (httpResponse.getStatusLine().getStatusCode() == 200) {
// 请求和响应都成功了
}
  1. 获取服务器返回的具体内容
1
2
3
4
HttpEntity entity = httpResponse.getEntity();//获取实例
String response = EntityUtils.toString(entity, "utf-8");//制定编码
或者:得到输入流自行处理
InputStram inputStreeam=httpEntity.getContent();

方法解释:

  • getEntity():

    用于获取响应的消息实体

  • getStatusLine()

    用于获取响应的状态行,在返回结果StatusLine对象包含了HTTP响应的状态码,可以使用方法getStatusCode().

错误问题

扩展

资料

Android持久化保存cookie,这个资料,太老了,讲得是HttpClient获取cookie的方式。

# Android Developer Reference - HttpURLConnection这篇译文,来自官网:HttpURLConnection