android网络编程

  • 通过浏览器查看Tomcat服务器中的图片

1、将要查看的图片dd.jpg存放到Tomcat的webapps/ROOT/目录下

2、启动服务器

3、打开浏览器,输入:http://172.23.7.240:8080/dd.jpg

  • 网络图片查看器(带有缓存功能)
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:id="@+id/activity_main"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:paddingBottom="@dimen/activity_vertical_margin"
 8     android:paddingLeft="@dimen/activity_horizontal_margin"
 9     android:paddingRight="@dimen/activity_horizontal_margin"
10     android:paddingTop="@dimen/activity_vertical_margin"
11     tools:context="com.ahu.lichang.scannetpicture.MainActivity">
12 
13     <Button
14         android:onClick="scan"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         android:text="查看网络图片(带缓存功能)" />
18     <ImageView
19         android:id="@+id/iv"
20         android:layout_width="wrap_content"
21         android:layout_height="wrap_content" />
22 </RelativeLayout>
View Code

  1、主线程不能被阻塞,所有很多的耗时操作都不能放在主线程中运行,否则会发生ANR异常(application not response)。

  2、刷新UI界面的代码只能运行在主线程中,运行在子线程中是没有任何效果的。     如果需要在子线程总刷新UI,那么就要使用消息队列机制。

  1 package com.ahu.lichang.scannetpicture;
  2 
  3 import android.app.Activity;
  4 import android.graphics.Bitmap;
  5 import android.graphics.BitmapFactory;
  6 import android.os.Bundle;
  7 import android.os.Handler;
  8 import android.os.Message;
  9 import android.view.View;
 10 import android.widget.ImageView;
 11 import android.widget.Toast;
 12 
 13 import java.io.File;
 14 import java.io.FileOutputStream;
 15 import java.io.InputStream;
 16 import java.net.HttpURLConnection;
 17 import java.net.URL;
 18 
 19 public class MainActivity extends Activity {
 20     private ImageView iv;
 21     Handler handler = new Handler(){
 22         //此方法在主线程中调用,用来刷新UI
 23         @Override
 24         public void handleMessage(Message msg) {
 25             switch (msg.what){
 26                 case 1:
 27                     iv.setImageBitmap((Bitmap) msg.obj);
 28                     break;
 29                 case 0:
 30                     Toast.makeText(MainActivity.this,"请求失败!",Toast.LENGTH_SHORT).show();
 31                     break;
 32             }
 33         }
 34     };
 35     @Override
 36     protected void onCreate(Bundle savedInstanceState) {
 37         super.onCreate(savedInstanceState);
 38         setContentView(R.layout.activity_main);
 39         iv = (ImageView) findViewById(R.id.iv);
 40     }
 41 
 42     /**
 43      * 点击按钮,查看网络图片(有缓存功能)
 44      * @param v
 45      */
 46     public void scan(View v){
 47         //图片的地址
 48         final String path = "http://172.23.4.91:8080/dd.jpg";
 49         final File file = new File(getCacheDir(),getFileName(path));
 50         //判断是否有图片缓存
 51         if(file.exists()){
 52             System.out.println("从缓存中获取。。。");
 53             //有缓存,直接从缓存中获取
 54             Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
 55             iv.setImageBitmap(bm);
 56         }else{
 57             System.out.println("从网络下载。。。");
 58             //没有缓存,就从网络上下载
 59             //网络下载是个耗时操作,需在线程中完成
 60             new Thread(){
 61                 @Override
 62                 public void run() {
 63                     try {
 64                         URL url = new URL(path);
 65                         //获取连接对象,但还没建立连接
 66                         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 67                         //设置连接超时
 68                         conn.setConnectTimeout(5000);
 69                         //设置读取超时
 70                         conn.setReadTimeout(5000);
 71                         //设置请求方法,必须大写
 72                         conn.setRequestMethod("GET");
 73                         //建立连接,发送GET请求
 74                         conn.connect();
 75                         //如果响应吗为200,说明请求服务器成功
 76                         if(conn.getResponseCode() == 200){
 77                             //获取服务器响应头中的流,流中的数据就是客户端请求的数据
 78                             InputStream is = conn.getInputStream();
 79                             //读取流里的数据,并写入到本地缓存起来
 80                             FileOutputStream fos = new FileOutputStream(file);
 81                             byte[] b = new byte[1024];
 82                             int len = 0;
 83                             while((len = is.read(b)) != -1){
 84                                 fos.write(b,0,len);
 85                             }
 86                             fos.close();
 87 
 88                             Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
 89                             //发送消息
 90                             Message msg = new Message();
 91                             msg.obj = bm;
 92                             msg.what = 1;
 93                             handler.sendMessage(msg);
 94                         }else{
 95                             //请求服务器失败
 96                             Message msg = handler.obtainMessage();
 97                             msg.what = 0;
 98                             handler.sendMessage(msg);
 99                         }
100                     } catch (Exception e) {
101                         e.printStackTrace();
102                     }
103                 }
104             }.start();
105         }
106     }
107 
108     /**
109      * 根据地址,截取图片的名称
110      * @param path
111      * @return
112      */
113     private String getFileName(String path) {
114         int index = path.lastIndexOf("/");
115         return path.substring(index + 1);
116     }
117 }
View Code

  要添加权限

