android客户端和服务端交互,谈谈android客户端和网站数据交互的实现

本文详细介绍了Android客户端如何通过HttpClient发送GET和POST请求,以及如何解析服务器返回的JSON数据。讲解了如何设置HttpClient参数,创建GetMethod和HttpPost对象,执行请求并处理响应。同时,文章还提供了动态组合请求参数的方法,并展示了如何解析JSON数据,将结果存储到列表中。整个过程涵盖了网络请求和数据解析的关键步骤。
摘要由CSDN通过智能技术生成

android客户端一般不直接访问网站数据库,而是像浏览器一样发送get或者post请求,然后网站返回客户端能理解的数据格式,客户端解析这些数据,显示在界面上,常用的数据格式是xml和json。

可以理解客户端其实是一个你自己定义标记语言的浏览器,一般浏览器能解析的是html+css的数据,而android客户端能解析的是xml和json(或者都不是而是你自己定义的火星格式),服务端为了能满足客户端输出这种数据格式的需求,不得不专门针对客户端开发不同于浏览器访问的接口。

所以要开发一个网站的客户端你需要:

1.在客户端模拟get和post请求,请求最终还是通过http协议以url的形式发送

2.在客户单解析服务器返回的数据

3.在服务端根据请求生成相应的json数据(强烈建议使用json而不是xml,相同字符的json能返回更多的有用数据而且解析方便速度快)

这里要讨论的是1、2两点.

一、发送get或者post请求

虽然java本身的HttpURLConnection类完全可以实现get和post,但是非常麻烦,我们还是使用HttpClient这个开源代码来实现。

先讲讲get方法的实现:

不管是get方法还是post方法,都需要httpclient来执行,通过HttpClient httpClient =newHttpClient()可以获得一个httpClient对象,httpClient对象可以给联网操作设定一些预定值,比如超时时间、字符集等。下面的函数在获得httpclient对象的同时设置预定值,同时返回这个httpclient,你可以在后面的代码中直接调用这个函数来获得设置好的httpclient对象:private static HttpClient getHttpClient() {

HttpClient httpClient = new HttpClient();

// 设置 HttpClient 接收 Cookie,用与浏览器一样的策略

//httpClient.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);

// 设置 默认的超时重试处理策略

httpClient.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

// 设置 连接超时时间

httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(TIMEOUT_CONNECTION);

// 设置 读数据超时时间

httpClient.getHttpConnectionManager().getParams().setSoTimeout(TIMEOUT_SOCKET);

// 设置 字符集

httpClient.getParams().setContentCharset(UTF_8);

return httpClient;

}

httpclient对象可以执行get方法(GetMethod),GetMethod对象代表这个请求是通过get发出的,它的构造方法中包含请求地址url参数,下面是我写的一个能获得GetMethod对象的方法:private static GetMethod getHttpGet(String url,String cookie, String userAgent) {

GetMethod httpGet = new GetMethod(url);

// 设置 请求超时时间

httpGet.getParams().setSoTimeout(TIMEOUT_SOCKET);

httpGet.setRequestHeader("Host", "www.netmoon.cn");

httpGet.setRequestHeader("Connection","Keep-Alive");

httpGet.setRequestHeader("Cookie", cookie);

httpGet.setRequestHeader("User-Agent", userAgent);

return httpGet;

}

其中GetMethod httpGet =newGetMethod(url);是必须的,下面的httpGet.setRequestHeader("Host", "www.netmoon.cn");

httpGet.setRequestHeader("Connection","Keep-Alive");

httpGet.setRequestHeader("Cookie", cookie);

httpGet.setRequestHeader("User-Agent", userAgent);

可以暂时不理会。

然后Httpclient对象调用executeMethod()方法,并且将包含了url的GetMethod对象作为executeMethod()方法的参数,executeMethod其实就是发送了一个get请求;int statusCode = httpClient.executeMethod(httpGet);

根据executeMethod()方法的返回码statusCode判断请求是否成功,如果成功则读取返回的数据。BufferedReader reader = new BufferedReader(new InputStreamReader(httpGet.getResponseBodyAsStream()));

StringBuffer stringBuffer = new StringBuffer();

String str = "";

while((str = reader.readLine())!=null){

stringBuffer.append(str);

}

responseBody = stringBuffer.toString();

responseBody中保存的就是get请求所返回的数据。

结合上面getHttpClient()方法和getHttpGet()方法,写一个完整的http get请求实现方法:

public static String http_get(String url) throws AppException {

HttpClient httpClient = null;

GetMethod httpGet = null;

String responseBody = "";

int time = 0;

do{

try

{

httpClient = getHttpClient();

httpGet = getHttpGet(url);

int statusCode = httpClient.executeMethod(httpGet);

Log.i("http","url="+url);

if (statusCode != HttpStatus.SC_OK) {

throw AppException.http(statusCode);

}

else if(statusCode == HttpStatus.SC_OK){

//

}

BufferedReader reader = new BufferedReader(new InputStreamReader(httpGet.getResponseBodyAsStream()));

StringBuffer stringBuffer = new StringBuffer();

String str = "";

while((str = reader.readLine())!=null){

stringBuffer.append(str);

}

responseBody = stringBuffer.toString();

//System.out.println("XMLDATA=====>"+responseBody);

break;

} catch (HttpException e) {

time++;

if(time < RETRY_TIME) {

try {

Thread.sleep(1000);

} catch (InterruptedException e1) {}

continue;

}

e.printStackTrace();

throw AppException.http(e);

} catch (IOException e) {

time++;

if(time < RETRY_TIME) {

try {

Thread.sleep(1000);

} catch (InterruptedException e1) {}

continue;

}

// 发生网络异常

e.printStackTrace();

throw AppException.http(e);

} finally {

// 释放连接

httpGet.releaseConnection();

httpClient = null;

}

}while(time < RETRY_TIME);

return responseBody;

}

其中AppException是我自定义的一个异常累,可以不用理会。

回到安卓开发中,假如客户端需要通过get请求访问一个url地址,则可以直接调用上面的http_get(String url)就可以得到服务器返回的数据了,你可以直接访问www.baidu.com,或者其他任意一网址,都能得到返回数据,不过这些数据是html的。

客户端解析返回的数据

通过上述方法去请求一个普通网址得到的是一般的html,html包含了很多与数据本身无关的东西,比如决定布局的

等标签,因此我们在android客户端开发中一般都是去请求能返回xml或者json数据的url,将这些json数据解析出来,得到我们要的数据,这里以一个第三方物流查询网站返回的json数据格式为例,讲解如何用java解析。

通过抓包我获得了某第三方物流查询网站的查询接口网址(声明,我仅仅是用于讲解未经过别人允许用作商业用途是不道德的):

http://www.kuaidi100.com/query

通过这个网址查询一个快递需要至少传入两个参数type:快递类型(EMS,圆通等),postid(快递编号)

这里涉及到将请求参数组合为一个完整请求地址的过程,因为客户端请求的生成都是动态的,比如博客的客户端,每篇文章的id不一样,url是变动的,往往需要将级别较大的url在代码运行的时候动态组合请求参数之后才能用,网上已经有了一个现成的方法:private static String _MakeURL(String p_url, Map params) {

StringBuilder url = new StringBuilder(p_url);

if(url.indexOf("?")<0)

url.append('?');

for(String name : params.keySet()){

url.append('&');

url.append(name);

url.append('=');

url.append(String.valueOf(params.get(name)));

//不做URLEncoder处理

//url.append(URLEncoder.encode(String.valueOf(params.get(name)), UTF_8));

}

return url.toString().replace("?&", "?");

}

使用这个方法将物流请求的完整url组合的代码如下

url = _MakeURL("http://www.kuaidi100.com/query", new HashMap(){{

put("type", "ems");

put("postid", "5036983946902");

}});

你可以将上面的url输入浏览器,就可以看到返回的json数据了。

运用java解析json:

其实别想太复杂,都是调用库函数实现的,具体解析请看下面的例子(包含了请求和解析,当中的某些方法用到了上面的代码,比如http_get方法和 _MakeUR)

private void getData(){

final Handler handler = new Handler(){

public void handleMessage(Message msg) {

if(msg.what == 1){

try{

JSONArray array = new JSONArray( (String)msg.obj );

for(int i=0; i

JSONObject obj = array.getJSONObject(i);

PostItem item =new PostItem(obj.getString("context") , obj.getString("time"));

mListDatas.add(item);

}

orderList(mListDatas);

mAdapter.notifyDataSetChanged();

mLayer.setVisibility(View.GONE);

}catch (Exception e){

e.printStackTrace();

}

}else if(msg.what == 0){

}else if(msg.what == -1 && msg.obj != null){

}

}

};

new Thread(){

public void run() {

Message msg = new Message();

String result = null;

try {

result = getPostInfo();

} catch (AppException e) {

e.printStackTrace();

msg.what = -1;

msg.obj = e;

}

String resultcode; //查询结果代码

String message; //反馈消息

String datas; //反馈消息

JSONObject jsonObj;

try {

jsonObj = new JSONObject(result);

resultcode = jsonObj.getString("state");

message = jsonObj.getString("message");

if(Integer.parseInt(resultcode) == 3 || message.equals("ok")){

msg.what = 1;

datas = jsonObj.getString("data");

msg.obj = datas;

}else{

msg.what = 0;

msg.obj = message;

}

}catch (Exception e){

e.printStackTrace();

return;

}

handler.sendMessage(msg);

}

}.start();

}

其中,getPostInfo()代码如下:

public static String getPostInfo() {

String url=AppContext.POST_URL;

url = _MakeURL(url, new HashMap(){{

put("type", "ems");

put("postid", "5036983946902");

}});

try{

return http_get(url);

}catch(Exception e){

e.printStackTrace();

return "erro";

}

}

是不是很简单,这里用到了handle来处理网络数据。我们将解析到的结果都保存在了一个list中。

如何使用post就不需要讲了吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值