首先需要搭建一个Tomcat服务器,然后测试服务器上的图片使用PC上的浏览器是否可以正常下载下来

可以看到服务器上的图片数据是可以正常访问的。图片的地址:http://localhost:8080/meinv.jpg

那如何在我们Android上从网络下载图片呢?

直接上获取网络图片的代码:

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View v){//1: 确定网址String path = "http://localhost:8080/meinv.jpg";try {//2:把网址封装为一个URL对象URL url = new URL(path);//3:获取客户端和服务器的连接对象,此时还没有建立连接HttpURLConnection conn = (HttpURLConnection) url.openConnection();//4:初始化连接对象conn.setRequestMethod("GET");//设置连接超时conn.setConnectTimeout(5000);//设置读取超时conn.setReadTimeout(5000);//5:发生请求,与服务器建立连接conn.connect();//如果响应码为200,说明请求成功if(conn.getResponseCode() == 200){//获取服务器响应头中的流InputStream is = conn.getInputStream();//读取流里的数据,构建成bitmap位图Bitmap bm = BitmapFactory.decodeStream(is);//显示在界面上ImageView imageView = (ImageView) findViewById(R.id.lv);imageView.setImageBitmap(bm);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

运行看效果:

从控制台的打印可以是警告: 网络工作在主线程中异常。

上面的警告就是从4.0以后引入的,如果网络任务在主线程中,就会报警告。所以我们需要开启一个线程来执行网络任务。

修改后的代码为:

public void click(View v){//开启一个线程Thread thread = new Thread(){@Overridepublic void run() {// TODO Auto-generated method stub//1: 确定网址String path = "http://localhost:8080/meinv.jpg";try {//2:把网址封装为一个URL对象URL url = new URL(path);//3:获取客户端和服务器的连接对象,此时还没有建立连接HttpURLConnection conn = (HttpURLConnection) url.openConnection();//4:初始化连接对象conn.setRequestMethod("GET");//设置连接超时conn.setConnectTimeout(5000);//设置读取超时conn.setReadTimeout(5000);//5:发生请求,与服务器建立连接conn.connect();//如果响应码为200,说明请求成功if(conn.getResponseCode() == 200){//获取服务器响应头中的流InputStream is = conn.getInputStream();//读取流里的数据,构建成bitmap位图Bitmap bm = BitmapFactory.decodeStream(is);//显示在界面上ImageView imageView = (ImageView) findViewById(R.id.lv);imageView.setImageBitmap(bm);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}};//启动线程任务thread.start();}

再次运行看效果:

又报出一个警告: 调用错误线程异常,也就是说只有创建它的view,才能调用该view。 直白点就是只有主线程(UI线程)才能更新UI,别的线程是不能随便更新UI的。

如果需要更新UI,那只能主线程来更新UI,那别的线程如何告诉主线程需要更新UI呢? 这就需要引入另一个知识点:消息

如果别的线程需要更新UI,就发生消息给主线程,主线程收到后会自动的更新UI

代码修改为:

if(conn.getResponseCode() == 200){//获取服务器响应头中的流InputStream is = conn.getInputStream();//读取流里的数据,构建成bitmap位图Bitmap bm = BitmapFactory.decodeStream(is);//发生更新UI的消息Message msg = handler.obtainMessage();msg.obj = bm;handler.sendMessage(msg);//显示在界面上//ImageView imageView = (ImageView) findViewById(R.id.lv);//imageView.setImageBitmap(bm);}

加入Handler,也就是处理消息的handle

 Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {//更新UIImageView imageView = (ImageView) findViewById(R.id.lv);imageView.setImageBitmap((Bitmap) msg.obj);};};

再次运行看效果:

可以看到图片正常显示出来了。

我们再次修改代码增加获取失败的处理逻辑

if(conn.getResponseCode() == 200){//获取服务器响应头中的流InputStream is = conn.getInputStream();//读取流里的数据,构建成bitmap位图Bitmap bm = BitmapFactory.decodeStream(is);//发生更新UI的消息Message msg = handler.obtainMessage();msg.obj = bm;msg.what = GET_OK;handler.sendMessage(msg);//显示在界面上//ImageView imageView = (ImageView) findViewById(R.id.lv);//imageView.setImageBitmap(bm);}else {//发送获取失败的消息Message msg = handler.obtainMessage();msg.what = GET_ERROR;handler.sendMessage(msg);}

消息处理过程:

static final int GET_ERROR = 0;static final int GET_OK  = 1;Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {//更新UIswitch (msg.what) {case GET_OK:ImageView imageView = (ImageView) findViewById(R.id.lv);imageView.setImageBitmap((Bitmap) msg.obj);break;case GET_ERROR:Toast.makeText(MainActivity.this, "访问失败!", Toast.LENGTH_SHORT).show();break;default:break;}};};

我们可以将地址改错,显示效果

关于消息机制简单说明一下:

1:发生消息系统会使用消息队列(MessageQueue)和消息轮询对象(Looper)

2:消息轮询对象的作用就是不停的检测消息队列中是否有小心,如果一旦有消息,消息轮询器就会将消息对象交给消息处理器(Handler),处理器会调用handleMessage方法来处理这条消息。handleMessage方法运行在主线程中,所以可以刷新ui

但是平常应用中,比如微信朋友圈的大量图片,第一次浏览时都是先缓冲到本地,第二次浏览时直接从本地读取即可,那我们来实现一下:

    public void click(View v){//指定文件的路径final File file = new File(getCacheDir(), "info.jpg");//如果文件存在,直接从本地打开if(file.exists()){System.out.println("从缓存读取的");Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());ImageView imageView = (ImageView) findViewById(R.id.lv);imageView.setImageBitmap(bm);}else {System.out.println("从网上下载的");//开启一个线程Thread thread = new Thread(){@Overridepublic void run() {// TODO Auto-generated method stub//1: 确定网址String path = "http://192.168.1.109:8080/meinv.jpg";try {//2:把网址封装为一个URL对象URL url = new URL(path);//3:获取客户端和服务器的连接对象,此时还没有建立连接HttpURLConnection conn = (HttpURLConnection) url.openConnection();//4:初始化连接对象conn.setRequestMethod("GET");//设置连接超时conn.setConnectTimeout(5000);//设置读取超时conn.setReadTimeout(5000);//5:发生请求,与服务器建立连接conn.connect();//如果响应码为200,说明请求成功if(conn.getResponseCode() == 200){//获取服务器响应头中的流InputStream is = conn.getInputStream();//读取服务器返回流里的数据,把数据写入到本地,缓冲起来FileOutputStream fos = new FileOutputStream(file);byte[] b = new byte[1024];int len = 0;while((len = is.read(b)) != -1){fos.write(b, 0, len);}fos.close();is.close();//从本地加载图片Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());//读取流里的数据,构建成bitmap位图//Bitmap bm = BitmapFactory.decodeStream(is);//发生更新UI的消息Message msg = handler.obtainMessage();msg.obj = bm;msg.what = GET_OK;handler.sendMessage(msg);//显示在界面上//ImageView imageView = (ImageView) findViewById(R.id.lv);//imageView.setImageBitmap(bm);}else {//发送获取失败的消息Message msg = handler.obtainMessage();msg.what = GET_ERROR;handler.sendMessage(msg);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}};//启动线程任务thread.start();}}

上面是增加从本地缓冲中获取图片文件。

第一次运行时:包文件名下的cache下就会存在info.jpg文件

缓冲文件

当退出再次进来,就会直接从缓冲去获取

关于从网络上获取文件,就简单的说到这里

Android 网络学习之获取服务器的图片相关推荐

  1. 获取服务器上图片的位置,怎么获取服务器上的图片地址

    怎么获取服务器上的图片地址 内容精选 换一换 通过云服务器或者外部镜像文件创建私有镜像时,如果云服务器或镜像文件所在虚拟机的网络配置是静态IP地址时,您需要修改网卡属性为DHCP,以使私有镜像发放的新 ...

  2. android 网络编程--URL获取数据/图片

    首先,开始最简单的网络编程实战,URL实现网络连接,不懂的童鞋可以参考JAVA中的URL编程,其原理是一样的,在这里不再多做解释. 直接贴出实现源代码: public class DataActivi ...

  3. android打开手机相册获取真正的图片路径

    版权声明:本文为博主原创文章,转载请注明地址.    https://blog.csdn.net/huangxiaoguo1/article/details/79062341 根据打开相机返回的Uri ...

  4. vue获取服务器路径图片显示,vue img图片路径和背景图片路径打包问题

    当项目需要放到服务器子目录时候,会遇到这个图片打包问题, 处理方法有两个:#A和#B #A 给所有资源配置相对路径'/'. A-1,找到 config->index.js里面,如下修改 //举个 ...

  5. android传感器学习之获取传感器的值

    在上一篇中,讲到了怎么获取手机的传感器http://blog.csdn.net/nainai007/article/details/7615364,在这里是获取传感器的值. 要获取传感器的值,首先要为 ...

  6. Android入门学习_Android获取来电号码

    2019独角兽企业重金招聘Python工程师标准>>> Android来电号码获取的方法很简单,虽然Dalvik上的程序都是Java写的,但是仍然可以处理系统事物,使用PhoneSt ...

  7. android上传字符串到服务器,【图片】【转】通过Android 客户端上传数据到服务器【aide吧】_百度贴吧...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 public class HttpRequester { /** * 直接通过HTTP 协议提交数据到服务器,实现如下面表单提交功能: * ACTION= ...

  8. 获取服务器上图片的大小KB

    public class ImageUtils {// 图片sizepublic static int size;/*** 根据图片地址返回图片大小kb或者 Mb** @param imgPath 图 ...

  9. android上传文件到服务器(图片、文本等)

    首先,在项目中导入SmartAndroid.jar包. 然后加入相应的方法: public void uploadFile(String imagePath){//服务器端地址String url = ...

  10. Android 网络获取图片处理

    今天做项目,需要从网络获取图片,然后加载到Listview里面. 这边需要分为两步. 第一步:从网络获取图片 public InputStream getImageViewInputStream(St ...

最新文章

  1. 腾讯的人工智能大战已然打响!
  2. 【译】Angular 5 新特性
  3. Python-描述符
  4. solidworks2018安装教程
  5. 全选文字的快捷键_高效办公必备Excel快捷键之Ctrl+26个字母!掌握它们,告别加班...
  6. Apache网页优化概述
  7. Linux(CenterOS 6.4)下安装jdk1.6
  8. linux xfs字体服务安装6,Linux系统中安装中文字体方法
  9. IBM 开源处理加密数据的工具集
  10. 解决Surface Pro外接移动硬盘经常睡眠的问题
  11. 三种DSO(标准DSO、写优化DSO、直接更新DSO)、标准DSO覆盖合计规则
  12. Spring 最常用的注解,史上最强整理!
  13. 学 C 语言,最经典的书有这样几本
  14. 中点画线完整算法c语言,中点画线算法
  15. Spark 基础知识
  16. 调用百度aip实现短语音翻译(附代码)
  17. 淘宝API应用开发小试
  18. 【Ubuntu】如何在Ubuntu系统上设置好看的动态壁纸(Komorebi)
  19. 物联卡机卡分离后该怎么处理?教你一招就能解决!
  20. Android 编程实用代码大全

热门文章

  1. Can't create new folder in windows7
  2. Hive里的分区、分桶、视图和索引再谈
  3. 如何开发一款堪比APP的微信小程序(腾讯内部团队分享)
  4. [原]Linux 命令行浏览器
  5. ARPSpoofing教程(四) - 捕获并分析数据包
  6. 符号“”和const在函数里不同位置的用法
  7. mysql8.0.15源码linux_源码安装mysql8.0.20
  8. MySQL中的四种Key
  9. php加载memcache模块
  10. Vmware 安装 Fedora 18 注意事项