1     <!--添加网络权限-->
2     <uses-permission android:name="android.permission.INTERNET"/>

 

  • 消息处理机制

消息处理机制的原理:

  所有使用UI界面的操作系统,后台都运行着一个死循环,在不停地监听和接受用户发出的指令,一旦接受指令就立即执行。

  当我们的Android应用程序的进程一创建的时候,系统就给这个进程提供了一个Looper(轮询器),Looper是一个死循环,它内部维护着一个消息队列,Looper不停地从消息队列中取消息,取到消息就发送给Handler,最后Handler根据接收到的消息去修改UI。

  主线程创建时,消息队列和轮询器对象就会被创建,但是消息处理器对象,需要使用时,自行创建。

步骤:

1、在主线程中创建Handler

2、在线程中得到handler的引用,调用发送消息的方法

3、handler执行handlerMessage方法去西湖里消息,并修改UI界面

  • HTML源文件查看器
 1 package com.ahu.lichang.scanhtml;
 2 
 3 import android.os.Bundle;
 4 import android.os.Handler;
 5 import android.os.Message;
 6 import android.support.v7.app.AppCompatActivity;
 7 import android.view.View;
 8 import android.widget.TextView;
 9 
10 import java.io.ByteArrayOutputStream;
11 import java.io.InputStream;
12 import java.net.HttpURLConnection;
13 import java.net.URL;
14 
15 public class MainActivity extends AppCompatActivity {
16 
17     private TextView tv;
18     Handler handler = new Handler(){
19         @Override
20         public void handleMessage(Message msg) {
21             tv.setText((String)msg.obj);
22         }
23     };
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28         tv = (TextView) findViewById(R.id.tv);
29     }
30     public void scan(View view){
31         new Thread(){
32             @Override
33             public void run() {
34                 String path = "http://172.23.4.91:8080/baidu.html";
35                 try {
36                     URL url = new URL(path);
37                     HttpURLConnection connection = (HttpURLConnection) url.openConnection();
38                     connection.setRequestMethod("GET");
39                     connection.setConnectTimeout(5000);
40                     connection.setReadTimeout(5000);
41                     connection.connect();
42                     if(connection.getResponseCode() == 200){
43                         InputStream is = connection.getInputStream();
44                         /**
45                          * 要将字节流中的内容转换成字符串
46                          */
47                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
48                         byte[] b = new byte[1024];
49                         int len = 0;
50                         while ((len = is.read(b)) != -1){
51                             baos.write(b,0,len);
52                         }
53                         /**
54                          * 注意转换的时候乱码的处理:
55                          *          默认情况下是utf-8
56                          *          也可以手动指定码表:text = new String(baos.toByteArray(),"gb2312");
57                          */
58                         String text  = new String(baos.toByteArray());
59                         Message msg = handler.obtainMessage();
60                         msg.obj = text;
61                         handler.sendMessage(msg);
62                     }
63                 } catch (Exception e) {
64                     e.printStackTrace();
65                 }
66             }
67         }.start();
68     }
69 }
View Code

 

  • 使用GET方式向服务器端提交数据

