Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解

Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解

   

(本文转自: http://blog.csdn.net/yinhaide/article/details/44756989)        

前言:现在很多APP都需要云的功能,也就是通过网络与服务器交换数据。有的采用tcp/ip协议,但是你必须拥有一个固定ip的服务器,可以购买阿里云服务器之类的,就是贵了点。如果只是个人的小应用的的话可以采用新浪云平台这种免费的服务器,采用的协议是http协议,具体实现方式如下:

方式一、在线登陆

这种方式一般是手机端向服务器提交用户名与密码两个参数,服务器通过数据库中查找匹配,找到与没找到都回复手机一个应答数据即可。

手机端代码实现

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
HttpClient httpClient =  new  DefaultHttpClient();
//这里是你与服务器交互的地址  
String validateUrl = " 
//设置读取超时
httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,  8000 );
//设置读取超时
httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,  8000 );
HttpPost httpRequst =  new  HttpPost(validateUrl);                 
//准备传输的数据
List<BasicNameValuePair> params =  new  ArrayList<BasicNameValuePair>();
//以post的方式给服务器传一下数据 健-值结构
params.add( new  BasicNameValuePair( "name" "zhangsan" ));
params.add( new  BasicNameValuePair( "password" "123" ));  
 
try
{
     //发送请求
     httpRequst.setEntity( new  UrlEncodedFormEntity(params, HTTP.UTF_8));
     //得到响应
     HttpResponse response = httpClient.execute(httpRequst);
     //返回值如果为200的话则证明成功的得到了数据
     if (response.getStatusLine().getStatusCode() ==  200 ){
         StringBuilder builder =  new  StringBuilder();
         //将得到的数据进行解析
         BufferedReader buffer =  new  BufferedReader( new  InputStreamReader(response.getEntity().getContent()));
         for (String s =buffer.readLine(); s!=  null ; s = buffer.readLine()){
             builder.append(s);
         }
         //得到Json对象
         JSONObject jsonObject   =  new  JSONObject(builder.toString());
         //通过得到键值对的方式得到值,其中success是服务器定义返回的数据
         String result = jsonObject.getString( "success" );
         Log.e( "message" , result);
     else {
         Log.e( "login" , "erro" );
         result= "erro" ;
     }
catch  (Exception e) {
     Log.e( "sharehotel" , "exception" );
     result= "exception" ;
}

 当然 Menifest必须添加联网权限啦~

1
< uses-permission  android:name = "android.permission.INTERNET"  />

服务器端代码实现

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
<?php  
     require_once ( "database.php" );  
     $db  new  DB();  
     $name  $_POST [ 'name' ];  
         $name  = iconv( "utf-8" , "gbk" , $name );  
     $passwd  $_POST [ 'passwd' ];  
         $passwd  = iconv( "utf-8" , "gbk" , $passwd );  
     //查看用户名和密码是否正确  
     $sql  "select name from `user_database` where name='%s' and password='%s' limit 1" ;  
     $sql  = sprintf( $sql $name $password );  
     $result  $db ->select( $sql );  
     if  (! count ( $result )){  
         $ret [ 'success' ] =  "false" ;  
         $ret [ 'msg' ] =  "fromuser or passwd is invalid" ;  
         $json  = json_encode( $ret );  
         echo  $json ;  
         exit ;  
     }     
         //密码或用户名正确  
     $ret [ 'success' ] =  "true" ;  
     $ret [ 'msg' ] =  "success login" ;  
     $json  = json_encode( $ret );  
     echo  $json ;  
     exit ;  
?>

前面两行输连接上新浪云平台的数据库,第三行是GBK文字编码转成UTF-8,因为有时候手机端采用的是GBK的编码方式。可以通过eclipse-右键工程-property-Android查看编码方式。再下面就是数据库查询了,如果查询成功即给手机返回json数据(键值格式success-true),如果失败返回false。

附上新浪云数据库函数database.php

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
<?php  
class  DB{  
   
     private  $mysql ;  
     function  __construct( $charset = "GBK" ){  
           
         //使用sae接口连接到数据库  
         $this ->mysql =  new  SaeMysql();  
         $this ->mysql->setCharset( $charset );        //设置字符集  
     }  
     /** 
      * @return:成功返回数组,失败时返回false 
      */  
     public  function  select( $sql ){  
         $result  $this ->mysql->getData( $sql );  
         if  ( $this ->mysql->errno() != 0){  
             die "Error:"  $this ->mysql->errmsg());  
         }  
         return  $result ;  
     }  
     /** 
      * @return:运行Sql语句,不返回结果集 
      */  
     public  function  query( $sql ){  
         $this ->mysql->runSql( $sql );  
         if  ( $this ->mysql->errno() != 0){  
             die "Error:" . $this ->mysql->errmsg());  
         }  
           
     }  
     public  function  exec ( $sql ){  
         $this ->query( $sql );  
     }  
     function  __destruct(){  
   
         $this ->mysql->closeDb();  
   
     }  
     public  function  get_con(){  
         return  $this ->mysql;  
     }  
}  
?>

