您的位置:首页 > 理论基础 > 计算机网络

Android网络编程Demo

2015-11-04 21:41 609 查看
1、前言
前一段时间答应了师弟们写一个Android网络请求工具,由于项目的原因一直拖着。今天抽空写一个Demo演示一下,顺便复习一下Android的基本知识点。如有不足之处,请多多指点,谢谢(^_^)

2、HttpUrlConnection与HttpClient的区别
目前android实现网络请求有两种方式分别是HttpUrlConnection和HttpClient。
(1)HttpUrlConnection是java的核心类(这个类能在Android和java之间都能使用)
HttpClient是Apache的开源项目,在Android之中已经默认集成此项目,在标准的java中不能直接使用(如果要使用需要引入Apache的项目包)

(2)HttpUrlConnection默认支持GZIP压缩,HttpClient默认不支持

根据官方指引Android版本2.2以后推荐使用HttpUrlConnection。嘿嘿!作为一名Android开发人员,官方的大腿还是得抱紧的啊(开玩笑>_<)

3、NetworkRequestTool的使用方法

按照惯例还是看一看项目结构,有两个java文件,不过重点是NetworkReuqestTool文件,我对HttpUrlConnection的基本操作做了封装,基本满足日常网络操作,需要使用的同学,直接将此文件Copy到自己的项目中即可。



(1)get请求的使用
先new一个实例,需要传入一个接口,必须重写三个方法,分别是networkSuccess,networkFailure,networkError。
其中networkSuccess方法传进来两个参数,resultString的访问指定地址成功之后返回的结果值,serverHeaderFieldBeanList(注意!这个值有可能为空,建议在使用之前判断是否为空)包含了服务器传回来的Cookies值和Headers值等等。

networkError方法,会传入一个errorString字符串。会大概告知错误的原因。

得到实例之后,调用getNetworkRequest传入一个网络地址(必传)和一个请求头参数(可以为空)。即可完成网络操作。
NetworkRequestTool networkRequestTool = new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {
@Override
public void networkSuccess(String resultString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {

for (int i = 0; i < serverHeaderFieldBeanList.size(); i++) {
NetworkRequestTool.ServerHeaderFieldBean serverHeaderFieldBean = serverHeaderFieldBeanList.get(i);

Log.e("----------->", serverHeaderFieldBean.getKey() + "   :  " + serverHeaderFieldBean.getValue());
}

txt.setText(resultString);
Log.e("----------->", resultString);
}

@Override
public void networkFailure() {
Log.e("----------->", "网络失败");
}

@Override
public void networkError(String errorString) {

Toast.makeText(getApplication(), errorString, Toast.LENGTH_SHORT).show();
}
});
networkRequestTool.getNetworkRequest("http://www.baidu.com", null);


(2)post请求的使用
这个基本和上面的用法差不多,不过主要讲讲调用post请求的postNetworkRequest方法。
这个方法有两种类型,分别如下
第一种类型

public void postNetworkRequest(String urlString, HashMap<String, String> requestParamsMap, HashMap<String, String> jsonBody, HashMap<String, String> setRequestPropertyMap)
第二种类型

public void postNetworkRequest(String urlString, String requestParamsString, String jsonBody, HashMap<String, String> setRequestPropertyMap)

两种方法都是有四个参数需要传入
第一个,当然是指定的网络地址。
第二个,是(键值对&)格式的请求参数。
第三个,是json格式的键值对。
第四个,是设置请求头参数(一般可以不设置,传一个null)。

在第一种类型中,其实是将requestParamsMap,jsonBody做了进步一个的处理将其边为字符串,再调用第二种类型的方法。
例如:

HashMap<String, String> map = new HashMap<>();
map.put("username", "C002563");
map.put("password", "888");


传入给第一种类型的方法。里面的源码将会将这些键值对拼接成一个字符串username=C002563&password=888,再调用第二个方法,将其传入。
jsonBody也是如此,将这些键值对拼接成一个json格式{"username":"C002563","password":"888"},再调用第二个方法,将其传入。

HashMap<String, String> map = new HashMap<>();
map.put("username", "C002563");
map.put("password", "888");
NetworkRequestTool networkRequestTool = new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {
@Override
public void networkSuccess(String jsonString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {
txt.setText(jsonString);
Log.e("----------->", jsonString);
}

@Override
public void networkFailure() {

}

@Override
public void networkError(String errorString) {

}
});
networkRequestTool.postNetworkRequest("网络地址", map, null, null);