1、把需要提交的参数组拼到URL地址的后面:http://192.168.22.136:8080/web/servlet/LoginServlet?username=123&password=1233
缺点:
  1、提交数据的长度有限制:最大长度4kb,windows中提交数据时最大长度为1kb;
  2、不安全
优点:代码简单

 1 public class MainActivity extends Activity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7     }
 8 
 9     Handler handler = new Handler(){
10         public void handleMessage(android.os.Message msg) {
11             Toast.makeText(MainActivity.this, (String)msg.obj, 0).show();
12         }
13     };
14     
15     public void click(View v){
16         EditText et_name = (EditText) findViewById(R.id.et_name);
17         EditText et_pass = (EditText) findViewById(R.id.et_pass);
18         
19         final String name = et_name.getText().toString();
20         final String pass = et_pass.getText().toString();
21         
22         Thread t = new Thread(){
23             @Override
24             public void run() {
25                 //提交的数据需要经过url编码,英文和数字编码后不变
26                 @SuppressWarnings("deprecation")
27                 String path = "http://192.168.13.13/Web2/servlet/LoginServlet?name=" + URLEncoder.encode(name) + "&pass=" + pass;
28                 
29                 try {
30                     URL url = new URL(path);
31                     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
32                     conn.setRequestMethod("GET");
33                     conn.setConnectTimeout(5000);
34                     conn.setReadTimeout(5000);
35                     
36                     if(conn.getResponseCode() == 200){
37                         InputStream is =conn.getInputStream();
38                         String text = Utils.getTextFromStream(is);
39                         
40                         Message msg = handler.obtainMessage();
41                         msg.obj = text;
42                         handler.sendMessage(msg);
43                     }
44                 } catch (Exception e) {
45                     e.printStackTrace();
46                 }
47             }
48         };
49         t.start();
50             
51     }
52 
53 }
View Code
  • 使用POST方式向服务器端提交数据(重点)

业务场景:
    1、用户登录
    2、文件上传

1、设置请求头信息POST、Content-Type、Content-Length:

  conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  //必须添加的两个请求头信息
  conn.setRequestProperty("Content-Length", data.length()+"");
  conn.setRequestMethod("POST");

2、设置把数据提交到服务器端:
  //设置允许打开post请求的流
  conn.setDoOutput(true);
  //把数据写到服务器端
  conn.getOutputStream().write(data.getBytes());

缺点:

  1、代码复杂
优点:

  1、安全;
  2、提交大量的数据

 1 public class MainActivity extends Activity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7     }
 8 
 9     Handler handler = new Handler(){
10         public void handleMessage(android.os.Message msg) {
11             Toast.makeText(MainActivity.this, (String)msg.obj, 0).show();
12         }
13     };
14     
15     public void click(View v){
16         EditText et_name = (EditText) findViewById(R.id.et_name);
17         EditText et_pass = (EditText) findViewById(R.id.et_pass);
18         
19         final String name = et_name.getText().toString();
20         final String pass = et_pass.getText().toString();
21         
22         Thread t = new Thread(){
23             @Override
24             public void run() {
25                 //提交的数据需要经过url编码,英文和数字编码后不变
26                 @SuppressWarnings("deprecation")
27                 String path = "http://192.168.13.13/Web2/servlet/LoginServlet";
28                 
29                 try {
30                     URL url = new URL(path);
31                     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
32                     conn.setRequestMethod("POST");
33                     conn.setConnectTimeout(5000);
34                     conn.setReadTimeout(5000);
35                     
36                     //拼接出要提交的数据的字符串
37                     String data = "name=" + URLEncoder.encode(name) + "&pass=" + pass;
38                     //添加post请求的两行属性
39                     conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
40                     conn.setRequestProperty("Content-Length", data.length() + "");
41                     
42                     //设置打开输出流
43                     conn.setDoOutput(true);
44                     //拿到输出流
45                     OutputStream os = conn.getOutputStream();
46                     //使用输出流往服务器提交数据
47                     os.write(data.getBytes());
48                     if(conn.getResponseCode() == 200){
49                         InputStream is = conn.getInputStream();
50                         String text = Utils.getTextFromStream(is);
51                         
52                         Message msg = handler.obtainMessage();
53                         msg.obj = text;
54                         handler.sendMessage(msg);
55                     }
56                 } catch (Exception e) {
57                     e.printStackTrace();
58                 }
59             }
60         };
61         t.start();    
62         
63     }
64 
65 }
View Code
  • HttpClient(发送GET请求和POST请求)
  1 public class MainActivity extends Activity {
  2 
  3     Handler handler = new Handler(){
  4         @Override
  5         public void handleMessage(android.os.Message msg) {
  6             Toast.makeText(MainActivity.this, (String)msg.obj, 0).show();
  7         }
  8     };
  9     @Override
 10     protected void onCreate(Bundle savedInstanceState) {
 11         super.onCreate(savedInstanceState);
 12         setContentView(R.layout.activity_main);
 13     }
 14 
 15 
 16     public void get(View v){
 17         EditText et_name = (EditText) findViewById(R.id.et_name);
 18         EditText et_pass = (EditText) findViewById(R.id.et_pass);
 19         
 20         final String name = et_name.getText().toString();
 21         final String pass = et_pass.getText().toString();
 22         
 23         Thread t = new Thread(){
 24             @Override
 25             public void run() {
 26                 String path = "http://192.168.13.13/Web/servlet/CheckLogin?name=" + URLEncoder.encode(name) + "&pass=" + pass;
 27                 //使用httpClient框架做get方式提交
 28                 //1.创建HttpClient对象
 29                 HttpClient hc = new DefaultHttpClient();
 30                 
 31                 //2.创建httpGet对象,构造方法的参数就是网址
 32                 HttpGet hg = new HttpGet(path);
 33                 
 34                 //3.使用客户端对象,把get请求对象发送出去
 35                 try {
 36                     HttpResponse hr = hc.execute(hg);
 37                     //拿到响应头中的状态行
 38                     StatusLine sl = hr.getStatusLine();
 39                     if(sl.getStatusCode() == 200){
 40                         //拿到响应头的实体
 41                         HttpEntity he = hr.getEntity();
 42                         //拿到实体中的内容,其实就是服务器返回的输入流
 43                         InputStream is = he.getContent();
 44                         String text = Utils.getTextFromStream(is);
 45                         
 46                         //发送消息,让主线程刷新ui显示text
 47                         Message msg = handler.obtainMessage();
 48                         msg.obj = text;
 49                         handler.sendMessage(msg);
 50                     }
 51                 } catch (Exception e) {
 52                     // TODO Auto-generated catch block
 53                     e.printStackTrace();
 54                 }
 55             }
 56         };
 57         t.start();
 58         
 59     }
 60     
 61     public void post(View v){
 62         EditText et_name = (EditText) findViewById(R.id.et_name);
 63         EditText et_pass = (EditText) findViewById(R.id.et_pass);
 64         
 65         final String name = et_name.getText().toString();
 66         final String pass = et_pass.getText().toString();
 67         
 68         Thread t = new Thread(){
 69             @Override
 70             public void run() {
 71                 String path = "http://192.168.13.13/Web/servlet/CheckLogin";
 72                 //1.创建客户端对象
 73                 HttpClient hc = new DefaultHttpClient();
 74                 //2.创建post请求对象
 75                 HttpPost hp = new HttpPost(path);
 76                 
 77                 //封装form表单提交的数据
 78                 BasicNameValuePair bnvp = new BasicNameValuePair("name", name);
 79                 BasicNameValuePair bnvp2 = new BasicNameValuePair("pass", pass);
 80                 List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
 81                 //把BasicNameValuePair放入集合中
 82                 parameters.add(bnvp);
 83                 parameters.add(bnvp2);
 84                 
 85                 try {
 86                     //要提交的数据都已经在集合中了,把集合传给实体对象
 87                     UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, "utf-8");
 88                     //设置post请求对象的实体,其实就是把要提交的数据封装至post请求的输出流中
 89                     hp.setEntity(entity);
 90                     //3.使用客户端发送post请求
 91                     HttpResponse hr = hc.execute(hp);
 92                     if(hr.getStatusLine().getStatusCode() == 200){
 93                         InputStream is = hr.getEntity().getContent();
 94                         String text = Utils.getTextFromStream(is);
 95                         
 96                         //发送消息,让主线程刷新ui显示text
 97                         Message msg = handler.obtainMessage();
 98                         msg.obj = text;
 99                         handler.sendMessage(msg);
100                     }
101                 } catch (Exception e) {
102                     // TODO Auto-generated catch block
103                     e.printStackTrace();
104                 }
105             }
106         };
107         t.start();
108         
109     }
110 }
View Code
  •  异步HttpClient框架(发送GET请求和发送POST请求)AsyncHttpClient
 1 public class MainActivity extends Activity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7     }
 8 
 9 
