總結android 採用http請求訪問網路並擷取資料的步驟: 一.發送http請求,並傳遞相應的參數; 二.擷取http返回的狀態,根據返回的狀態,如404錯誤,500錯誤,連線逾時,請求異常等,並在介面提示相關狀態; 三.web伺服器端封裝資料並返回一定格式的資料對象,例如封裝json對象; 四.http狀態返回正常,取出正確的參數並解析,如解析json對象; 五.解析伺服器端返回的資料後顯示在android相應的控制項或儲存本機資料,提示操作完成等。 因為習慣使用以上的5個步驟,於是寫了一個相對完善的一個處理方法。以下主要是使用post方式擷取資料並解析封裝的過程,封裝json主要有兩種封裝方法:一種是單個json封裝,另一種是帶數組的json封裝;解析json對應相應的方法。伺服器端封裝資料的語言採用php封裝。get方式請求的方法過程類似。 1.發送伺服器的http post要求方法 為了使編寫的http post請求具有高度的可重用性,對於傳遞參數採用類似索引值對的數組方式分別傳遞參數以及參數的值,String []key,String []value就是這樣的一個類似索引值對的傳參方式。key是傳遞的參數,value是參數對應的值,url則是訪問的地址。 HttpPostRequest .java源碼:
- package com.httppost.main;
- import java.io.IOException;
- import java.io.InterruptedIOException;
- import java.io.UnsupportedEncodingException;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpResponse;
- import org.apache.http.client.ClientProtocolException;
- import org.apache.http.client.entity.UrlEncodedFormEntity;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.conn.ConnectTimeoutException;
- import org.apache.http.impl.client.DefaultHttpClient;
- import org.apache.http.message.BasicNameValuePair;
- import org.apache.http.params.HttpConnectionParams;
- import org.apache.http.protocol.HTTP;
- import org.apache.http.util.EntityUtils;
- public class HttpPostRequest {
- private String webContext;
- //返回請求內容
- public String getWebContext() {
- return webContext;
- }
- public void setWebContext(String webContext) {
- this.webContext = webContext;
- }
- //該函數返回伺服器訪問的各種狀態,並通過webContext傳遞擷取的文本值
- /**
- * 參數說明
- * url 訪問的網路地址
- * key 傳遞參數的名稱
- * value 傳遞參數的值
- * key 與value數組長度對應,即一對索引值對,這樣可以不限制參數傳遞的個數
- * */
- public int requestHttp(String url,String []key,String []value) {
- // TODO Auto-generated method stub
- int status = 0;
- DefaultHttpClient mHttpClient = new DefaultHttpClient();
- HttpPost mPost = new HttpPost(url);
- List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>();
- int size=key.length;
- for(int i=0;i<size;i++){
- pairs.add(new BasicNameValuePair(key[i], value[i]));
- }
- try {
- mPost.setEntity(new UrlEncodedFormEntity(pairs, HTTP.UTF_8));
- } catch (UnsupportedEncodingException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- try {
- // Socket逾時設定60s
- mHttpClient.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT,60000);
- // 連線逾時60s
- mHttpClient.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT,60000);
- HttpResponse response = mHttpClient.execute(mPost);
- int res = response.getStatusLine().getStatusCode();
- if (res == 200) {
- HttpEntity entity = response.getEntity();
- if (entity != null) {
- String info = EntityUtils.toString(entity);
- setWebContext(info);
- status=1;
- }
- } else if (res == 404) {
- status = 404;
- } else if (res == 500) {
- status = 500;
- }
- } catch (ClientProtocolException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- status = 900;
- } catch (ConnectTimeoutException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- status = 901;
- } catch (InterruptedIOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- status = 902;
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- status = 903;
- }
- return status;
- }
- }
複製代碼 2.擷取伺服器端返回http狀態的提示及處理方法 根據伺服器返回的狀態提示相應的資訊的類,可以根據實際需要自訂提示狀態,例如登入,註冊等提示。 Http_Status_Tips.java源碼:
- package com.httppost.main;
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.widget.Toast;
- public class Http_Status_Tips {
- //伺服器端返回的狀態提示
- public static final String HTTP_0="其他錯誤";
- public static final String HTTP_1="";
- public static final String HTTP_404="404錯誤,請求連結無效";
- public static final String HTTP_500="網路500錯誤,伺服器端程式出錯";
- public static final String HTTP_900="網路傳輸協議出錯";
- public static final String HTTP_901="連線逾時";
- public static final String HTTP_902="網路中斷";
- public static final String HTTP_903="網路資料流傳輸出錯";
- public static final String HTTP_UNKONW="未知的錯誤";
- //自訂的提示
- private String tips;
- public void ShowHttpStatusTips(int status,Context context,ProgressDialog proDialog){
- switch(status){
- case 0:
- Toast.makeText(context, getTips(), Toast.LENGTH_LONG).show();
- break;
- case 1:
- //Toast.makeText(context, getTips(), Toast.LENGTH_LONG).show();
- break;
- case 2:
- Toast.makeText(context, getTips(), Toast.LENGTH_LONG).show();
- break;
- case 3:
- Toast.makeText(context, getTips(), Toast.LENGTH_LONG).show();
- break;
- case 404:
- Toast.makeText(context, HTTP_404, Toast.LENGTH_LONG).show();
- break;
- case 500:
- Toast.makeText(context, HTTP_500,Toast.LENGTH_LONG).show();
- break;
- case 900:
- Toast.makeText(context, HTTP_900, Toast.LENGTH_LONG).show();
- break;
- case 901:
- Toast.makeText(context, HTTP_901, Toast.LENGTH_LONG).show();
- break;
- case 902:
- Toast.makeText(context, HTTP_902, Toast.LENGTH_LONG).show();
- break;
- case 903:
- Toast.makeText(context, HTTP_903, Toast.LENGTH_LONG).show();
- break;
- default:
- Toast.makeText(context, HTTP_UNKONW, Toast.LENGTH_LONG).show();
- break;
- }
- if(proDialog!=null)
- proDialog.dismiss();
- }
- public String getTips() {
- return tips;
- }
- public void setTips(String tips) {
- this.tips = tips;
- }
- }
複製代碼 3.伺服器端封裝json資料的方法 採用php語言封裝json的兩種格式,資料可以是從資料庫返回的數組,本例只採用簡單的賦值方式返回資料。$_POST["type"]對應的是post的請求方式擷取參數值。 (1.)封裝單個json對象 json_1.php
- <?php
- //對於POST的請求
- $type=$_POST["type"];
- $arr = array(
- 'id'=>'2',
- 'username'=>'william',
- 'lat'=>'113.09',
- 'lon'=>'22.2982',
- 'type'=>'傳遞參數:'.$type
- );
- echo json_encode($arr);
- ?>
複製代碼 (2.)封裝帶數組的json對象 json_2.php
- <?php
- //對於POST的請求
- $type=$_POST["type"];
- $arr=array();
- $a = array(
- 'id'=>'1',
- 'username'=>'charlie',
- 'lat'=>'113.09832',
- 'lon'=>'22.29322',
- 'type'=>'傳遞參數:'.$type
- );
- $b = array(
- 'id'=>'2',
- 'username'=>'william',
- 'lat'=>'113.09',
- 'lon'=>'22.2982',
- 'type'=>'傳遞參數:'.$type
- );
- //將兩個數組合并成一個數組
- array_push($arr,$a);
- array_push($arr,$b);
- //封裝成json_2的json
- echo "{\"json_2\":".json_encode($arr)."}"; ?>
複製代碼 4.解析json的兩種方法 兩種解析json的方法:一個是解析單一的json對象(返回字串數組),另一個是解析帶數組對象的json對象(返回ArrayList的對象)。同樣採用key-value的方式擷取數值,適應封裝不同參數的類型。 Json.java源碼
- package com.httppost.main;
- import java.util.ArrayList;
- import java.util.HashMap;
- import org.json.JSONArray;
- import org.json.JSONException;
- import org.json.JSONObject;
- public class Json {
- // 解析單一的json封裝,並返回字串數組
- /**
- * 參數說明:
- * 1.webContent 擷取的網頁封裝的json格式資料
- * 2.key 以數組形式組成的json的鍵名稱
- * */
- public String[] getJSON(String webContent, String[] key) {
- int size = key.length;
- String[] s = new String[size];
- try {
- JSONObject jsonObject = new JSONObject(webContent);
- for (int j = 0; j < size; j++) {
- s[j] = jsonObject.getString(key[j]);
- System.out.println(key[j] + "===string==="
- + jsonObject.getString(key[j]));
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- s = null;
- }
- return s;
- }
- // 擷取數組型的結構,返回ArrayList<HashMap<String, Object>>,方便listview中填充資料
- /**
- * 參數說明:
- * 1.webContent 擷取的網頁封裝的json格式資料
- * 2.key 以數組形式組成的json的鍵名稱 3.jsonName
- * 封裝json數組資料的json名稱
- * */
- public ArrayList<HashMap<String, Object>> getJSONArray(String webContent,
- String[] key, String jsonName) {
- ArrayList<HashMap<String, Object>> list;
- JSONArray jsonObject;
- try {
- jsonObject = new JSONObject(webContent).getJSONArray(jsonName);
- list = new ArrayList<HashMap<String, Object>>();
- for (int i = 0; i < jsonObject.length(); i++) {
- JSONObject jsonObject2 = (JSONObject) jsonObject.opt(i);
- HashMap<String, Object> map = new HashMap<String, Object>();
- for (int j = 0; j < key.length; j++) {
- map.put(key[j], jsonObject2.getString(key[j]));
- System.out.println(key[j] + "==="
- + jsonObject2.getString(key[j]));
- }
- list.add(map);
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- list = null;
- }
- return list;
- }
- }
複製代碼 5.線程處理伺服器狀態並解析相應的資料方法 android中Thread與Handler結合使用的方法,主要調用http請求,提示相應的狀態,處理json資料等。 HttpThread.java源碼
- package com.httppost.main;
- import java.util.ArrayList;
- import java.util.HashMap;
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.os.Handler;
- import android.os.Message;
- import android.widget.Toast;
- public class HttpThread extends Thread{
- private Context context;
- private ProgressDialog proDialog;
- private String url;
- private String []key;
- private String []value;
- private String []jsonKey;
- private String jsonName;
- private String []array;
- ArrayList<HashMap<String, Object>> list;
- public HttpThread(Context context,ProgressDialog proDialog){
- this.context=context;
- this.proDialog=proDialog;
- }
- @Override
- public void run(){
- Message msg = handler.obtainMessage();
- HttpPostRequest post=new HttpPostRequest();
- int res=post.requestHttp(url, key, value);
- String webContent=post.getWebContext();
- msg.what=res;
- if(res==1){
- //解析json
- Json json=new Json();
- if(jsonName!=null)
- //解析數組型的json
- list=json.getJSONArray(webContent, jsonKey, jsonName);
- else
- //解析單個json值
- array=json.getJSON(webContent, jsonKey);
- }
- handler.sendMessage(msg);
- }
- private Handler handler = new Handler() {
- // TODO Auto-generated constructor stub
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- super.handleMessage(msg);
- int what=msg.what;
- Http_Status_Tips status=new Http_Status_Tips();
- //返回成功資料時
- if(what==1){
- //處理數組型json
- if(list!=null){
- int size=list.size();
- String result="";
- for(int i=0;i<size;i++){
- int s=jsonKey.length;
- //迭代jsonKey數組值
- for(int j=0;j<s;j++){
- result+=jsonKey[j]+":"+list.get(i).get(jsonKey[j])+"\n";
- }
- result+="\n";
- }
- Toast.makeText(context, result, Toast.LENGTH_LONG).show();
- }
- //處理單個字元json
- if(array!=null){
- int arraySize=array.length;
- String rs="";
- for(int k=0;k<arraySize;k++){
- rs+=jsonKey[k]+":"+array[k]+"\n";
- }
- Toast.makeText(context, rs, Toast.LENGTH_LONG).show();
- }
- }
- //根據伺服器端返回資料,自訂提示
- else if(what==2){
- status.setTips("自訂提示2");
- }//根據伺服器端返回資料,自訂提示
- else if(what==3){
- status.setTips("自訂提示3");
- }
- status.ShowHttpStatusTips(what, context,proDialog);
- }
- };
- //activity介面傳遞的參數
- public String getUrl() {
- return url;
- }
- public void setUrl(String url) {
- this.url = url;
- }
- 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;
- }
- public String[] getJsonKey() {
- return jsonKey;
- }
- public void setJsonKey(String[] jsonKey) {
- this.jsonKey = jsonKey;
- }
- public String getJsonName() {
- return jsonName;
- }
- public void setJsonName(String jsonName) {
- this.jsonName = jsonName;
- }
- }
複製代碼 6.activity傳遞並調用線程處理方法 activity介面中調用HttpThread的方法,主要實現數值參數的傳遞,並返回具體的數組。通過兩個按鈕擷取不同類型的json資料對象,擷取伺服器端資料的主要方法採用Toast顯示,-1。 HttpPostActivity.java源碼
- package com.httppost.main;
- import android.app.Activity;
- import android.app.ProgressDialog;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- public class HttpPostActivity extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- Button jsonBtn = (Button) findViewById(R.id.get_array_json);
- jsonBtn.setOnClickListener(jsonClick);
- Button listBtn = (Button) findViewById(R.id.get_list_json);
- listBtn.setOnClickListener(listClick);
- }
- //擷取單個json封裝的資料
- OnClickListener jsonClick = new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- ProgressDialog proDialog = ProgressDialog.show(v.getContext(), "",
- "正在擷取資料……", true, true);
- HttpThread jsonThread = new HttpThread(v.getContext(), proDialog);
- String url = "http://10.0.2.2/json/json_1.php";
- // url傳遞參數
- String[] key = { "type" };
- String[] value = { "0" };
- // php頁面返回的json鍵
- String[] jsonKey = { "id", "username", "lat", "lon","type" };
- //傳遞相應的參數
- jsonThread.setUrl(url);
- jsonThread.setKey(key);
- jsonThread.setValue(value);
- jsonThread.setJsonKey(jsonKey);
- jsonThread.start();
- }
- };
- //擷取帶數群組類型的封裝
- OnClickListener listClick = new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- ProgressDialog proDialog = ProgressDialog.show(v.getContext(), "",
- "正在擷取資料……", true, true);
- HttpThread jsonThread = new HttpThread(v.getContext(), proDialog);
- String url = "http://10.0.2.2/json/json_2.php";
- // url傳遞參數
- String[] key = { "type" };
- String[] value = { "1" };
- // php頁面返回的json鍵
- String[] jsonKey = { "id", "username", "lat", "lon","type" };
- String jsonName="json_2";
- //傳遞相應的參數
- jsonThread.setUrl(url);
- jsonThread.setKey(key);
- jsonThread.setValue(value);
- jsonThread.setJsonName(jsonName);
- jsonThread.setJsonKey(jsonKey);
- jsonThread.start();
- }
- };
- }
複製代碼 布局檔案 main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_margin="12dip"
- android:textSize="18dip"
- android:gravity="center_horizontal"
- android:text="post請求擷取json資料" />
- <Button android:id="@+id/get_array_json"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="18dip"
- android:text="擷取json資料" />
- <Button android:id="@+id/get_list_json"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="18dip"
- android:text="擷取數組型json資料" />
- </LinearLayout>
複製代碼 AndroidManifest.xml加入網路存取權限
- <!-- 網路存取權限 -->
- <uses-permission android:name="android.permission.INTERNET" />
複製代碼 2012-5-7 15:49 上傳下載附件 (33.08 KB) 圖-1 顯示擷取json資料 |