Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android之客戶端從服務端解析數據及上傳與反饋數據

android之客戶端從服務端解析數據及上傳與反饋數據

編輯:關於Android編程

1、json從服務端解析服務端數據

客戶端的運行結果本來是這樣的

[{id:1,title:"馬雲",publishTime:Sat May 14 15:31:11 CST2016},{id:1,title:"李彥宏",publishTime:SatMay 14 15:31:11 CST 2016},{id:1,title:"李嘉誠",publishTime:Sat May 14 15:31:11 CST 2016}]

,為了方便解析我們把他先改成這樣

[{id:1,title:"馬雲",publishTime:1463209359065},{id:1,title:"李彥宏",publishTime:1463209359065},{id:1,title:"李嘉誠",publishTime:1463209359065}]

,在客戶端的時候通過json解析成時間就ok了

 

首先要讓服務端有這些數據

sdaoimp=new ServiceDaoImp();
		ListnLists=sdaoimp.getAllNews();//獲取集合對象
		StringBuilder stringBuilder=new StringBuilder();//遍歷所有對象
		stringBuilder.append('[');
		for (News news : nLists) {
			stringBuilder.append("{");
			stringBuilder.append("id:").append(news.getId()).append(",");
			stringBuilder.append("title:\"").append(news.getTitle()).append("\",");
			stringBuilder.append("publishTime:").append(news.getPublishTime());
			//通過getTime()將時間改為長整形,到客戶端再改回來
			stringBuilder.append("},");
		}
		//[{"id:1","title:馬雲","publishTime:06-25"},{"id:1","title:李彥宏","publishTime:06-26"},{"id:1","title:李嘉誠","publishTime:06-27"}]
		stringBuilder.deleteCharAt(stringBuilder.length()-1);
		stringBuilder.append(']');
		//作為屬性的值存放
		request.setAttribute("json", stringBuilder);
		//response.sendRedirect("json.jsp");
		request.getRequestDispatcher("json.jsp").forward(request, response);

這裡我們用了StringBulider,通常情況下StringBuilder >StringBuffer >String

String 字符串常量
StringBuffer 字符串變量(線程安全)
StringBuilder 字符串變量(非線程安全)

好了接下來我們看一下客戶端的編碼

Service.java

 

package com.json.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.json.entity.News;

public class Service {
	private Handler mhanHandler=new Handler();
	
	public Service(Handler mhanHandler) {
		super();
		this.mhanHandler = mhanHandler;
	}