10     public void get(View v){
11         EditText et_name = (EditText) findViewById(R.id.et_name);
12         EditText et_pass = (EditText) findViewById(R.id.et_pass);
13         
14         final String name = et_name.getText().toString();
15         final String pass = et_pass.getText().toString();
16         String url = "http://192.168.13.13/Web/servlet/CheckLogin?name=" + URLEncoder.encode(name) + "&pass=" + pass;
17         //创建异步httpclient
18         AsyncHttpClient ahc = new AsyncHttpClient();
19         
20         //发送get请求提交数据
21         ahc.get(url, new MyResponseHandler());
22     }
23     
24     public void post(View v){
25         EditText et_name = (EditText) findViewById(R.id.et_name);
26         EditText et_pass = (EditText) findViewById(R.id.et_pass);
27         
28         final String name = et_name.getText().toString();
29         final String pass = et_pass.getText().toString();
30         String url = "http://192.168.13.13/Web/servlet/CheckLogin";
31         
32         //创建异步httpclient
33         AsyncHttpClient ahc = new AsyncHttpClient();
34         
35         //发送post请求提交数据
36         //把要提交的数据封装至RequestParams对象
37         RequestParams params = new RequestParams();
38         params.add("name", name);
39         params.add("pass", pass);
40         ahc.post(url, params, new MyResponseHandler());
41     }
42     
43     class MyResponseHandler extends AsyncHttpResponseHandler{
44 
45         //请求服务器成功时,此方法调用
46         @Override
47         public void onSuccess(int statusCode, Header[] headers,
48                 byte[] responseBody) {
49             Toast.makeText(MainActivity.this, new String(responseBody), 0).show();
50             
51         }
52 
53         //请求失败此方法调用
54         @Override
55         public void onFailure(int statusCode, Header[] headers,
56                 byte[] responseBody, Throwable error) {
57             Toast.makeText(MainActivity.this, "请求失败", 0).show();
58             
59         }
60         
61     }
62     
63 }
View Code

  

原文地址:https://www.cnblogs.com/ahu-lichang/p/6588467.html