当然你也可以这么写,不用HashMap了,咋们自己拼接了字符串,传进去

new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {
@Override
public void networkSuccess(String jsonString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {
txt.setText(jsonString);
Log.e("----------->", jsonString);
}

@Override
public void networkFailure() {

}

@Override
public void networkError(String errorString) {
Toast.makeText(getApplication(), errorString, Toast.LENGTH_SHORT).show();
}
}).postNetworkRequest("网络地址", "username=C002563&password=888", null, null);


(3)post包含JSON格式的使用
这个例子的,我演示了一下请求头的设置以及服务器返回给我的Heardes和Cookies。
请求头和JSON格式,都是自己new一个HashMap,写入自己键值对。即可

主要讲讲serverHeaderFieldBeanList的使用。源码里面写了一个静态的实体类用来存放服务器返回的Headers和Cookies的键值对。
先判断是否为空(因为有些网络请求,服务器可能没有返回这些参数值。)由于ServerHeaderFieldBean实体类是在NetworkRequestTool里面,因此需要NetwrokRequestTool.ServerHeadersFieldBean。接着循环打印这些参数出来(你也可以根据需求实现自己的操作)。

//目标地址
String url = "http://web.jingoal.com/module/common/Login.cjson?client=win&puse=win";

//设置请求头参数
HashMap<String, String> setRequestPropertyMap = new HashMap<>();
//要求服务器返回JSON格式给我
setRequestPropertyMap.put("Content-Type", "application/json; charset=utf-8");

//设置请求json数据
HashMap<String, String> jsonBodyMap = new HashMap<>();
jsonBodyMap.put("login_name", "admin@3028216");
jsonBodyMap.put("old_token", "");
jsonBodyMap.put("pswd", "3dd635a808ddb6dd4b6731f7c409d53dd4b14df2");

NetworkRequestTool networkRequestTool = new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {
@Override
public void networkSuccess(String jsonString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {
//判断是否为空
if (serverHeaderFieldBeanList != null) {
//获取服务器返回的Headers和Cookies
for (int i = 0; i < serverHeaderFieldBeanList.size(); i++) {
NetworkRequestTool.ServerHeaderFieldBean serverHeaderFieldBean = serverHeaderFieldBeanList.get(i);

Log.e("----------->我的测试", serverHeaderFieldBean.getKey() + "   :  " + serverHeaderFieldBean.getValue());
}
}

txt.setText(jsonString);
Log.e("----------->", jsonString);
}

@Override
public void networkFailure() {
Log.e("----------->", "网络失败");
}

@Override
public void networkError(String errorString) {
Log.e("----------->", "网络错误");
}
//在这里设置参数
});

networkRequestTool.postNetworkRequest(url, null, jsonBodyMap, setRequestPropertyMap);


至此,整个类的基本操作就结束了。

接下来看看Demo的效果图



4、NetworkRequestTool源码
这个类的源码,设计比较简单,不再多说了。

package sms.edward.per.myapplication;

