package com.ccl.getp_w_picpath; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_path; private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_path = (EditText) findViewById(R.id.et_path); iv = (ImageView) findViewById(R.id.iv); } public void getImage(View view){ String path = et_path.getText().toString().trim(); if(TextUtils.isEmpty(path)){ Toast.makeText(this, "地址不能为空", 0).show(); return; } try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); System.out.println("响应码是--"+conn.getResponseCode()); if(conn.getResponseCode()==200){ //获取服务器返回的流数据 InputStream in = conn.getInputStream(); //将返回的流数据解析成图片 Bitmap bitmap = BitmapFactory.decodeStream(in); //显示图片 iv.setImageBitmap(bitmap); in.close(); } } catch (Exception e) { e.printStackTrace(); } } }
Android模拟器版本4.1.2
异常解释:在主线程中的网络异常
原因:Android2.3版本后不允许在主线程中直接请求网络获取数据
解决方法(两种):
一:onCreate方法中加入如下代码(不推荐使用,有可能阻塞Android主线程)
if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }
二:使用Android 的handler机制,另外开启一个子线程请求网络获取数据(推荐使用)
package com.ccl.getp_w_picpath; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_path; private ImageView iv; private String path; //使用Handler更新主线程(UI线程) private Handler handler = new Handler(){ public void handleMessage(Message msg) { Bitmap bitmap = (Bitmap) msg.obj; iv.setImageBitmap(bitmap); }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_path = (EditText) findViewById(R.id.et_path); iv = (ImageView) findViewById(R.id.iv); } public void getImage(View view){ path = et_path.getText().toString().trim(); if(TextUtils.isEmpty(path)){ Toast.makeText(this, "地址不能为空", 0).show(); return; } new Thread(){ public void run(){ try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); System.out.println("响应码是--"+conn.getResponseCode()); if(conn.getResponseCode()==200){ //获取服务器返回的流数据 InputStream in = conn.getInputStream(); //将返回的流数据解析成图片 Bitmap bitmap = BitmapFactory.decodeStream(in); //使用handler传递消息 Message msg = Message.obtain(); msg.obj = bitmap;//传递的数据 handler.sendMessage(msg); in.close(); } } catch (Exception e) { e.printStackTrace(); } } }.start(); } }
注意两点:
Message对象的创建使用obtain方法可以达到对象重用的目的,节省内存开销。
Message对象可以使用msg.what = 传递消息的类型,handler可以根据传递的消息类型做不同处理,优化代码如下:
package com.ccl.getp_w_picpath; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { protected static final int SUCCESS = 0; protected static final int ERROR = 1; protected static final int NETWORK_ERROR = 2; private EditText et_path; private ImageView iv; private String path; //使用Handler更新主线程(UI线程) private Handler handler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what) { case SUCCESS: Bitmap bitmap = (Bitmap) msg.obj; iv.setImageBitmap(bitmap); break; case ERROR: Toast.makeText(MainActivity.this, "获取图片失败", 0).show(); break; case NETWORK_ERROR: Toast.makeText(MainActivity.this, "连接网络失败", 0).show(); break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_path = (EditText) findViewById(R.id.et_path); iv = (ImageView) findViewById(R.id.iv); } public void getImage(View view){ path = et_path.getText().toString().trim(); if(TextUtils.isEmpty(path)){ Toast.makeText(this, "地址不能为空", 0).show(); return; } new Thread(){ public void run(){ try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); System.out.println("响应码是--"+conn.getResponseCode()); if(conn.getResponseCode()==200){ //获取服务器返回的流数据 InputStream in = conn.getInputStream(); //将返回的流数据解析成图片 Bitmap bitmap = BitmapFactory.decodeStream(in); //使用handler传递消息 Message msg = Message.obtain(); msg.obj = bitmap;//传递的数据 msg.what = SUCCESS;//传递的消息类型,handler可根据消息类型做不同处理 handler.sendMessage(msg); in.close(); }else{ Message msg = Message.obtain(); msg.what = ERROR; handler.sendMessage(msg); } } catch (Exception e) { Message msg = Message.obtain(); msg.what = NETWORK_ERROR; handler.sendMessage(msg); e.printStackTrace(); } } }.start(); } }