Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 745|回复: 0

[实例教程]Android 怎么样实现文件下载

[复制链接]

该用户从未签到

发表于 2011-10-22 12:20:00 | 显示全部楼层 |阅读模式
我们在开发中经常需要从服务器下载文件,下载的内容可能有交换的信息,缓存的图片,程序更新包等。我们使用URLConnection来实现下载。先看几行代码:

java代码: String urlDownload = "";



urlDownload = "http://www.baidu.com/img/baidu_sylogo1.gif";

URL url = new URL(urlDownload );

// 打开连接

URLConnection con = url.openConnection();

// 输入流

InputStream is = con.getInputStream();

如上面的代码所示,指定一个下载的目标链接,我们上面指定了一个图片地址。然后构建一个URL对象,调用该对象的openConnection方法来建立一个数据通路(连接)。代码的最后一行使用 con.getInputStream,拿到一个输入流对象,通过这个流对象我们就可以读取到这个文件的内容了。下面要做的,就是读取这个流,将流写入我们的本地文件。不过在这之前,我们还要说下这个方法:

java代码:
//获得文件的长度

int contentLength = con.getContentLength();

System.out.println("长度 :"+contentLength);
获得文件长度的方法。ContentLength是不很熟啊。它是http协议里描述头(head)部分的描述属性之一。实际这里是发送了一个http请求,分析了返回(response)里数据内容。

       我们常常会把文件下载到手机的存储卡里,所以还会用到获得存储卡路径的方法:

java代码:
// 获得存储卡路径,构成 保存文件的目标路径



String dirName = "";

dirName = Environment.getExternalStorageDirectory()+"/MyDownload/";

File f = new File(dirName);

if(!f.exists()){

f.mkdir();

}
Environment.getExternalStorageDirectory() 方法会返回一个字符串,指示了存储卡的路径。我们拼接字符串出一个准备存放下载文件的文件夹。并先判断文件夹是是否存在,如果不存在,则新建一个文件夹。

       做完了上面的准备后,基本就能实现下载了。我们看看主要的完整代码。
       下载前的准备工作:

java代码:
//要下载的文件路径



String urlDownload = "";

//urlDownload = "http://192.168.3.39/text.txt%22;

urlDownload = "http://www.baidu.com/img/baidu_sylogo1.gif%22;

// 获得存储卡路径,构成 保存文件的目标路径

String dirName = "";

dirName = Environment.getExternalStorageDirectory()+"/MyDownload/";

File f = new File(dirName);

if(!f.exists()){

f.mkdir();

}

下载的操作:

java代码:
//准备拼接新的文件名(保存在存储卡后的文件名)



String newFilename = _urlStr.substring(_urlStr.lastIndexOf("/")+1);

newFilename = _dirName + newFilename;

File file = new File(newFilename);

//如果目标文件已经存在,则删除。产生覆盖旧文件的效果



if(file.exists()){

file.delete();

}



try {

// 构造URL

URL url = new URL(_urlStr);

// 打开连接

URLConnection con = url.openConnection();

//获得文件的长度

int contentLength = con.getContentLength();

System.out.println("长度 :"+contentLength);

// 输入流

InputStream is = con.getInputStream();

// 1K的数据缓冲

byte[] bs = new byte[1024];

// 读取到的数据长度

int len;

// 输出的文件流

OutputStream os = new FileOutputStream(newFilename);

// 开始读取





while ((len = is.read(bs)) != -1) {

os.write(bs, 0, len);

}

// 完毕,关闭所有链接

os.close();

is.close();

} catch (Exception e) {

e.printStackTrace();

}

  进阶篇 - 增加进度条提示下载进度

       本可以再写一篇博文的,考虑到完整性,决定放到同一篇文档里去。
我们先来看下进度条

java代码:
&ltrogressBar

android:id="@+id/ProgressBar01"

style="?android:attr/progressBarStyleHorizontal"

android:layout_height="wrap_content"

android:visibility="visible"

android:max="100"

android:progress="1"

android:layout_width="200dp"/>
上面展示了一个水平的进度条。max属性指定了最大值,progress指示当前的进度位置。style指定了一个现实风格。

       不得不说的一个是设计模式里的“观察者”模式。观察者模式提供了一个“让一个观察者去观察一个对象,当观察的目标发生变化时,通知给 订阅了观察结果的对象 ”。这句话纯属于个人理解。它表达了几个对象:

       1.订阅了“观察结果的对象”,该对象会收到“观察者”的通知。
       2.观察者对象,一个紧盯这 目标对象 的对象。它负责将 观察的目标 的变化 通知给 “订阅者”
       3.被观察的目标,会发生变化的目标对象,它的变化及时的都被观察者所知。

       在我们的下载时我们的几个对象是

       1.进度条,是订阅者,它接受观察者对象的消息,来显示自己的进度条位置。
       2.观察者,是一个handler对象。该对象适合在线程间传递消息。我们就用它传递消息的特点,并且该对象属于android平台核心框架,和主界面的消息循环有联系。
       3.被观察的目标就是下载的过程了。这个过程中下载文件的进度。

       我们分别实现它:

java代码:
private Handler myHandler = new Handler(){



public void handleMessage(android.os.Message msg) {

//获得进度,该进度由实际的操作进行通知。这里负责对通知进行处理

int progress = msg.arg1;

//设置进度条的当前位置

_ProgressBar01.setProgress(progress);





if(progress == 100){

Toast.makeText(getApplicationContext(), "下载成功", 0).show();

}

};



};

  我们构建一个myHandler 对象,并重载了它的handleMessage方法,该方法会捕获(收到)所有发送给myHandler 的消息。我们接收消息,并根据消息携带的信息arg1作为当前的进度表示。

       下面我们将这个myHandler 传递给下载的线程new FileDownloader(urlDownload,dirName,myHandler).start();
如上面这行代码所示,FileDownloader对象是个下载器对象,它负责下载文件,同时他和观察者myHandler关联。有了消息,它就告诉这个观察者。观察者收到消息,通知给订阅了消息的对象。

       下面看下如何进行下载进程的:

java代码:
// 构造URL

URL url = new URL(_urlStr);



// 打开连接

URLConnection con = url.openConnection();



//获得文件的长度

int contentLength = con.getContentLength();

System.out.println("长度 :"+contentLength);



// 输入流

InputStream is = con.getInputStream();

int hasRead = 0;//已经读取了多少

int progress = 0;



// 1K的数据缓冲

byte[] bs = new byte[128];

// 读取到的数据长度

int len;

// 输出的文件流

OutputStream os = new FileOutputStream(newFilename);

// 开始读取

while ((len = is.read(bs)) != -1) {

os.write(bs, 0, len);



//记录完成了的多少

hasRead +=len;

progress = (int)((double)hasRead/(double)contentLength * 100);//完成的百分比

//发送通知

Message msg = _myHandler.obtainMessage();

msg.arg1 = progress;

msg.sendToTarget();

Thread.sleep(500);//故意延迟,不然进度条跑的太快看不清楚

}



// 完毕,关闭所有链接

os.close();

is.close();
回复

使用道具 举报

该用户从未签到

发表于 2011-10-22 12:20:04 | 显示全部楼层

Re:[实例教程]Android

写得好详细啊。不过网络连接用HttpClient也不错
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2011-10-22 12:20:12 | 显示全部楼层

Re:[实例教程]Android

顶,下载来看看
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-5-6 03:02 , Processed in 0.401597 second(s), 49 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表