import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* description:网络请求工具
*
* 此Demo博客地址:http://blog.csdn.net/u012814441/article/details/49643865
* <p/>
* author:Edward
* <p/>
* 2015/10/26
*/
public class NetworkRequestTool {
private final String CONNECTION_NETWORK_FAILURE = "网络连接失败,请检查网络连接!";
private final String URL_PARSE_FAILURE = "URL解析错误";
private final String NETWORK_RESPONSE_FAILURE = "网络响应失败";
//连接时间,默认(5秒)
private int connTime = 5;
//读取时间,默认(5秒)
private int readTime = 5;
//返回数据成功
private int CONNECTION_SUCCEED = 200;
//编码类型,默认为UTF-8
private String encodingType = "utf-8";
//成功获取返回结果值
private final int GET_RESULT_STRING_SUCCEED = 1;
//获取返回结果值失败
private final int GET_RESULT_STRING_FAILURE = 0;
//网络错误
private final int ERROR = 2;
//回调监听接口
private NetworkCallbackListener networkCallbackListener;
//线程池变量
private ExecutorService executorService;
//是否开启线程池
private boolean isOpenThreadPool = true;
//线程变量
private Thread thread;
//
private List<ServerHeaderFieldBean> serverHeaderFieldList;

//设置编码格式
public void setEncodingType(String encodingType) {
this.encodingType = encodingType;
}

//设置连接时间
public void setConnTime(int connTime) {
if (connTime > 0) {
this.connTime = connTime;
} else {
Log.e("------------->", "设置连接时间不能少于0");
}
}

//设置读取时间
public void setReadTime(int readTime) {
if (readTime > 0) {
this.readTime = readTime;
} else {
Log.e("------------->", "设置读取时间不能少于0");
}
}

//设置回调接口
public void setNetworkCallbackListener(NetworkCallbackListener networkCallbackListener) {
this.networkCallbackListener = networkCallbackListener;
}

/**
* 构造方法
*
* @param networkCallbackListener
*/
public NetworkRequestTool(NetworkCallbackListener networkCallbackListener) {
this(5, 5, 5, true, networkCallbackListener);
}

/**
* 构造方法
*
* @param connTime
* @param readTime
* @param threadPoolNumber
* @param isOpenThreadPool
* @param networkCallbackListener
*/
public NetworkRequestTool(int connTime, int readTime, int threadPoolNumber, boolean isOpenThreadPool, NetworkCallbackListener networkCallbackListener) {
this.connTime = connTime;
this.readTime = readTime;
this.isOpenThreadPool = isOpenThreadPool;
this.networkCallbackListener = networkCallbackListener;
//初始化线程池(默认为5)
executorService = Executors.newFixedThreadPool(threadPoolNumber);
}

/**
* get网络请求(异步)没有包含设置请求头参数
*/
public void getNetworkRequest(String url) {
getNetworkRequest(url, null);
}

/**
* get网络请求(异步)包含设置请求头参数
*/
public void getNetworkRequest(String url, HashMap<String, String> setRequestPropertyMap) {
if (TextUtils.isEmpty(url)) {
Log.e("---------->", "url不能为空");
return;
}
//是否使用线程池
if (isOpenThreadPool) {
executorService.submit(new GetThreadRunnable(url, setRequestPropertyMap));
} else {
thread = new Thread(new GetThreadRunnable(url, setRequestPropertyMap));
//开启一个线程
thread.start();
}
}

/**
* post网络请求(异步)
*
* @param urlString             访问地址
* @param requestParamsMap      设置请求参数(字符串)
* @param jsonBody              设置josn格式参数(字符串)
* @param setRequestPropertyMap 设置请求头参数
*/
public void postNetworkRequest(String urlString, HashMap<String, String> requestParamsMap, HashMap<String, String> jsonBody, HashMap<String, String> setRequestPropertyMap) {
if (TextUtils.isEmpty(urlString)) {
Log.e("---------->", "url不能为空");
return;
}
//将HashMap的requestParamsMap拼接成一个字符串
String resultRequestString = combineRequestParams(requestParamsMap);
//将HashMap的jsonBody拼接成一个字符串。
String resultJsonString = combineJsonBody(jsonBody);
//调用
postNetworkRequest(urlString, resultRequestString, resultJsonString, setRequestPropertyMap);
}

/**
* post网络请求(异步)
*
* @param urlString             访问地址
* @param requestParamsString   设置请求参数(HashMap)
* @param jsonBody              设置josn格式参数(HashMap)
* @param setRequestPropertyMap 设置请求头参数
*/
public void postNetworkRequest(String urlString, String requestParamsString, String jsonBody, HashMap<String, String> setRequestPropertyMap) {
if (isOpenThreadPool) {
executorService.submit(new PostThreadRunnable(urlString, requestParamsString, jsonBody, setRequestPropertyMap));
} else {
thread = new Thread(new PostThreadRunnable(urlString, requestParamsString, jsonBody, setRequestPropertyMap));
//开启一个线程
thread.start();
}
}

/**
* GET的线程操作
*/
public class GetThreadRunnable implements Runnable {
private String urlString;
private HashMap<String, String> setRequestPropertyMap;

public GetThreadRunnable(String urlString, HashMap<String, String> setRequestPropertyMap) {
this.urlString = urlString;
this.setRequestPropertyMap = setRequestPropertyMap;
}

@Override
public void run() {
try {
URL url = new URL(urlString);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// 忽略缓存
httpURLConnection.setUseCaches(false);
//设置读取时间
httpURLConnection.setReadTimeout(readTime * 1000);
//设置连接时间
httpURLConnection.setConnectTimeout(connTime * 1000);
//提出Post请求
httpURLConnection.setRequestMethod("GET");

//设置请求头参数(请求参数必须写在Http正文之内)
if (setRequestPropertyMap != null) {
setRequestProperty(httpURLConnection, setRequestPropertyMap);
}

//获取服务器返回Header
getServerHeaderField(httpURLConnection);

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == CONNECTION_SUCCEED) {
//此处才是发送数据的真正操作
InputStream inputStream = httpURLConnection.getInputStream();

String responseResult = inputStreamConvertString(inputStream);
if (!TextUtils.isEmpty(responseResult)) {
//                        Log.e("----------->网络请求工具最终返回值", responseResult);
handler.sendMessage(handler.obtainMessage(GET_RESULT_STRING_SUCCEED, responseResult));
} else {
handler.sendEmptyMessage(GET_RESULT_STRING_FAILURE);
}
} else {
handler.sendMessage(handler.obtainMessage(ERROR, NETWORK_RESPONSE_FAILURE));
}

} catch (MalformedURLException e) {
Log.e("--------------->", "Url字符串解析错误!");
handler.sendMessage(handler.obtainMessage(ERROR, URL_PARSE_FAILURE));
} catch (IOException e) {
Log.e("--------------->", "网络连接失败,请检查网络连接!");
handler.sendMessage(handler.obtainMessage(ERROR, CONNECTION_NETWORK_FAILURE));
}
}
}

