一、傳輸字符串數據
在Android中HttpURLConnection傳輸數據是必不可少的,我們繼續在“AsyncTask(異步任務)”案例的基礎上添加。
案例:
首先我們做一個jsp的服務端,文件名為test1.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><% String a = "1234567"; String lastId = request.getParameter("lastId"); if (lastId==null){ lastId = "0"; } int int_a = Integer.valueOf(a); int int_lastId = Integer.valueOf(lastId); out.print(int_a + int_lastId); %>
1、定義一個String類型的變量用來返回給客戶端的字符串"1234567"。
2、通過客戶端的lastId的參數值來判斷是否請求。
3、通過out.print返回數據給客戶端。
MainActivity.java文件:
public class MainActivity extends Activity { private SimpleAdapter sa; private Button btn; private TextView tv; private List<Userinfos> list=new ArrayList<Userinfos>(); private List<Map<String,Object> > messageList2 = new ArrayList<Map<String,Object> >(); private BaseAdapter adapter; private ListView lv; private Runnable doInBackground1; private Runnable doInBackground2; private Runnable doInBackground3; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { //這里是UI主線程 super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //gdnf_class@126.com for (int i = 0; i < 5; i++) { Userinfos u = new Userinfos(); u.setName("小明"+i); u.setSex("男"+i); list.add(u); } lv=(ListView)this.findViewById(R.id.listView1); tv=(TextView)findViewById(R.id.textView1); btn=(Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener(){ //模擬數據訪問產生數據 @Override public void onClick(View v) { // TODO Auto-generated method stub Take tk=new Take(MainActivity.this);//同步任務 tk.execute(list,adapter);//參數是傳給doInBackground }}); adapter=new BaseAdapter(){ @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub LayoutInflater inflater = MainActivity.this.getLayoutInflater(); View vw; if(convertView==null) { Log.i("View","創建對象"); vw = inflater.inflate(R.layout.item, null); } else { vw=convertView; } TextView tv_username = (TextView)vw.findViewById(R.id.username); TextView tv_sex = (TextView)vw.findViewById(R.id.sex); tv_username.setText(list.get(position).getName()); tv_sex.setText(list.get(position).getSex()); return vw; }}; lv.setAdapter(adapter); @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
通過 Button的點擊事件,傳參數是傳給doInBackground,進入客戶端的后台進行操作。
Take.java文件:
public class Take extends AsyncTask{ private MainActivity activity; private BaseAdapter adapter; private List<Userinfos> list=new ArrayList<Userinfos>(); private static final String URL_STR="http://android2017.duapp.com/test1.jsp"; private String errorMessage = ""; private String lastId = "5"; protected Take(MainActivity activity) { this.activity=activity; } //后台運行(數據庫,藍牙,互聯網) @Override protected Object doInBackground(Object... params) { list = (List<Userinfos>) params[0]; adapter = (BaseAdapter) params[1]; try { //發送數據 注釋二URL ul = new URL(URL_STR); HttpURLConnection http = (HttpURLConnection) ul.openConnection(); // 對連接進行配置 http.setDoInput(true);// 輸入 http.setDoOutput(true);// 輸出 http.setRequestMethod("POST"); // 防止讀取臟數據 http.setUseCaches(false); // 獲取一個輸出流 OutputStream os = http.getOutputStream(); // DataOutputStream數據輸出流 DataOutputStream str = new DataOutputStream(os); str.writeBytes("lastId=" + URLEncoder.encode(lastId, "UTF-8"));// 編碼 str.flush();// 刷新,將數據發到緩沖區。 str.close();if (http.getResponseCode() == 200) { //讀取數據 // 輸入流 注釋二InputStream inst = http.getInputStream();// // reader(注意UTF-8讀) InputStreamReader isr = new InputStreamReader(inst, "UTF-8"); // 緩沖區,防止讀死 BufferedReader br = new BufferedReader(isr); String ReadOneline = null; // 多行數據時,減少不斷創建String對象 StringBuffer sb = new StringBuffer(); while ((ReadOneline = br.readLine()) != null) { sb.append(ReadOneline); } inst.close(); isr.close(); br.close(); http.disconnect(); return sb.toString(); } else { errorMessage = "服務器繁忙,請稍后再試(" + http.getResponseCode() + ")"; return "errorserver"; } } catch (Exception e) { // TODO Auto-generated catch block errorMessage = e.getMessage(); return "errorclient"; } } //准備 @Override protected void onPreExecute() { Toast.makeText(activity, "今晚有約", Toast.LENGTH_SHORT).show(); super.onPreExecute(); } //做完后執行 @Override protected void onPostExecute(Object result) { // result的值為doInBackground方法的返回值 String tr = result.toString(); Log.i("d",""+tr); TextView tv = (TextView) activity.findViewById(R.id.textView1); /* tv.setText("訪問完成!"+tr); */ //空指針 if ("errorclient".equals(tr)) { if (errorMessage.indexOf("No add") != -1) { tv.setText("網絡不通"); } else { tv.setText("訪問網絡時其它異常:" + errorMessage); } } else if ("errorserver".equals(tr)) { tv.setText(errorMessage); } else { tv.setText(tr); } } //分步完成 //onProgressUpdate更新進度條 @Override protected void onProgressUpdate(Object... values) { // TODO Auto-generated method stub Log.i("dd", "進入分步"); int bar = Integer.parseInt(values[0].toString()); bar = (bar + 1) * 20; ProgressBar progressBar = (ProgressBar) activity .findViewById(R.id.progressBar1); progressBar.setProgress(bar); adapter.notifyDataSetChanged(); // 這里是UI主線程 } }
1、URL_STR是我們發布服務的地址。
2、我們通過地址加上參數lastid
3、通過HttpURLConnection等相關設置連接服務發起請求。
4、OutputStream等流來傳遞和讀取數據(注:由於上一章詳解過在這就不多說)
5、通過onPostExecute方法將讀取到的數據賦值給textView1
二、下載圖片:
互聯網傳遞二進制流
我們添加一take2img的類同樣繼承於AsyncTask,進行相關的操作。
take2img.java文件:
//下載圖片 private MainActivity activity; private BaseAdapter adapter; private static final String URL_img_STR = "http://cms-bucket.nosdn.127.net/c476803813014a5fa865f22c0faa340320161208080029.jpeg"; private String errorMessage = ""; private Bitmap bitmap; protected Take2img(MainActivity activity) { this.activity=activity; } @Override protected Object doInBackground(Object... params) { try { URL ul=new URL(URL_img_STR); Log.i("d","dddddd2"); HttpURLConnection http = (HttpURLConnection)ul.openConnection();//創建連接對象 // 對連接對象進行配置 http.setDoInput(true);// 輸入 http.setDoOutput(false);// 輸出 http.setRequestMethod("GET"); if (http.getResponseCode() == 200) { InputStream inst=http.getInputStream(); bitmap= BitmapFactory.decodeStream(inst); inst.close(); http.disconnect(); return "ere"; } else { errorMessage = "服務器繁忙,請稍后再試(" + http.getResponseCode() + ")"; return "errorserver"; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } //做完后執行 @Override protected void onPostExecute(Object result) { // result的值為doInBackground方法的返回值 String tr = result.toString(); TextView tv = (TextView) activity.findViewById(R.id.textView1); /* tv.setText("訪問完成!"+tr); */ if ("errorclient".equals(tr)) { if (errorMessage.indexOf("No add") != -1) { tv.setText("網絡不通"); } else { tv.setText("訪問網絡時其它異常:" + errorMessage); } } else if ("errorserver".equals(tr)) { tv.setText(errorMessage); } else { tv.setText(tr); ImageView img=(ImageView) activity.findViewById(R.id.imageView1); img.setImageBitmap(bitmap); } super.onPostExecute(result); } }
1、URL_img_STR 網絡圖片路徑。
2、由於是讀取圖片所以設置輸出為false,GET請求。
3、通過HttpURLConnection等相關設置連接服務發起請求。
4、設置Bitmap變量緩存圖片。
5、通過onPostExecute方法設置imageView1圖片。
效果圖:
三、傳遞集合(JSON格式)
首先我們將test1.jsp修改一下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.util.*,com.fasterxml.jackson.databind.*"%><% //解決中文問題,以及緩存問題 //http1.1瀏覽器 response.setHeader("Cache-Control", "no-cache"); //http1.0瀏覽器 response.setHeader("Prama", "no-cache"); //提醒過期1.0,1.1都支持 response.setDateHeader("Expires", 0); //控制輸出流 response.setCharacterEncoding("UTF-8"); //告之瀏覽器 response.setHeader("content-type","text/json;charset=UTF-8"); //保證獲取過來的參數為UTF8,否則亂碼 request.setCharacterEncoding("utf-8"); String a = "1234567"; String lastId = request.getParameter("lastId"); if (lastId==null){ lastId = "3"; } int count = Integer.valueOf(lastId); class User { private String username; private String sex; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } } List<User> userList = new ArrayList<User>(); for(int i=0;i<count;i++){ User u = new User(); u.setUsername("明明"+i); u.setSex("女"+i); userList.add(u); } ObjectMapper mapper = new ObjectMapper(); String jsonStr = mapper.writeValueAsString(userList); out.print(jsonStr); /* int int_a = Integer.valueOf(a); int int_lastId = Integer.valueOf(lastId); out.print(int_a + int_lastId); */ %>
1、創建一個User類,添加了username,sex兩個字段,通過List<user>對該類賦值添加數據。
2、設置了一個count變量通過 request.getParameter("lastId")方法獲取客戶端傳遞過來的lastId參數值。
3、同過map 的writeValueAsString方法轉換成JSON格式。
4、通過out.print()方法返回給客戶端。
take.java文件:
public class Take extends AsyncTask{ private MainActivity activity; private BaseAdapter adapter; private List<Userinfos> list=new ArrayList<Userinfos>(); private static final String URL_STR="http://android2017.duapp.com/test1.jsp"; private String errorMessage = ""; private String lastId = "5"; protected Take(MainActivity activity) { this.activity=activity; } //后台運行(數據庫,藍牙,互聯網) @Override protected Object doInBackground(Object... params) { list = (List<Userinfos>) params[0]; adapter = (BaseAdapter) params[1]; try { URL ul = new URL(URL_STR); HttpURLConnection http = (HttpURLConnection) ul.openConnection(); // 對連接進行配置 http.setDoInput(true);// 輸入 http.setDoOutput(true);// 輸出 http.setRequestMethod("POST"); // 防止讀取臟數據 http.setUseCaches(false); // 獲取一個輸出流, OutputStream os = http.getOutputStream(); // DataOutputStream數據輸出流 DataOutputStream str = new DataOutputStream(os); str.writeBytes("lastId=" + URLEncoder.encode(lastId, "UTF-8"));// 編碼 str.flush();// 刷新,將數據發到緩沖區。 str.close(); if (http.getResponseCode() == 200) { Log.i("狀態","200"); //讀取數據 // 輸入流 InputStream inst = http.getInputStream(); // reader(注意UTF-8讀) InputStreamReader isr = new InputStreamReader(inst, "UTF-8"); // 緩沖區,防止讀死 BufferedReader br = new BufferedReader(isr); String ReadOneline = null; // 多行數據時,減少不斷創建String對象 StringBuffer sb = new StringBuffer(); while ((ReadOneline = br.readLine()) != null) { sb.append(ReadOneline); } //讀取JSON數據 list.clear(); JSONArray jso = new JSONArray(sb.toString()); for (int i = 0; i < jso.length(); i++) { JSONObject jo = (JSONObject) jso.get(i); Userinfos us=new Userinfos(); us.setName(jo.getString("username")); us.setSex(jo.getString("sex") ); list.add(us); } inst.close(); isr.close(); br.close(); http.disconnect(); return sb.toString(); } else { errorMessage = "服務器繁忙,請稍后再試(" + http.getResponseCode() + ")"; return "errorserver"; } } catch (Exception e) { // TODO Auto-generated catch block errorMessage = e.getMessage(); return "errorclient"; } } //做完后執行 @Override protected void onPostExecute(Object result) { // result的值為doInBackground方法的返回值 String tr = result.toString(); Log.i("d",""+tr); TextView tv = (TextView) activity.findViewById(R.id.textView1); /* tv.setText("訪問完成!"+tr); */ //空指針 if ("errorclient".equals(tr)) { if (errorMessage.indexOf("No add") != -1) { tv.setText("網絡不通"); } else { tv.setText("訪問網絡時其它異常:" + errorMessage); } } else if ("errorserver".equals(tr)) { tv.setText(errorMessage); } else { tv.setText(tr); adapter.notifyDataSetChanged(); } } }
1、URL_STR服務端網站地址。
2、通過HttpURLConnection等相關設置連接服務發起請求。
3、ReadOneline讀取數據,JSONArray轉換數據通過循環獲取數據
4、通過 adapter.notifyDataSetChanged()通知進行更新操作。
效果圖: