android开发(7) 文件下载

摘要:
先看几行代码:StringurlDownload="";urlDownload="http://www.baidu.com/img/baidu_sylogo1.gif";URLurl=newURL;//打开连接URLConnectioncon=url.openConnection();//输入流InputStreamis=con.getInputStream();如上面的代码所示,指定一个下载的目标链接,我们上面指定了一个图片地址。f.exists()){f.mkdir();}下载的操作://准备拼接新的文件名StringnewFilename=_urlStr.substring;newFilename=_dirName+newFilename;Filefile=newFile;//如果目标文件已经存在,则删除。我们就用它传递消息的特点,并且该对象属于android平台核心框架,和主界面的消息循环有联系。我们分别实现它:privateHandlermyHandler=newHandler(){publicvoidhandleMessage{//获得进度,该进度由实际的操作进行通知。

我们在开发中经常需要从服务器下载文件,下载的内容可能有交换的信息,缓存的图片,程序更新包等。我们使用URLConnection来实现下载。先看几行代码:

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,拿到一个输入流对象,通过这个流对象我们就可以读取到这个文件的内容了。下面要做的,就是读取这个流,将流写入我们的本地文件。不过在这之前,我们还要说下这个方法:

//获得文件的长度
int contentLength = con.getContentLength();
System.out.println("长度 :"+contentLength);

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

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

// 获得存储卡路径,构成 保存文件的目标路径
String dirName = "";
dirName = Environment.getExternalStorageDirectory()+"/MyDownload/";
File f = new File(dirName);
if(!f.exists())
{
f.mkdir();
}

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

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

下载前的准备工作:

//要下载的文件路径
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();
}

下载的操作:

//准备拼接新的文件名(保存在存储卡后的文件名)
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();
}

完整的代码下载


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

本可以再写一篇博文的,考虑到完整性,决定放到同一篇文档里去。

我们先来看下进度条

<ProgressBar
android:
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.被观察的目标就是下载的过程了。这个过程中下载文件的进度。

我们分别实现它:

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关联。有了消息,它就告诉这个观察者。观察者收到消息,通知给订阅了消息的对象(本文为进度条)。

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

// 构造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();

我们记录我们当前从服务器读了多少字节,又知道总共需要下载多少字节。计算后,得到一个完成了多少的百分比。将这个百分比通知给 观察者。

完整的代码下载

免责声明:文章转载自《android开发(7) 文件下载》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ccf-集合竞价-201412-3LoadRunner监控图表与配置(一) 监控与图表下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android开发学习路线图

通过前面的3篇博客已经简单的介绍了Android开发的过程并写了一个简单的demo,了解了Android开发的环境以及一些背景知识。 接下来这篇博客不打算继续学习Android开发的细节,先停一下,明确一下接下来的学习目标以及学习路线。 一、对Android开发的基本认识 1、Android原生开发是基于Java语言的,由于我比较擅长C#,所以对Java语...

UI组件库Kendo UI for Angular入门指南教程

Conversational UI组件弥合了Web 和下一代自然语言应用程序之间的差距。Conversational UI 包提供了Kendo UI聊天组件,该组件允许用户参与与其他用户或聊天机器人的聊天会话。 Conversational UI Package 是Kendo UI for Angular的一部分,这是一个专业级 UI 库,具有 100 多...

React Native环境搭建

最近组里老大开始招RN的一些开发人员,也从最近的一些动向表明将来的功能有可能会由RN来编写了,而对于我是从事纯Native的android开发工作已经N多年了,对于RN组里面也有一些同事的技术分享,说实话对它是非常之抗拒的,觉着这玩意不会就像几年前出的PhoneGap那样鸡肋的技术吧,也就是用Webview去加载h5页面嘛,不可能代替Native的,直到最...

Qt for Android 部署流程分析

原地址:http://blog.csdn.net/foruok/article/details/17796017 今天为了测试使用 Qt Creator 3.0.0 开发的纯 C 工程,利用了Windows 下 Qt 5.2 for Android 开发入门里创建的 HelloAndroid 工程,想把纯 C 工程生成的 so 库加到 HelloAndro...

Android ButterKnife注解式开发

在Android开发中findViewById和setOnClickListener解脱写法。 在任意的一个类中 @Bind(R.id.et) EditText editText; @OnClick(R.id.btn) public void btnClick(){ Toast.makeText(MainActivity.this,editText.get...

android 判断网络 网络监控

获取网络信息需要在AndroidManifest.xml文件中加入相应的权限。 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 1)判断是否有网络连接 复制代码 代码如下: public boolean isNetworkConnected...