/**
* 获取服务器返回的Header(不可覆盖)
*
* @param httpURLConnection
*/
private void getServerHeaderField(HttpURLConnection httpURLConnection) {
//实例化
serverHeaderFieldList = new ArrayList<>();
String key = null;
for (int i = 1; (key = httpURLConnection.getHeaderFieldKey(i)) != null; i++) {
ServerHeaderFieldBean searverHeaderFieldBean = new ServerHeaderFieldBean();

searverHeaderFieldBean.setKey(key);
searverHeaderFieldBean.setValue(httpURLConnection.getHeaderField(key));
Log.e("----->服务器HeaderField", key + ":" + httpURLConnection.getHeaderField(key));

serverHeaderFieldList.add(searverHeaderFieldBean);
}
}

/**
* POST的线程操作
*/
public class PostThreadRunnable implements Runnable {
private String urlString;
private String requestParamsString;
private String jsonBody;
private HashMap<String, String> setRequestPropertyMap;

public PostThreadRunnable(String urlString, String requestParamsString, String jsonBody, HashMap<String, String> setRequestPropertyMap) {
this.urlString = urlString;
this.jsonBody = jsonBody;
this.requestParamsString = requestParamsString;
this.setRequestPropertyMap = setRequestPropertyMap;
}

@Override
public void run() {
try {
URL url = new URL(urlString);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
// 忽略缓存
httpURLConnection.setUseCaches(false);
//设置读取时间
httpURLConnection.setReadTimeout(readTime * 1000);
//设置连接时间
httpURLConnection.setConnectTimeout(connTime * 1000);
//提出Post请求
httpURLConnection.setRequestMethod("POST");

//设置请求头参数(请求参数必须写在Http正文之内)
if (setRequestPropertyMap != null) {
setRequestProperty(httpURLConnection, setRequestPropertyMap);
}

//开启一个输出流(getOutputStream方法已经在里面调用connect方法)
DataOutputStream dataOutputStream = new DataOutputStream(httpURLConnection.getOutputStream());
//设置请求参数
if (requestParamsString != null) {
dataOutputStream.write(requestParamsString.getBytes(encodingType));
}

//设置实体JSON参数
if (jsonBody != null) {
dataOutputStream.write(jsonBody.getBytes(encodingType));
Log.e("------------>设置JSON:", jsonBody);
}

dataOutputStream.flush();
dataOutputStream.close();

//获取服务器返回Header
getServerHeaderField(httpURLConnection);

//得到网络响应码
int responseCode = httpURLConnection.getResponseCode();

if (responseCode == CONNECTION_SUCCEED) {
//此处才是发送数据的真正操作
InputStream inputStream = httpURLConnection.getInputStream();

String responseResult = inputStreamConvertString(inputStream);
if (!TextUtils.isEmpty(responseResult)) {
//                        Log.e("----------->网络请求工具最终返回值", responseResult);
handler.sendMessage(handler.obtainMessage(GET_RESULT_STRING_SUCCEED, responseResult));
} else {
handler.sendEmptyMessage(GET_RESULT_STRING_FAILURE);
}
} else {
handler.sendMessage(handler.obtainMessage(ERROR, NETWORK_RESPONSE_FAILURE));
}

} catch (MalformedURLException e) {
Log.e("--------------->", "Url字符串解析错误!");
handler.sendMessage(handler.obtainMessage(ERROR, URL_PARSE_FAILURE));
} catch (IOException e) {
Log.e("--------------->", "网络连接失败,请检查网络连接!");
handler.sendMessage(handler.obtainMessage(ERROR, CONNECTION_NETWORK_FAILURE));
}
}
}

