一、自己封装URLConnection 连接请求类

   public void downloadFile1() {
try{
//下载路径,如果路径无效了,可换成你的下载路径
String url = "http://c.qijingonline.com/test.mkv";
String path = Environment.getExternalStorageDirectory().getAbsolutePath(); final long startTime = System.currentTimeMillis();
Log.i("DOWNLOAD","startTime="+startTime);
//下载函数
String filename=url.substring(url.lastIndexOf("/") + 1);
//获取文件名
URL myURL = new URL(url);
URLConnection conn = myURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
int fileSize = conn.getContentLength();//根据响应获取文件大小
if (fileSize <= 0) throw new RuntimeException("无法获知文件大小 ");
if (is == null) throw new RuntimeException("stream is null");
File file1 = new File(path);
if(!file1.exists()){
file1.mkdirs();
}
//把数据存入路径+文件名
FileOutputStream fos = new FileOutputStream(path+"/"+filename);
byte buf[] = new byte[1024];
int downLoadFileSize = 0;
do{
//循环读取
int numread = is.read(buf);
if (numread == -1)
{
break;
}
fos.write(buf, 0, numread);
downLoadFileSize += numread;
//更新进度条
} while (true); Log.i("DOWNLOAD","download success");
Log.i("DOWNLOAD","totalTime="+ (System.currentTimeMillis() - startTime)); is.close();
} catch (Exception ex) {
Log.e("DOWNLOAD", "error: " + ex.getMessage(), ex);
}
}
这种方式在Android 刚兴起的时候,很少下载封装框架,就自己封装了。虽然一般的文件都能下载,但这种方式缺点很多,不稳定或者各种各样的问题会出现。
 

二、Android自定的下载管理(会在notification 显示下载的进度,同时可以暂停、重新连接等)

private void downloadFile2(){
//下载路径,如果路径无效了,可换成你的下载路径
String url = "http://c.qijingonline.com/test.mkv";
//创建下载任务,downloadUrl就是下载链接
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
//指定下载路径和下载文件名
request.setDestinationInExternalPublicDir("", url.substring(url.lastIndexOf("/") + 1));
//获取下载管理器
DownloadManager downloadManager= (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
//将下载任务加入下载队列,否则不会进行下载
downloadManager.enqueue(request);
}

这种方式其实就是交给了Android系统的另一个app去下载管理。这样的好处不会消耗该APP的 CPU资源。缺点是:控制起来很不灵活。

三、使用第三方 okhttp 网络请求框架

private void downloadFile3(){
//下载路径,如果路径无效了,可换成你的下载路径
final String url = "http://c.qijingonline.com/test.mkv";
final long startTime = System.currentTimeMillis();
Log.i("DOWNLOAD","startTime="+startTime); Request request = new Request.Builder().url(url).build();
new OkHttpClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 下载失败
e.printStackTrace();
Log.i("DOWNLOAD","download failed");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Sink sink = null;
BufferedSink bufferedSink = null;
try {
String mSDCardPath= Environment.getExternalStorageDirectory().getAbsolutePath();
File dest = new File(mSDCardPath, url.substring(url.lastIndexOf("/") + 1));
sink = Okio.sink(dest);
bufferedSink = Okio.buffer(sink);
bufferedSink.writeAll(response.body().source()); bufferedSink.close();
Log.i("DOWNLOAD","download success");
Log.i("DOWNLOAD","totalTime="+ (System.currentTimeMillis() - startTime));
} catch (Exception e) {
e.printStackTrace();
Log.i("DOWNLOAD","download failed");
} finally {
if(bufferedSink != null){
bufferedSink.close();
} }
}
});
}
okhttp是一个很有名气的开源框架,目前已经很多大公司都直接使用它作为网络请求库(七牛云SDK, 阿里云SDK)。 且里面集成了很多优势,包括 okio (一个I/O框架,优化内存与CPU)。
 
在接收数据的时候使用了 okio框架 来做一些I/O处理,okio框架是弥补Java.io 上的不足,节省CPU与内存资源,但这个例子,我没还没看到其效果,也可以自己来接收字符流,然后获取下载的进度
 public void downloadFile(){
final String url = "http://c.qijingonline.com/test.mkv";
final long startTime = System.currentTimeMillis();
Log.i("DOWNLOAD","startTime="+startTime);
OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 下载失败
e.printStackTrace();
Log.i("DOWNLOAD","download failed");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
// 储存下载文件的目录
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath();
try {
is = response.body().byteStream();
long total = response.body().contentLength();
File file = new File(savePath, url.substring(url.lastIndexOf("/") + 1));
fos = new FileOutputStream(file);
long sum = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
sum += len;
int progress = (int) (sum * 1.0f / total * 100);
// 下载中
// listener.onDownloading(progress);
}
fos.flush();
// 下载完成
// listener.onDownloadSuccess();
Log.i("DOWNLOAD","download success");
Log.i("DOWNLOAD","totalTime="+ (System.currentTimeMillis() - startTime));
} catch (Exception e) {
e.printStackTrace();
// listener.onDownloadFailed();
Log.i("DOWNLOAD","download failed");
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
}
}
});
}
 
 
 