	public  void getAll() {//由於此時將集合放進message中,就不需要返回值為List
		 
		 
		 new Thread(new Runnable() {
			 String url = "http://localhost:8080/JsonXmlService/JsonServlet";
			@Override
			public void run() {
				// TODO Auto-generated method stub
				List newsList=null;
				try {
					HttpURLConnection conn = (HttpURLConnection) new URL(url)
							.openConnection();
					conn.setReadTimeout(5000);
					conn.setRequestMethod("GET");
					if (conn.getResponseCode() == 200) {
						// 當請求碼為200的時候表示網絡服務連接成功
						// 將字節流轉換成集合或字符串

						InputStream inputStream = conn.getInputStream();
		                       newsList=parserJson(inputStream);
		                       if (newsList.size()>0) {//這裡最好先判斷一下
		                    	   Message msg=new Message();
		                    	   msg.obj=newsList;
		                    	   msg.what=0x12;
		                    	   mhanHandler.sendMessage(msg);
		                    	   //將集合封裝在message中並通過handler發送出去
								
							}
					}
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ProtocolException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
	
	}

	// 自定義一個方法將流轉換成字節數組
	public byte[] costom(InputStream is) {
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		byte[] buffer=new byte[1024];//創建一個字節緩沖區
		int length=0;
		while (buffer.length!=-1) {
			try {
				baos.write(buffer);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return baos.toByteArray();//返回baos,由於方法的返回值是byte[]類型,所以通過toByteArray()方法進行轉換一下
	}
//將字節數組轉換成對象封裝在News對象中。,並插入集合中
	public List parserJson(InputStream is) {
		List lists=new ArrayList();
		byte[] byteJson=costom(is);
		String strJson=new String(byteJson);//由於不能通過字符串(沒有帶流參數的構造方法,但有帶byte參數的構造方法)將流
		//轉換成字符串,這裡我們通過字節,先將流轉換成byte字節數組,再轉換成字符串
		
		try {
			JSONArray jsonArray=new JSONArray(strJson);
			 
			for (int i = 0; i < jsonArray.length(); i++) {
				JSONObject jsonObject=new JSONObject();
				int id=jsonObject.getInt("id");
				String title=jsonObject.getString("title");
				Date time=new Date(jsonObject.getLong("publishTime"));//由於沒有Date的類型可獲得
				//所以創建一個date對象將字符串轉換成Date對象
				//封裝對象
				News news=new News(id, title, time);
				//將對象添加到集合中
				lists.add(news);
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return lists;
	}
}
由於網絡訪問一般要在線程中實現,所以這裡我使用了handler線程來通過網絡獲取下面集合中獲取到的數據
這裡我們需要處理的是基本數據類型,那麼我們如何將流轉換成字符串呢?

 

流→字節數組→字符串,不能通過流直接到字符串,首先這裡自定義一個custom方法,返回值為字節數組,而又通過

String strJson=new String(byteJson);將字節轉換為字符串
由於時間沒有辦法直接通過json獲取到,所以我們在服務端的時候做成了長整形,而這裡我們獲取長整形,再強轉為Date類型就又可以顯示具體的時間了

 

接下來進行界面數據綁定,通過 message獲取service.java傳遞過來的值,並通過SimpleAdapter實現界面數據的綁定

JsonXmlActivity.java

 

package com.json.activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.json.entity.News;
import com.json.service.Service;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class JsonXmlActivity extends Activity {
	/** Called when the activity is first created. */
	List newsList=null;
	private ListView lv;
	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what == 0x12) {
				 newsList = (List) msg.obj;//取到傳遞過來的值,傳遞過來的是個集合,所以獲取到的值要放在集合中
			}
		};
	};
//通過service.java獲取傳遞過來的值,並通過SimpleAdapter實現界面數據的綁定
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		lv = (ListView) findViewById(R.id.listView1);
		Service service = new Service(handler);// 參數為上面的handler對象
		service.getAll();// 只有調用這個方法上面的Handler才能夠獲取到數據
	}

	private void getData() {
		List> datalist = new ArrayList>();

		for (com.json.entity.News news : newsList) {
			Map map = new HashMap();
			map.put("id", news.getId());// 此處通過map將SimpleAdapter的values與Service中獲取的標簽內容進行綁定
			map.put("title", news.getTitle());
			map.put("time", news.getPublishTime());
			datalist.add(map);
		}
		SimpleAdapter adapter = new SimpleAdapter(this, datalist,
				R.layout.test, new String[] { "id", "title", "time" },
				new int[] { R.id.id, R.id.id, R.id.id });
		lv.setAdapter(adapter);

	}
}

這裡一定要調用getAll()這個方法,只有調用這個方法上面的Handler才能夠獲取到數據傳遞過來的數據

 

2、pull從服務端解析服務端數據

在android系統中,很多資源文件中,很多都是xml格式,在android系統中解析這些xml的方式,是使用pul解析器進行解析的,它和sax解析一樣(個人感覺要比sax簡單點),也是采用事件驅動進行解析的,當pull解析器,開始解析之後,我們可以調用它的next()方法,來獲取下一個解析事件(就是開始文檔,結束文檔,開始標簽,結束標簽),當處於某個元素時可以調用XmlPullParser的getAttributte()方法來獲取屬性的值,也可調用它的nextText()獲取本節點的值。

接下來進行代碼示例

首先是服務端集合對象中要添加數據

 

	public List getAll() {
		// TODO Auto-generated method stub
		List nLists=new ArrayList();
		News news1=new News(1, "英雄聯盟", new Date(System.currentTimeMillis()));
		News news2=new News(2, "穿越火線", new Date(System.currentTimeMillis()));
		News news3=new News(3, "刀塔", new Date(System.currentTimeMillis()));
		nLists.add(news1);
		nLists.add(news2);
		nLists.add(news3);
		return nLists;
	}
這裡很簡單就不多說了,接下來就是Servlet部分

 

 

List newsList=nImp.getAll();
       request.setAttribute("newsList", newsList);
       request.getRequestDispatcher("/a.jsp").forward(request, response);

注意獲取jsp頁面的連接,而a.jsp

 

 


  
     
     ${new.data}
     
  
  
服務端沒什麼可說的,接下來我們看一下客戶端
NewsService.java

 

 

package edu.service;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;

import android.util.Xml;

import edu.entity.News;

public class NewsService {
	// 連接服務器
	public static List getlistNews() {

		String path = "http://172.20.58.104:8080/XmlService/XmlServlet";
		List newsList = null;

		try {
			HttpURLConnection conn = (HttpURLConnection) new URL(path)
					.openConnection();

			conn.setConnectTimeout(5000);
			conn.setRequestMethod("GET");

			if (conn.getResponseCode() == 200) {
				// 正常連接服務器
				try {
					InputStream xml = conn.getInputStream();
					// 經過解析轉換成集合對象
					newsList = pullParserxml(xml);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return newsList;
	}

	// 自定義方法,利用pull解析xml
	public static List pullParserxml(InputStream is) throws Exception {
		List list = null;
		News news = null;
		XmlPullParser pullParser = Xml.newPullParser();// pull解析器
		pullParser.setInput(is, "utf-8");
		int envent = pullParser.getEventType();

		while (envent != XmlPullParser.END_DOCUMENT) {
			switch (envent) {
			case XmlPullParser.START_DOCUMENT:
				list = new ArrayList();

				break;
			case XmlPullParser.START_TAG:
				if ("news".equals(pullParser.getName())) {
					news = new News();
					int id = new Integer(pullParser.getAttributeValue(0));
//開始標簽的內容從0開始
						//記住此處是getAttributeValues不是getAttributeName
					news.setId(id);

				}
				if ("title".equals(pullParser.getName())) {
//					String title = pullParser.nextText();
//					news.setTitle(title);
					news.setTitle(pullParser.nextText());
				}
				if ("data".equals(pullParser.getName())) {
					String time = pullParser.nextText();
//					SimpleDateFormat sdf = new SimpleDateFormat("yyyy--MM--dd");
//					news.setTime(sdf.parse(time));
					news.setTime(time);

				}

				break;
			case XmlPullParser.END_TAG:
				if ("news".equals(pullParser.getName())) {
					list.add(news);
					news = null;

				}

				break;

		
			}
			envent = pullParser.next();

		}

		return list;

	}
}

 


這裡的path中的8686根據個人電腦的端口號而定,默認是8080。當請求碼為200的時候表示網絡服務連接成功

 

ListXmlActivity.java

 

package edu.abc;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import edu.entity.News;
import edu.service.NewsService;

import android.app.ListActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.SimpleAdapter;

public class ListXmlActivity extends ListActivity {
	/** Called when the activity is first created. */
	public static final String TAG = "ListXmlActivity";
	List> data = null;
	SimpleAdapter adapter = null;
	Handler handler = new  Handler(){

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			if (msg.what == 0x123) {
				 adapter = new SimpleAdapter(ListXmlActivity.this, data, R.layout.test,
							new String[] { "id", "title", "data" }, new int[] { R.id.id,
									R.id.title, R.id.time });
				 setListAdapter(adapter);
			}
		}
	};
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		 setContentView(R.layout.main);
		 new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				super.run();
				data = getData();
				handler.sendEmptyMessage(0x123);
			}
		 }.start();
	}
	public List> getData() {
		
		List>	list = new ArrayList>();
		List newsList = NewsService.getlistNews();
		for (News news : newsList) {
			HashMap map = new HashMap();
			map.put("id", news.getId());
			map.put("title", news.getTitle());
			map.put("data", news.getTime());
			
			
			list.add(map);
			
		}
		
		return list;
	}
}
此處通過map將SimpleAdapter的values與NewService中獲取的標簽內容進行綁定
\

 

3、客戶端與服務端的互相通信

服務端不僅可以獲取客戶端發過來的數據,也可反饋給客戶端數據,那麼我們先看一下服務端的Servlet代碼

 

String name=(String) request.getParameter("name");
		String pass=(String) request.getParameter("pass");
		System.out.println("My Name:"+name);
		System.out.println("My Pass:"+pass);
		//回饋數據
		OutputStream os=response.getOutputStream();
		 
		String ss="Get successfully,this is the back!";
		os.write(ss.getBytes());//轉換成字節讀取
接下來看一下客戶端的代碼

 

Service.java

 

package com.up.activity;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import android.os.Handler;
import android.os.Message;

public class Service {
	String path = "http://172.20.52.25:8080/UpService/ResceviceServlet";
	String name, pass;
	Handler handler;

	public Service(String name, String pass, Handler handler) {
		super();
		this.name = name;
		this.pass = pass;
		this.handler = handler;

	}

	public void setMsg() {// 講參數寫在上面的構造方法中

		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				StringBuilder sb = new StringBuilder(path);
				sb.append("?");

				Map map = new HashMap();
				map.put("name", name);
				map.put("pass", pass);
				 
				
				
				if (map != null && !map.isEmpty()) {//此處之循環一次
					for (Map.Entry damap : map.entrySet()) {
						sb.append(damap.getKey()).append("=");
						sb.append(damap.getValue());						
						sb.append("&");
						// http://172.20.58.109:8686/UpService/ResceviceServlet?name=***&pass=***&
					}
					sb.deleteCharAt(sb.length() - 1);// 多余一個&去掉
					// http://172.20.58.109:8686/UpService/ResceviceServlet?name=***&pass=***
				}

				try {
					HttpURLConnection conn = (HttpURLConnection) new URL(sb.toString())//前面已經將不完整的path添加到StringBulider
							.openConnection();
					conn.setReadTimeout(2000);//鏈接超市
					conn.setRequestMethod("POST");
					conn.setRequestProperty("Content-Type",
							"application/x-www-form-urlencoded");
					// 請求屬性,可以把地址的?與&之間的屬性隔開
					conn.setDoOutput(true);// 設置允許輸出流輸出內容

					byte[] data = sb.toString().getBytes();// 將字符串轉換成字節數組,因為前面的字符串存儲在StringBuilder裡,所以要轉換成字符串通過toString
					OutputStream os = conn.getOutputStream();
					os.write(data);// 數據上傳是輸出流,是write寫數據
					os.flush();
					// 等待網絡請求的響應
					if (conn.getResponseCode() == 200) {
						InputStream is = conn.getInputStream();// 數據下載回應是輸入流,是read讀數據
						ByteArrayOutputStream baos = new ByteArrayOutputStream();
						byte[] size = new byte[1024];
						int length = 0;
						while ((length = is.read(size)) != -1) {
							baos.write(size);//將讀的內容寫入字節中

						}
						 
						Message msg = new Message();
						msg.what = 12;
						msg.obj=baos.toString();//轉換成字符串
						handler.sendMessage(msg);// 注意上面構造handler的使用
					}
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			// 連接服務器

		}).start();

	}

}
要說的內容都在注釋裡面做了詳細的介紹,接下來看一下我們在主線程中要做的事情

 

UpToServiceActivity.java

 

package com.up.activity;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class UpToServiceActivity extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
	private EditText etName,etPass;
	private Button bt;
    Handler handler=new Handler(){
    	
    	public void handleMessage(android.os.Message msg) {
    		if (msg.what==12) {
    			String sss=(String)msg.obj;
				Toast.makeText(UpToServiceActivity.this, sss, Toast.LENGTH_LONG).show();
			}
    	};
    };
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        etName=(EditText) findViewById(R.id.etName);
        etPass=(EditText) findViewById(R.id.etPass);
        bt=(Button) findViewById(R.id.bt);
        bt.setOnClickListener(this);
       
    }


	@Override
	public void onClick(View arg0) {
		// TODO Auto-generated method stub
		String name=etName.getText().toString().trim();
		String pass=etPass.getText().toString().trim();
		//將網絡請求放在主線程中實現
		Service s=new Service(name, pass, handler);//此時有個handler參數,所以上面要創建一個handler
		s.setMsg();
	}
}

 

 

這裡我在服務端設置了一段文字

Get successfully,this is the back!
以方便觀察是否成功,下面就是客戶端與服務端的效果圖

 

\\

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved