- 通过浏览器查看Tomcat服务器中的图片
1、将要查看的图片dd.jpg存放到Tomcat的webapps/ROOT/目录下
2、启动服务器
3、打开浏览器,输入:http://172.23.7.240:8080/dd.jpg
- 网络图片查看器(带有缓存功能)
1 212 13 18 22
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 path111 * @return112 */113 private String getFileName(String path) {114 int index = path.lastIndexOf("/");115 return path.substring(index + 1);116 }117 }
要添加权限
1 2
- 消息处理机制
消息处理机制的原理:
所有使用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 @Override20 public void handleMessage(Message msg) {21 tv.setText((String)msg.obj);22 }23 };24 @Override25 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 @Override33 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-856 * 也可以手动指定码表: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 }
- 使用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 @Override24 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 }
- 使用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 @Override24 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 }
- 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 Listparameters = new ArrayList (); 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 block103 e.printStackTrace();104 }105 }106 };107 t.start();108 109 }110 }
- 异步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 //创建异步httpclient18 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 //创建异步httpclient33 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 @Override47 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 @Override55 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 }