/**
* 将输入流转换为字符串
*
* @param inputStream
* @return
* @throws IOException
*/
public String inputStreamConvertString(InputStream inputStream) throws IOException {
if (inputStream == null) {
return null;
}
//将输入流暂时写进缓冲区中
BufferedInputStream bis = new BufferedInputStream(inputStream);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int length = 0;
byte[] by = new byte[1024];
while ((length = bis.read(by)) != -1) {
bos.write(by, 0, length);
}
bos.flush();
String result = new String(bos.toByteArray(), encodingType);

bos.close();
bis.close();

return result;
}

/**
* 拼接请求参数
*
* @return
*/
public String combineRequestParams(HashMap<String, String> requestParamsMap) {
if (requestParamsMap == null) {
return null;
}
Iterator<Entry<String, String>> iterator = requestParamsMap.entrySet().iterator();

StringBuffer stringBuffer = new StringBuffer();

while (iterator.hasNext()) {
Map.Entry<String, String> tempMap = iterator.next();

stringBuffer.insert(0, tempMap.getKey() + "=" + tempMap.getValue() + "&");
}
//删除最后一个&
stringBuffer.deleteCharAt(stringBuffer.length() - 1);

System.out.println(stringBuffer.toString());

Log.e("-------------->拼接请求参数:", stringBuffer.toString());
return stringBuffer.toString();
}

/**
* 拼接字符串
*
* @param jsonBody
* @return
*/
public String combineJsonBody(HashMap<String, String> jsonBody) {
if (jsonBody == null) {
return null;
}
Iterator<Entry<String, String>> iterator = jsonBody.entrySet().iterator();

StringBuffer stringBuffer = new StringBuffer();

stringBuffer.append("{");

while (iterator.hasNext()) {
Map.Entry<String, String> map = iterator.next();
// 将键值对插入到第1个字符之后(从0开始)
stringBuffer.insert(1, "\"" + map.getKey() + "\":\"" + map.getValue() + "\",");
}
//删除最后一个逗号
stringBuffer.deleteCharAt(stringBuffer.length() - 1);
stringBuffer.append("}");
Log.e("------------>拼接请求JSON参数", stringBuffer.toString());

return stringBuffer.toString();
}

/**
* 设置请求头参数(不能被覆盖)注意请求头参数的设置,因为它有可能决定了服务器返回值的类型
*
* @param httpURLConnection
*/
private void setRequestProperty(HttpURLConnection httpURLConnection, HashMap<String, String> setRequestPropertyMap) {
Iterator<Entry<String, String>> iterator = setRequestPropertyMap.entrySet().iterator();
//设置遍历了一遍Map
while (iterator.hasNext()) {
Map.Entry<String, String> map = iterator.next();

Log.e("------------>设置请求头:", map.getKey() + "    " + map.getValue());
httpURLConnection.setRequestProperty(map.getKey(), map.getValue());
}
}

/**
* Handler处理子线程返回的数据
*/
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//获取子线程发送过来的字符串
String resultString = (String) msg.obj;
switch (msg.what) {
case GET_RESULT_STRING_SUCCEED:
//将子线程得到的结果值回调出去
networkCallbackListener.networkSuccess(resultString, serverHeaderFieldList);
break;
case GET_RESULT_STRING_FAILURE:
networkCallbackListener.networkFailure();
break;
case ERROR:
networkCallbackListener.networkError(resultString);
break;
}
}
};

/**
* 回调接口
*/
public interface NetworkCallbackListener {
//网络连接成功
void networkSuccess(String returnString, List<ServerHeaderFieldBean> serverHeaderFieldBeanList);

//网络连接失败
void networkFailure();

//网络错误
void networkError(String errorString);
}

/**
* HeaderField实体类,用来保存服务器返回的Headers和Cookies
*/
public static class ServerHeaderFieldBean {
private String key;
private String value;

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}
}


5、结束
谢谢各位。

源码请戳这里Android网络编程Demo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: