一、传输字符串数据
在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); //[email protected] 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()通知进行更新操作。
效果图: