总结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" />
复制代码
图-1 显示获取json数据 |