综合来看,第三种方案是最佳的,是目前最流行的下载方案。

Android 文件下载三种基本方式的更多相关文章

  1. Android平台中实现对XML的三种解析方式

    本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...

  2. Android中三种超实用的滑屏方式汇总(转载)

    Android中三种超实用的滑屏方式汇总   现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于 ...

  3. JSON的三种解析方式

    一.什么是JSON? JSON是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度. JSON就是一串字符串 只不过元素会使用特定 ...

  4. Service组件 总结 + 绑定理Service三种实现方式 Messager + Binder + AIDL

    在Android中进程按优先级可以分为五类,优先级从高到低排列: - 前台进程 该进程包含正在与用户进行交互的界面组件,比如一个Activity - 可视进程 该进程中的组件虽然没有和用户交互,但是仍 ...

  5. Java三种编译方式

    Java程序代码需要编译后才能在虚拟机中运行,编译涉及到非常多的知识层面:编译原理.语言规范.虚拟机规范.本地机器码优化等:了解编译过程有利于了解整个Java运行机制,不仅可以使得我们编写出更优秀的代 ...

  6. Android 中三种启用线程的方法

    在多线程编程这块,我们经常要使用Handler(处理),Thread(线程)和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢? 首先说明Android的CPU分配的最小单元是线程,Han ...

  7. 通过三个DEMO学会SignalR的三种实现方式

    一.理解SignalR ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信(即:客户端(Web页面)和服务器端可以互相实时的通知消息 ...

  8. Hive metastore三种配置方式

    http://blog.csdn.net/reesun/article/details/8556078 Hive的meta数据支持以下三种存储方式,其中两种属于本地存储,一种为远端存储.远端存储比较适 ...

  9. django 模板语法和三种返回方式

    模板 for循环 {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} if语句 ...

随机推荐

  1. 直接请求转发(Forward)和间接请求转发(Redirect)两种区别?

    用户向服务器发送了一次HTTP请求,该请求肯能会经过多个信息资源处理以后才返回给用户,各个信息资源使用请求转发机制相互转发请求,但是用户是感觉不到请求转发的.根据转发方式的不同,可以区分为直接请求转发 ...

  2. CCF系列之数列分段(201509-1)

    试题名称: 数列分段 试题编号: 201509-1 时间限制: 1.0s 内存限制: 256.0MB 问题描述 给定一个整数数列,数列中连续相同的最长整数序列算成一段,问数列中共有多少段? 输入格式 ...

  3. mybatis_SQL映射(2)

    文章摘录自:http://blog.csdn.net/y172158950/article/details/17258377 1. sql的重用:定义一个sql片段,可在任何SQL语句中重用该片段. ...

  4. python中的Queue(队列)详解

    一.Queue简介 python中的队列分类可分为两种: 1.线程Queue,也就是普通的Queue 2.进程Queue,在多线程与多进程会介绍. Queue的种类: FIFO:  Queue.Que ...

  5. js 获取url链接的任意参数

    <script> //先获取 当前的url链接 var url = location.href; //把url 链接切割为数组 var arr = url.split("&quo ...

  6. zabbix自动清理30天前的数据

    转:http://www.361way.com/delete-zabbix-histroy-data/3826.html zabbix属于一个细度化的监控工具,其入库数据随着细度的增加相应的入库数据量 ...

  7. PHP数据核心:Zend HashTable详解

    最近看了篇关于php内的hashtable的文章,PHP数据存储的核心,各种常量.变量.函数.类.对象等都用它来组织的.转载地址 http://www.phppan.com/2009/12/zend- ...

  8. linux常用命令_1

    linux中命令格式是什么? 命令 [参数选项] [文件或路径] 中括号表示可选,命令的参数与路径文件可选 参数选择表示一个命令的不同功能 命令 和 参数选项 中必有一空格,多个参数连在一起写 几乎所 ...

  9. Python中变量和常量的理解

    一.变量的定义:把程序运算的中间结果临时存到内存里,以备后面的代码继续调用,这几个名字的学名就叫做"变量". 二.变量的作用:变量用于存储要在计算机程序中引用和操作的信息.它提供了 ...

  10. SuperMap iClient for JavaScript初入

    SuperMap iClient for JavaScript初入 介绍SuperMap for Js的简单使用. 推荐先看下这篇文档:SuperMap iClient for JavaScript ...