之前有看过一个著名的断点下载的框架MultiThreadDownload,用的是线程池开启下载任务,点击暂停的时候将断点的信息保存在数据库里面,下次拿出来继续下载,本文的思路也和这个差不多。
 
 这篇文章的代码将会在上次写的《即拿即用-HttpURLConnection分别实现图片,文本,文件的请求》的GitHub项目里面继续更新。完整下载地址在文章最后

 该例子在下载中多次点击开始和暂停对进度进行控制,下面放上一张效果图:

 主要步骤如下:

 点击开始的时候,我们要先开一个网络连接去获取文件的长度:

    /*** 点击开始*/public void onStartClick(View view) {// 开启fileName.setText(getfileName(urlstr));// 获得Activity传来的参数Log.i("test", "START" + fileInfo.toString());//开启一个下载任务new InitThread(fileInfo).start();}
/*** 开启一个网络连接用来获得下载文件的信息*/class InitThread extends Thread {private FileInfo mFileInfo = null;public InitThread(FileInfo mFileInfo) {super();this.mFileInfo = mFileInfo;}@Overridepublic void run() {HttpURLConnection conn = null;RandomAccessFile raf = null;try {URL url = new URL(mFileInfo.getUrl());conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(5 * 1000);conn.setRequestMethod("GET");int code = conn.getResponseCode();int length = -1;if (code == HttpURLConnection.HTTP_OK) {length = conn.getContentLength();}//如果文件长度为小于0,表示获取文件失败,直接返回if (length <= 0) {return;}// 判断文件路径是否存在,不存在这创建File dir = new File(DownloadPath);if (!dir.exists()) {dir.mkdir();}// 创建本地文件File file = new File(dir, mFileInfo.getFileName());raf = new RandomAccessFile(file, "rwd");raf.setLength(length);// 设置文件长度mFileInfo.setLength(length);// 将ileInfo对象传送给HandlerMessage msg = Message.obtain();msg.obj = mFileInfo;msg.what = MSG_INIT;mHandler.sendMessage(msg);
//              msg.setTarget(mHandler);} catch (Exception e) {e.printStackTrace();} finally {if (conn != null) {conn.disconnect();}try {if (raf != null) {raf.close();}} catch (IOException e) {e.printStackTrace();}}super.run();}}

 获取文件的长度之后,发送一个handler消息通知应用去开启另外一个网络连接DownloadTask,进行下载:

    // 从InitThread线程中获取FileInfo信息,然后开始下载任务Handler mHandler = new Handler() {public void handleMessage(android.os.Message msg) {switch (msg.what) {case MSG_INIT:FileInfo fileInfo = (FileInfo) msg.obj;Log.i("test", "INIT:" + fileInfo.toString());// 获取FileInfo對象,开始下载任务mTask = new DownloadTask(SingleThreadDownloadActivity.this, fileInfo);mTask.download();break;}}};

 在开启下载任务之前,根据下载的地址作为条件,看一下数据库这个地址有没有上一次下载的信息,也就是上一次文件下载的长度,结束的位置等信息,有的话获取并传给下载任务,没有的话会在下载任务里面插入一条到数据库

     /*** 查询数据库上一次下载的信息,有则获取,没有则新建*/public void download() {// 从数据库中获取到下载的信息List<ThreadInfo> list = mDao.queryThreads(mFileInfo.getUrl());ThreadInfo info = null;if (list.size() == 0) {info = new ThreadInfo(0, mFileInfo.getUrl(), 0, mFileInfo.getLength(), 0);} else {info = list.get(0);}//开启下载任务new DownloadThread(info).start();}

 到了最关键的时候了,开启一个下载任务。一边下载一边记录下载的长度,并更新到数据库。如果点击了暂停,则跳出循环结束下载。

 class DownloadThread extends Thread {private ThreadInfo threadInfo = null;public DownloadThread(ThreadInfo threadInfo) {this.threadInfo = threadInfo;}@Overridepublic void run() {Log.i("test", "开启一个下载任务");// 如果数据库不存在下载信息,添加下载信息if (!mDao.isExists(threadInfo.getUrl(), threadInfo.getId())) {mDao.insertThread(threadInfo);}HttpURLConnection conn = null;RandomAccessFile raf = null;InputStream is = null;try {URL url = new URL(mFileInfo.getUrl());conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(5 * 1000);conn.setRequestMethod("GET");//开始位置为getFinished()开始上次结束的位置Log.i("test", "文件的长度"+mFileInfo.getLength()+"   上次结束的位置:" + threadInfo.getFinished());int start = threadInfo.getStart() + threadInfo.getFinished();// 设置下载文件开始到结束的位置(结束的位置也就是文件的长度)conn.setRequestProperty("Range", "bytes=" + start + "-" + threadInfo.getEnd());File file = new File(SingleThreadDownloadActivity.DownloadPath, mFileInfo.getFileName());raf = new RandomAccessFile(file, "rwd");raf.seek(start);mFinished += threadInfo.getFinished();int code = conn.getResponseCode();if (code == HttpURLConnection.HTTP_PARTIAL) {is = conn.getInputStream();byte[] bt = new byte[1024];int len = -1;// 定义UI刷新时间long time = System.currentTimeMillis();while ((len = is.read(bt)) != -1) {raf.write(bt, 0, len);//记录结束的位置mFinished += len;// 设置为500毫米更新一次if (System.currentTimeMillis() - time > 500) {time = System.currentTimeMillis();//发送一个广播提示下载的进度Intent intent = new Intent(SingleThreadDownloadActivity.ACTION_UPDATE);//结束的位置/文件长度*100=下载进度百分比intent.putExtra("finished", mFinished * 100 / mFileInfo.getLength());Log.i("test", mFinished * 100 / mFileInfo.getLength() + "");// 发送广播给ActivitymComtext.sendBroadcast(intent);}if (mIsPause) {//如果状态为暂停,则跳出循环,并记录这次结束的位置的长度mDao.updateThread(threadInfo.getUrl(), threadInfo.getId(), mFinished);return;}}}// 下载完成后,刪除数据库信息mDao.deleteThread(threadInfo.getUrl(), threadInfo.getId());Intent intent = new Intent(SingleThreadDownloadActivity.ACTION_UPDATE);//结束的位置/文件长度*100=下载进度百分比intent.putExtra("finished", 100);// 发送广播给ActivitymComtext.sendBroadcast(intent);Log.i("DownloadTask", "下载完毕");} catch (Exception e) {e.printStackTrace();} finally {if (conn != null) {conn.disconnect();}try {if (is != null) {is.close();}if (raf != null) {raf.close();}} catch (IOException e) {e.printStackTrace();}Log.i("test", "关闭一个下载任务");}super.run();}}

在这篇文章中的重点是使用了RandomAccessFile,它支持任意访问的方式,程序可以直接跳到任意地方来读写数据,RandomAccessFile的使用方式请查看《断点下载神器-RandomAccessFile》

《即拿即用-Android单线程断点下载》

《断点下载神器-RandomAccessFile》

《即拿即用-Android多线程断点下载》

完整代码地址

https://github.com/mocn26169/HttpRequest-Demo

参考

  • Android实战:简易断点续传下载器实现

即拿即用-Android单线程断点下载相关推荐

  1. 即拿即用-Android多线程断点下载

    线程下载只需要确定好下载一个文件需要多少个线程,一般来说最好为3条线程,因为线程过多会占用系统资源,而且线程间的相互竞争也会导致下载变慢. 其次下载的时候将文件分割为三份(假设用3条线程下载)下载,在 ...

  2. Android文件下载——单线程断点下载

    文章目录 1. 相关逻辑 1.1 获取待下载文件的总长度 1.2 使用HTTP的Range头部字段 1.3 RandomAccessFile 1.4 添加监听接口 2. 调用示例 3. DownLoa ...

  3. android 多线程断点下载,listview 模式 开始 暂停等功能

    android 多线程断点下载,listview 模式 代码依次如下: 布局: <?xml version="1.0" encoding="utf-8"? ...

  4. android 断点下载的实现,Android实现断点下载的方法

    最近做的项目中需要实现断点下载,即用户一次下载可以分多次进行,下载过程可以中断,在目前大多数的带离线缓存的软件都是需要实现这一功能.本文阐述了通过sqlite3简单实现了一个具有断点下载功能的demo ...

  5. Android 多线程断点下载demo实现

    先来一张效果图: 主要实现思路: 每一个下载都是通过RandomAccessFile对下载资源的总长进行切割之后,根据我们设置的线程多少进行计算之后开启多线程下载的.而每一个任务都是一个AsyncTa ...

  6. Android多线程断点下载

    到华为后,信息管理特别严格,文件不能外发.所以好久都没写博客了,今天周日,老婆非要我学习.就闲来无事,写一篇博客,呵呵-- 前段时间,项目中提到了断点下载apk并静默安装的需求.本打算用应用市场成熟的 ...

  7. Android 多线程断点下载(非原创)

    1.服务器的CPU分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服务器资源,这里在客户端开启多个线程来从服务器下载资源 2.fragment_ma ...

  8. Android中http断点下载,Android HttpURLConnection断点下载(单线程)

    HttpCilent 跟 HttpURLConnection 是安卓原生的用来实现http请求的类: Android 6.0之后取消了HttpClient,不支持跟新 ,今天小编使用的是HttpURL ...

  9. Android之用HttpURLConnection断点下载谷歌云存储(google cloud storage)文件

    1 需求 在Android app里面实现断点下载谷歌云存储(google cloud storage)文件,也就是说用户下载谷歌云存储(google cloud storage)文件的时候可以暂停下 ...

  10. android学习笔记---31_多线程断点下载器,下载原理实现

    1.1.31_多线程断点下载器 ----------------------- 1.软件界面:   文件下载路径              text框   button 下载   点击后,下面显示下载 ...

最新文章

  1. 28岁女博士生被骂“学术媛”,只因在网上分享自己牛津年级第一成绩毕业......
  2. 想进大厂?Dubbo 普普通通 9 问你知道吗
  3. ios NSFileManager 用法详解
  4. 汇编解析(2)-内存寻址之实模型平面模式(real mode flat mode)(2)
  5. Windows中添加svnserve作为系统服务
  6. WPF之鼠标滑动切换图片
  7. 数据结构之排序算法Java实现(2)——选择类排序之堆排序算法
  8. Moonbox v0.3beta 发布:Grid 全新重构,更快更解耦
  9. 常用的排序算法(java版)
  10. excel进销存添加网页模块,可手机开单
  11. centos7 pe系统安装_CentOS 系统的安装
  12. osip和mysql_osip2/eXosip2调试笔记
  13. Unity 关于制作UV动画,模拟管路气路流向示意图
  14. 关于癌症的思考:癌症的本质是什么
  15. Linux基础命令的那些事儿(1)
  16. AE-摄影机和跟踪器
  17. Android Studio报错:E/EGL_emulation: tid 3197: eglSurfaceAttrib(1199): error 0x3009 (EGL_BAD_MATCH)
  18. jquery-weui扩展功能Picker实现营业时间选择
  19. “昆明城市咖啡地图”活动再度开启
  20. mac u盘linux 双系统安装教程,U盘安装MAC双系统完美方案实现在MAC系统下使用双系统...

热门文章

  1. Windows下让Tomcat6定时重启服务的方法
  2. 10K 3435热敏电阻阻值表
  3. 希尔伯特变换到底有什么用
  4. 《你的灯亮着吗?》 读后感
  5. 5个常用的大数据可视化分析工具
  6. BGP 基本配置参考
  7. Python学习之Python入门知识(一)
  8. ADS2015 for linux 安装教程
  9. java时间格式转换
  10. 如何成为一名Go开发人员:总共分六步