当然,不得不说的是,因为手机端登陆访问服务器是个耗时操作,你不能在主线程中直接调用以上代码,必须要新开辟一个线程处理这些耗时的操作。具体怎么开辟线程处理这里就不多讲了!

方式二:批量的数据获取

相对第一种方式来说,这种方式获得的数据结构更加复杂。比如说,你需要服务器返回给你十条数据,其中每条数据中都包含若干个键值数据,相当于一个二维数组。手机端的请求代码一样,只是在收到数据之后需要解包,因为服务器把数据打包发送来的。

服务器端实现代码:

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
<?php  
     require_once ( "database.php" );  
     //解码  
     function  JSON( $array ) {  
             arrayRecursive( $array 'urlencode' , true);  
             $json  = json_encode( $array );  
             return  urldecode( $json );  
             }  
     function  arrayRecursive(& $array $function $apply_to_keys_also  = false)  
         {  
             static  $recursive_counter  = 0;  
             if  (++ $recursive_counter  > 1000) {  
                 die ( 'possible deep recursion attack' );  
             }  
             foreach  ( $array  as  $key  =>  $value ) {  
                 if  ( is_array ( $value )) {  
                     arrayRecursive( $array [ $key ],  $function $apply_to_keys_also );  
                 else  {  
                     $array [ $key ] =  $function ( $value );  
                 }  
            
                 if  ( $apply_to_keys_also  &&  is_string ( $key )) {  
                     $new_key  $function ( $key );  
                     if  ( $new_key  !=  $key ) {  
                         $array [ $new_key ] =  $array [ $key ];  
                         unset( $array [ $key ]);  
                     }  
                 }  
             }  
             $recursive_counter --;  
         }  
     //解码  
     $db  new  DB();  
     $content  $_POST [ 'content' ];  
         $content  = iconv( "utf-8" , "gbk" , $content );  
     $name  $_POST [ 'name' ];  
         $name  = iconv( "utf-8" , "gbk" , $name );  
     $sql  "select * from `advice` order by time desc limit 20" ;  
     $result  $db ->select( $sql );  
     if  (! count ( $result )){  
         $ret [ 'success' ] =  "false" ;  
         $ret [ 'msg' ] =  "no message record" ;  
         $json  = json_encode( $ret );  
         echo  $json ;  
         exit ;  
     }  
     $i  = 0;  
         foreach  ( $result  as  $val ){  
             $ret [ 'data' ][ $i ][ 'remarks' ] = iconv( "gbk" , "utf-8" , $val [ 'remarks' ]);  
         $ret [ 'data' ][ $i ][ 'name' ] = iconv( "gbk" , "utf-8" , $val [ 'name' ]);  
             $ret [ 'data' ][ $i ][ 'time' ] = iconv( "gbk" , "utf-8" , $val [ 'time' ]);  
             $ret [ 'data' ][ $i ][ 'content' ] = iconv( "gbk" , "utf-8" , $val [ 'content' ]);  
         $i ++;     
     }  
     $ret [ 'success' ] =  "true" ;  
     $ret [ 'msg' ] =  "receiver message success" ;  
         $json  = JSON( $ret );  
     echo  $json ;  
     exit ;  
?>

与前面的服务器代码有所不同的是,这段代码在前面多了两个函数,有什么用呢?首先说的是,服务器在获得手机的请求成功之后将一大堆的数据经过json打包发给手机,但是,json是不支持中文的,所以如果需要传输中文的话必须经过前面两个函数进行编码才能传输。最后传给手机的$json变量其实就是一个二维键值数据,只要手机那边经过合理的解析即可。数据库请求成功之后的返回值result其实就是一个二维数组,通过一个类似for循环的foreach函数将数据获取下来之后经过json打包发给手机端。

手机端实现:

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
List<Map<String,Object>>  listiterms= new  ArrayList<Map<String,Object>>();  
HashMap<String, Object>  hashmap= new  HashMap<String,Object>();  
String result =  null ;                             
HttpClient httpClient =  new  DefaultHttpClient();                
//这里是你与服务器交互的地址  
String validateUrl =  "http://" ;                 
//设置读取超时  
httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,  5000 );                
//设置读取超时  
httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,  5000 );                 
HttpPost httpRequst =  new  HttpPost(validateUrl);                
//准备传输的数据  
List<BasicNameValuePair> params =  new  ArrayList<BasicNameValuePair>();     
params.add( new  BasicNameValuePair( "content" "example" ));  
params.add( new  BasicNameValuePair( "name" "zhangsan" ));                                           
try  
{       
     //发送请求  
     httpRequst.setEntity( new  UrlEncodedFormEntity(params, HTTP.UTF_8));  
     //得到响应  
     HttpResponse response = httpClient.execute(httpRequst);                           
     //返回值如果为200的话则证明成功的得到了数据  
     if (response.getStatusLine().getStatusCode() ==  200 )  
     {  
         StringBuilder builder =  new  StringBuilder();                                    
         //将得到的数据进行解析  
         BufferedReader buffer =  new  BufferedReader( new  InputStreamReader(response.getEntity().getContent()));                   
         for (String s =buffer.readLine(); s!=  null ; s = buffer.readLine()){  
             builder.append(s);                                                
         }  
         //得到Json对象  
         JSONObject jsonObject   =  new  JSONObject(builder.toString());  
         //通过得到键值对的方式得到值  
         result = jsonObject.getString( "success" ); //判断时候获得数据  
         if (result.equals( "true" )){  
             //得到json数据  
             String data = jsonObject.getString( "data" );    
             //将json数据进行解析  
             JSONArray arr =  new  JSONArray(data);  
             int  i= 0 ;  
             //循环解析json数组,得到一个需要的键-值变量  
             for  ( i =  0 ; i < arr.length(); i++) {   
                 Map<String,Object> map= new  HashMap<String,Object>();  
                 JSONObject temp = (JSONObject) arr.get(i);     
                 map.put( "remarks" , temp.getString( "remarks" ));  
                 map.put( "name" , temp.getString( "name" ));  
                 Log.e( "innername" , temp.getString( "name" ));  
                 map.put( "content" , temp.getString( "content" ));  
                 map.put( "time" , temp.getString( "time" ));                                              
                 listiterms.add(map);                
             }                                        
         } else {      
             //没有数据  
             hashmap.put( "remarks" "no_data" );  
             listiterms.add(hashmap);  
         }  
                 
     else {  
         //连接失败  
         hashmap.put( "remarks" "connect_erro" );  
         listiterms.add( hashmap);   
     }  
catch  (Exception e) {    
     //连接异常  
     hashmap.put( "remarks" "exception" );  
     listiterms.add(hashmap);   
}

与登陆代码不同的是这里多了json数据解析,将二维键值数组存储到List<Map<String,Object>>中,具体怎么用这个结构这里就不多提了。与前面一样的是必须新开线程处理这些耗时的操作。

 


本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/4660830.html,如需转载请自行联系原作者

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值