Android 多线程下载 显示进度 速度
功能要求:从网络下载一APK应用,显示下载速度、进度,并安装应用。
运行效果图:

工程结构图:

很简单,就一个activity,一个更新UI的线程,一个下载线程加个文件处理类
主要代码:
/**
*多线程下载,UI更新类
*@author young
* */
public class MultiThreadDownload extends Thread{
private static final String TAG = "MultiThreadDownload";
/**每一个线程需要下载的大小 */
private int blockSize;
/*** 线程数量<br> 默认为5个线程下载*/
private int threadNum = ;
/*** 文件大小 */
private int fileSize;
/** * 已经下载多少 */
private int downloadSize;
/**文件的url,线程编号,文件名称*/
private String UrlStr,ThreadNo,fileName;
/***保存的路径*/
private String savePath;
/**下载的百分比*/
private int downloadPercent = ;
/**下载的 平均速度*/
private int downloadSpeed = ;
/**下载用的时间*/
private int usedTime = ;
/**当前时间*/
private long curTime;
/**是否已经下载完成*/
private boolean completed = false;
private Handler handler ;
/**
* 下载的构造函数
* @param url 请求下载的URL
* @param handler UI更新使用
* @param savePath 保存文件的路径
*/
public MultiThreadDownload(Handler handler,String url,String savePath)
{
this.handler = handler;
this.UrlStr = url;
this.savePath = savePath;
Log.e(TAG, toString());
} @Override
public void run() { FileDownloadThread[] fds = new FileDownloadThread[threadNum];//设置线程数量
try {
URL url = new URL(UrlStr);
URLConnection conn = url.openConnection();
fileSize = conn.getContentLength(); this.fileName = FileUtil.getFileName(UrlStr);
//只创建一个文件,saveFile下载内容
File saveFile = new File(savePath+"/"+fileName);
Log.e(TAG, "文件一共:"+fileSize+" savePath "+savePath+" fileName "+fileName); RandomAccessFile accessFile = new RandomAccessFile(saveFile,"rwd");
//设置本地文件的长度和下载文件相同
accessFile.setLength(fileSize);
accessFile.close();
//Handler更新UI,发送消息
sendMsg(FileUtil.startDownloadMeg);
//每块线程下载数据
blockSize = ((fileSize%threadNum)==)?(fileSize/threadNum):(fileSize/threadNum+);
Log.e(TAG, "每个线程分别下载 :"+blockSize); for (int i = ; i < threadNum; i++) {
int curThreadEndPosition = (i+)!=threadNum ? ((i+)*blockSize-) : fileSize;
FileDownloadThread fdt = new FileDownloadThread(url, saveFile, i*blockSize, curThreadEndPosition);
fdt.setName("thread"+i);
fdt.start();
fds[i]=fdt;
}
/**
* 获取数据,更新UI,直到所有下载线程都下载完成。
*/
boolean finished = false;
//开始时间,放在循环外,求解的usedTime就是总时间
long startTime = System.currentTimeMillis();
while(!finished)
{
downloadSize = ;
finished = true;
for (int i = ; i < fds.length; i++) {
downloadSize+= fds[i].getDownloadSize();
if(!fds[i].isFinished())
{
finished = false;
}
}
downloadPercent = (downloadSize*)/fileSize;
curTime = System.currentTimeMillis();
System.out.println("curTime = "+curTime+" downloadSize = "+downloadSize+" usedTime "+(int) ((curTime-startTime)/));
usedTime = (int) ((curTime-startTime)/); if(usedTime==)usedTime = ;
downloadSpeed = (downloadSize/usedTime)/;
sleep();/*1秒钟刷新一次界面*/
sendMsg(FileUtil.updateDownloadMeg);
}
Log.e(TAG, "下载完成");
completed = true;
sendMsg(FileUtil.endDownloadMeg);
} catch (Exception e) {
Log.e(TAG, "multi file error Exception "+e.getMessage());
e.printStackTrace();
}
super.run();
}
/**
* 得到文件的大小
* @return
*/
public int getFileSize()
{
return this.fileSize;
}
/**
* 得到已经下载的数量
* @return
*/
public int getDownloadSize()
{
return this.downloadSize;
}
/**
* 获取下载百分比
* @return
*/
public int getDownloadPercent(){
return this.downloadPercent;
}
/**
* 获取下载速度
* @return
*/
public int getDownloadSpeed(){
return this.downloadSpeed;
}
/**
* 修改默认线程数
* @param threadNum
*/
public void setThreadNum(int threadNum){
this.threadNum = threadNum;
}
/**
* 分块下载完成的标志
* @return
*/
public boolean isCompleted(){
return this.completed;
}
@Override
public String toString() {
return "MultiThreadDownload [threadNum=" + threadNum + ", fileSize="
+ fileSize + ", UrlStr=" + UrlStr + ", ThreadNo=" + ThreadNo
+ ", savePath=" + savePath + "]";
} /**
* 发送消息,用户提示
* */
private void sendMsg(int what)
{
Message msg = new Message();
msg.what = what;
handler.sendMessage(msg);
}
下载类:
public class FileDownloadThread extends Thread{
private static final String TAG = "FileDownloadThread";
/**缓冲区 */
private static final int BUFF_SIZE = ;
/**需要下载的URL*/
private URL url;
/**缓存的FIle*/
private File file;
/**开始位置*/
private int startPosition;
/**结束位置*/
private int endPosition;
/**当前位置*/
private int curPosition;
/**完成*/
private boolean finished = false;
/**已经下载多少*/
private int downloadSize = ;
/***
* 分块文件下载,可以创建多线程模式
* @param url 下载的URL
* @param file 下载的文件
* @param startPosition 开始位置
* @param endPosition 结束位置
*/
public FileDownloadThread(URL url, File file, int startPosition,
int endPosition) {
this.url = url;
this.file = file;
this.startPosition = startPosition;
this.curPosition = startPosition;
this.endPosition = endPosition;
Log.e(TAG, toString());
}
@Override
public void run() {
BufferedInputStream bis = null;
RandomAccessFile rAccessFile = null;
byte[] buf = new byte[BUFF_SIZE];
URLConnection conn = null;
try {
conn = url.openConnection();
conn.setConnectTimeout();//设置超时
conn.setReadTimeout();
conn.setAllowUserInteraction(true);
System.out.println(this.getName()+" startPosition "+startPosition+" endPosition "+endPosition);
conn.setRequestProperty("Range", "bytes="+(startPosition)+"-"+endPosition); //取剩余未下载的
rAccessFile = new RandomAccessFile(file,"rwd");//读写
//设置从什么位置开始写入数据
rAccessFile.seek(startPosition);
bis = new BufferedInputStream(conn.getInputStream(), BUFF_SIZE);
while(curPosition<endPosition) //当前位置小于结束位置 继续下载
{
int len = bis.read(buf,,BUFF_SIZE);
if(len==-) //下载完成
{
break;
}
rAccessFile.write(buf,,len);
curPosition = curPosition +len;
if(curPosition > endPosition)
{ //如果下载多了,则减去多余部分
System.out.println(" curPosition > endPosition !!!!");
int extraLen = curPosition-endPosition;
downloadSize += (len-extraLen+);
}else{
downloadSize+=len;
}
}
this.finished = true; //当前阶段下载完成
Log.e(TAG, "当前"+this.getName()+"下载完成");
} catch (Exception e) {
Log.e(TAG, "download error Exception "+e.getMessage());
e.printStackTrace();
}finally{
//关闭流
FileUtil.closeInputStream(bis);
try {
rAccessFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("AccessFile", "AccessFile IOException "+e.getMessage());
}
}
super.run();
}
/**
* 是否完成当前段下载完成
* @return
*/
public boolean isFinished() {
return finished;
}
/**
* 已经下载多少
* @return
*/
public int getDownloadSize() {
return downloadSize;
}
@Override
public String toString() {
return "FileDownloadThread [url=" + url + ", file=" + file
+ ", startPosition=" + startPosition + ", endPosition="
+ endPosition + ", curPosition=" + curPosition + ", finished="
+ finished + ", downloadSize=" + downloadSize + "]";
}
这里面多线程下载是分段下载,创建保存一个文件,子线程分别通过RandomAccessFile类进行写入操作。
Android 多线程下载 显示进度 速度的更多相关文章
- android程序---->android多线程下载(一)
多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务,可以使任务的执行速度变快.多线程的任务下载时常都会使用得到断点续传下载,就是我们在一次下载未结束时退出下载,第二次下载时会接着第一次 ...
- 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)
1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...
- Andoid 更好的Android多线程下载框架
概述 为什么是更好的Android多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先聊聊我们框架的特点: 多线程 多任务 断点续传 支持大文件 可以自定义下载数据库 高度 ...
- 更好的Android多线程下载框架
/** * 作者:Pich * 原文链接:http://me.woblog.cn/ * QQ群:129961195 * Github:https://github.com/lifengsofts */ ...
- (委托事件处理)关于多线程执行显示进度条的实例(转)&&线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。
关于多线程执行显示进度条的实例! 之前回答了一篇关于怎么在线程中操作进度条的帖子,估计有人看的不是很明白今天没事,写了一个小小的实例,很简单,就2个文件权当抛砖引玉,希望有更好解决方案的人发表一下意见 ...
- android程序---->android多线程下载(二)
上篇我们讲到了android中下载的断点续传问题,今天我们开始学习下载的多线程问题.本次的多线程源码下载:androdi中多线程下载的实现代码.有关断点续传的问题,请参见博客:android程序--- ...
- *Android 多线程下载 仿下载助手
今天带来一个多线程下载的 样例.先看一下效果.点击 下载 開始下载,同一时候显示下载进度.完成下载,变成程 安装,点击安装 提示 安装应用. 界面效果 线程池 ThreadPoolExecutor , ...
- 赵雅智_android多线程下载带进度条
progressBar说明 在某些操作的进度中的可视指示器,为用户呈现操作的进度,还它有一个次要的进度条,用来显示中间进度,如在流媒体播放的缓冲区的进度. 一个进度条也可不确定其进度.在不确定模式下, ...
- *Android 多线程下载 仿下载助手(改进版)
首先声明一点: 这里的多线程下载 并非指的 多个线程下载一个 文件.而是 每一个线程 负责一个文件. 真正的多线程 希望后面能给大家带来. ------------- 欢迎 爱学习的小伙伴 加群 ...
随机推荐
- Linux vi命令快操作汇总
第一部份:一般指令模式可用的按钮說明,游标移动.复制粘贴.搜寻取代等 一.移动游标的方法h 或 向左方向鍵(←) 游标向左移动一个字节j 或 向下方向鍵(↓) 游标向下移动一个字节k 或 向上方向 ...
- 如何像Uber一样给工程师派单 解放外包落后的生产力
2014年,陈柯好的第一个创业项目失败,半年之内,陈柯好以技术合伙人的方式游走于旅游.电商.团购.票务等各种领域.正当他对职业方向感到迷茫时,“大众创业.万众创新”的口号被提了出来 一时间,技术需求被 ...
- Centos7下 yum安装php扩展
linux下, 使用thinkphp的模板标签,如 eq, gt, volist defined, present , empty等 标签时, 报错: used undefined function ...
- python与图灵机器人交互(ITCHAT版本)
#!/usr/bin/env python#-*- coding:utf-8 -*- @Author : wujf @Time:2018/9/5 17:42import requestsimport ...
- Css进阶练习(实现抽屉网样式布局)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Project Euler 44 Sub-string divisibility( 二分 )
题意:五边形数由公式Pn=n(3n−1)/2生成,在所有和差均为五边形数的五边形数对Pj和Pk中,找出使D = |Pk − Pj|最小的一对:此时D的值是多少? 思路:二分找和差 /********* ...
- [USACO4.2] 草地排水 Drainage Ditches (最大流)
题目背景 在农夫约翰的农场上,每逢下雨,贝茜最喜欢的三叶草地就积聚了一潭水.这意味着草地被水淹没了,并且小草要继续生长还要花相当长一段时间.因此,农夫约翰修建了一套排水系统来使贝茜的草地免除被大水淹没 ...
- weblogic11g 密码忘记肿么办?
今天小编在用 weblogic 时,把密码忘记了,肿么办呢!很是着急,还不想重新建空间.那就跟我做下面的操作吧! %DOMAIN_HOME%为你 weblogic base_domain 安装目录:我 ...
- js区分ie不同版本
方法1 js中 if(window.ActiveXObject)//判断浏览器是否属于IE { var browser=navigator.appName var b_version=navigat ...
- rabbitMQ学习笔记(六) topic类型消息。
上一节中使用了消息路由,消费者可以选择性的接收消息. 但是这样还是不够灵活. 比如某个消费者要订阅娱乐新闻消息 . 包括新浪.网易.腾讯的娱乐新闻.那么消费者就需要绑定三次,分别绑定这三个网站的消息类 ...