android 客户端和网站交互数据的实现

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对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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对象的方法:

1
2
3
4
5
6
7
8
9
10
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 = new GetMethod(url);是必须的,下面的

1
2
3
4
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请求;

1
int statusCode = httpClient.executeMethod(httpGet);

根据executeMethod()方法的返回码statusCode判断请求是否成功,如果成功则读取返回的数据。

1
2
3
4
5
6
7
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请求实现方法:

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
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包含了很多与数据本身无关的东西,比如决定布局的<div>等标签,因此我们在android客户端开发中一般都是去请求能返回xml或者json数据的url,将这些json数据解析出来,得到我们要的数据,这里以一个第三方物流查询网站返回的json数据格式为例,讲解如何用java解析。

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

http://www.kuaidi100.com/query

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static String _MakeURL(String p_url, Map<String, Object> 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<String, Object>(){{
           put("type", "ems");
           put("postid", "5036983946902");

       }});

url最后等效于http://www.kuaidi100.com/query?type=ems&postid=5036983946902

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

运用java解析json:

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


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
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<array.length(); 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()代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static String getPostInfo()  {
     String url=AppContext.POST_URL;
     url = _MakeURL(url, new HashMap<String, Object>(){{
         put( "type" , "ems" );
         put( "postid" , "5036983946902" );
                                                                           
     }});
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
     try {
         return http_get(url);     
     } catch (Exception e){
         e.printStackTrace();
         return "erro" ;
     }
}


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值