補充:關於PHP服務端可能出現的問題:php
若是你恰好也像我同樣,用php實現的服務端程序,採用的是apache服務器,那麼虛擬主機的配置可能會影響到android應用的調試!!android
在android應用中訪問的IP都是10.0.2.2,若是在apache虛擬主機配置文件中配置了多個虛擬主機,那麼將默認解析爲對第一個虛擬主機的請求,因此,在調試android應用時,應該將對應的服務端所配置的那個虛擬主機放在配置文件中的第一個虛擬主機的位置。不然就會出現請求的文件不存在等的錯誤。git
服務端返回JSON數據及在android應用中解析JSON數據:github
1.新建一個json.php文件,返回json格式的數據:apache
1 <?php 2 3 if(isset($_REQUEST["username"])&& isset($_REQUEST["password"])){ 4 5 $username = $_REQUEST["username"]; 6 7 $password = $_REQUEST["password"]; 8 9 if($username == "zhangsan" && $password == "123"){ 10 11 $arr = array( 12 13 "errorCode"=>200, 14 15 "errorMsg"=>"login success" 16 17 ); 18 19 echo json_encode($arr); 20 21 }else{ 22 23 $arr = array( 24 25 "errorCode"=>404, 26 27 "errorMsg"=>"login failure" 28 29 ); 30 31 echo json_encode($arr); 32 33 } 34 35 }else{ 36 37 $arr = array( 38 39 "errorCode"=>500, 40 41 "errorMsg"=>"illeagle params" 42 43 ); 44 45 echo json_encode($arr); 46 47 } 48 49 ?>
返回的信息格式以下:json
{"errorCode":500,"errorMsg":"illeagle params"}
一個大括號內的表示的是一個json對象,內部存儲的是鍵值對數據,鍵與值用冒號分隔,多個鍵值對之間用逗號分隔。緩存
形式如同下面格式的是json array對象:服務器
[{"errorCode":200,"errorMsg":"login success"},{"errorCode":200,"errorMsg":"login success"},{"errorCode":200,"errorMsg":"login success"}]
中括號裏面存放的是用逗號分隔的一個個json對象。網絡
2.Android中要解析json格式數據須要用到的類有JSONObject和JSONArray:async
JSONObject直接使用傳入字符串形式的參數的構造方法建立JSONObject實例,而後調用相應的get方法,便可獲取json形式數據中的每一個鍵對應的值。
當返回的數據是用中括號括着的多個json形式字符串是,就要用到JSONArray了,一樣能夠使用字符串參數構造出JSONArray實例,而後能夠使用下標的形式獲取到其中的每個JSONObject對象,而後使用JSONObject的方法分別取解析便可。
簡單使用示例:
在MainActivity中添加上修改Handler的消息處理方法,當前經過get或者post取得的是json格式的數據,因此添加上對json數據的解析:
1 private Handler handler = new Handler(){ 2 3 public void handleMessage(android.os.Message msg) { 4 5 if(msg.what == OK){ 6 7 String str = msg.obj.toString(); 8 9 try { 10 11 JSONObject obj = new JSONObject(str); 12 13 Log.i(TAG,obj.getString("errorCode")); 14 15 Log.i(TAG,obj.getString("errorMsg")); 16 17 } catch (JSONException e) { 18 19 // TODO Auto-generated catch block 20 21 e.printStackTrace(); 22 23 } 24 25 26 27 } 28 29 } 30 31 };
運行結果:
有時候,服務端返回的多是一些實體類信息,若用戶登陸成功,返回存放用戶我的信息用以緩存在本地,這時,可能但願直接能將返回的JSON格式的數據解析爲實體類對象,以簡化操做。使用JSONObject類固然也能實現,只要獲取到各個字段的值,而後經過它們構造實體類對象便可。可是,還有更簡單的方式,那就是使用GSON。
3.使用GSON解析json數據:
要在本身項目中使用GSON,有兩種方式:
方式1:從網上下載gson的jar包,放到項目的libs目錄中,而後添加到項目的build path中,就能夠直接使用GSON了
方式2:下載GSON的源碼,能夠到github上下載,而後把源碼整個複製到src目錄下,以後也能夠直接使用GSON了。
下面是GSON的簡單使用示例,更多的使用能夠參考GSON的幫助文檔:在下載源碼的包中有docs目錄,裏面就是GSON使用的幫助文檔,能夠在須要時參考。
新建一個實體類,存放返回的errorCode和errorMsg:
1 package cn.csc.start.bean; 2 3 4 5 public class ResponseInfo { 6 7 private int errorCode; 8 9 private String errorMsg; 10 11 public int getErrorCode() { 12 13 return errorCode; 14 15 } 16 17 public void setErrorCode(int errorCode) { 18 19 this.errorCode = errorCode; 20 21 } 22 23 public String getErrorMsg() { 24 25 return errorMsg; 26 27 } 28 29 public void setErrorMsg(String errorMsg) { 30 31 this.errorMsg = errorMsg; 32 33 } 34 35 public ResponseInfo(int errorCode, String errorMsg) { 36 37 super(); 38 39 this.errorCode = errorCode; 40 41 this.errorMsg = errorMsg; 42 43 } 44 45 public ResponseInfo() { 46 47 super(); 48 49 } 50 51 }
修改Handler中消息處理中解析json數據的代碼,此次改用GSON方式解析:
1 Gson gson = new Gson(); 2 3 ResponseInfo info = gson.fromJson(str, ResponseInfo.class); 4 5 Toast.makeText(MainActivity.this, info.getErrorCode()+info.getErrorMsg(), Toast.LENGTH_LONG).show();
注意到,使用GSON的方式解析到實體類對象很是簡單:
沒有特別的需求時,使用默認構造建立GSON實例便可,須要特殊的配置時,能夠使用GsonBuilder來建立GSON實例,具體參考說明文檔
調用fromJson()傳入要解析的數據,及解析後的對象類型,便可完成從json格式字符串到實體類對象的解析。
如果json array形式的字符串,解析則稍微麻煩一點:
如:想要解析[{"errorCode":200,"errorMsg":"login success"},{"errorCode":200,"errorMsg":"login success"},{"errorCode":200,"errorMsg":"login success"}]爲List<ResponseInfo>
可是不能List<ResponseInfo>.class,這時GSON中提供了獲取泛型的類型信息的方法:
使用TypeToken:
TypeToken< List<ResponseInfo>> list = new TypeToken< List<ResponseInfo>>() {};
而後調用list.getType()注意返回的是Type類型的對象,而Gson的fromJson()方法恰好有第二個參數爲Type類型的重載形式。
因此,對[{"errorCode":200,"errorMsg":"login success"},{"errorCode":200,"errorMsg":"login success"},{"errorCode":200,"errorMsg":"login success"}]解析的具體代碼以下:
1 Gson gson = new Gson(); 2 3 TypeToken<List<ResponseInfo>> list = new TypeToken<List<ResponseInfo>>(){}; 4 5 List<ResponseInfo> info_list = gson.fromJson(str, list.getType());
以上,就是兩種對json形式數據的解析方式。
與服務器交互的方式除了內置的HttpURLConnection和HttpClient以外,還能夠選擇一些優秀的開源項目,來簡化與服務端交互的工做,如使用AsyncHttpClient:
AsyncHttpClient能夠到github上獲取:
在github中搜說async-http便可找到該項目,而後clone或者下載zip包就能夠得到該項目了。
在本身的項目中使用async-http的方式如同GSON,也能夠直接使用源碼,或者引用jar包,根據我的喜愛便可。
簡單演示下async-http發送get和post請求的示例:
在MainActivity中添加兩個方法:
使用AsyncHttpClient發送get請求:
1 private void async_get_test(){ 2 3 String username = et_username.getText().toString(); 4 5 String password = et_password.getText().toString(); 6 7 AsyncHttpClient client = new AsyncHttpClient(); 8 9 client.get("http://10.0.2.2/index.php?username="+username+"&password="+password, new AsyncHttpResponseHandler() { 10 11 12 13 @Override 14 15 public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { 16 17 // TODO Auto-generated method stub 18 19 Message msg = new Message(); 20 21 msg.what = OK; 22 23 msg.obj = new String(responseBody); 24 25 handler.sendMessage(msg); 26 27 } 28 29 30 31 @Override 32 33 public void onFailure(int statusCode, Header[] headers, 34 35 byte[] responseBody, Throwable error) { 36 37 // TODO Auto-generated method stub 38 39 Message msg = new Message(); 40 41 msg.what = OK; 42 43 msg.obj = new String(responseBody); 44 45 handler.sendMessage(msg); 46 47 } 48 49 }); 50 51 }
使用AsyncHttpClient發送post請求:
1 private void async_post_test(){ 2 3 String username = et_username.getText().toString(); 4 5 String password = et_password.getText().toString(); 6 7 AsyncHttpClient client = new AsyncHttpClient(); 8 9 RequestParams params = new RequestParams(); 10 11 params.add("username", username); 12 13 params.add("password", password); 14 15 client.post("http://10.0.2.2/index.php", params , new AsyncHttpResponseHandler() { 16 17 18 19 @Override 20 21 public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { 22 23 // TODO Auto-generated method stub 24 25 Message msg = new Message(); 26 27 msg.what = OK; 28 29 msg.obj = new String(responseBody); 30 31 handler.sendMessage(msg); 32 33 } 34 35 36 37 @Override 38 39 public void onFailure(int statusCode, Header[] headers, 40 41 byte[] responseBody, Throwable error) { 42 43 // TODO Auto-generated method stub 44 45 Message msg = new Message(); 46 47 msg.what = OK; 48 49 msg.obj = new String(responseBody); 50 51 handler.sendMessage(msg); 52 53 } 54 55 }); 56 57 }
能夠看到使用AsyncHttpClient的方式很是簡單:
get方式:
建立AsyncHttpClient對象,而後調用get方法便可。
惟一稍微複雜的就是get方法的第二個參數:AsyncHttpResponseHandler,須要建立一個匿名內部類對象,而後重寫AsyncHttpResponseHandler的兩個方法,分別是網絡請求成功的回調方法及網絡請求失敗的回調方法。
post方式:
就比get方式多了一個傳遞參數而已:
RequestParams params = new RequestParams();
params.add("username", username);
params.add("password", password);
使用RequestParams對象存放要提交的參數,而後將其傳遞給post()方法便可。