随笔,注释写得很清楚了,如有不明白的地方,相互交流.....
package com.download.service;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
/**
* 下载线程
* @author dream
*
*/
public class DownThread extends Thread {
/**
* 保存文件路径
*/
private String filepath;
/**
* 停止线程标识
*/
private boolean stopFlag=false;
/**
* 下载开始位置
*/
private int startposition;
/**
* 下载结束位置
*/
private int endposition;
/**
* 下载链接
*/
private String url;
/**
* 下载服务类
*/
private HttpDownService hds;
/**
* 线程下载完毕标识
*/
private boolean success=false;
/**
* 当前线程下载量
*/
private int currentjd=0;
/**
* 获取当前线程下载量
* @return
*/
public int getCurrentjd() {
return currentjd;
}
/**
* 当前线程是否下载完毕
* @return
*/
public boolean isSuccess() {
return success;
}
@Override
public void run() {
BufferedReader br=null;
RandomAccessFile fout=null;
int oldposition=0;
try{
File fstate=null;
if(FileUtil.Exists(HttpDownService.DIR, this.getName()+".txt")){
fstate=FileUtil.createFile(HttpDownService.DIR, this.getName()+".txt");
br=new BufferedReader(new FileReader(fstate));
String line=br.readLine();
br.close();
if(line!=null){
line=line.trim();
//是否已完成下载
if("complete".equals(line)){
this.currentjd=endposition-startposition;
this.success=true;
return;
}else{
int newposition=Integer.parseInt(line);
//若当前开始位置大于下载开始位置则保存下载开始位置(用于计算下载量)
if(newposition>startposition){
oldposition=startposition;
startposition=newposition;
}
}
}
}else{
fstate=FileUtil.createFile(HttpDownService.DIR, this.getName()+".txt");
oldposition=startposition;
}
fout= new RandomAccessFile(this.filepath, "rwd");
fout.seek(startposition);
HttpURLConnection http=DownUtil.getDownConnection(this.url, this.startposition, this.endposition);
InputStream in= http.getInputStream();
byte[] buff=new byte[1024];
int len=0;
while((len=in.read(buff, 0, 1024))>0){
success=false;
if(stopFlag){
if(fout!=null){
fout.close();
return;
}
return;
}
fout.write(buff, 0, len);
//当前线程下载进度
startposition=startposition+len;
int jd=startposition-oldposition;
//刷新当前进度消息
this.currentjd=jd;
//把进度存储到存储设备中去
FileOutputStream fw=new FileOutputStream(fstate);
fw.write((startposition+"").getBytes());
fw.close();
}
//线程下载完毕
fout.close();
//将线程下载完毕信息写到磁盘
FileOutputStream fw=new FileOutputStream(fstate);
fw.write(("complete").getBytes());
fw.close();
//下载完毕信号
this.success=true;
//更新进度信息
this.currentjd=endposition-oldposition;
}catch(Exception e){
throw new RuntimeException(e);
}finally{
try{
if(fout!=null){
fout.close();
}
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
public DownThread(String randomFile,String threadName,int startposition,int endposition,String url,HttpDownService hds){
this.filepath=randomFile;
this.setName(threadName);
this.startposition=startposition;
this.endposition=endposition;
this.url=url;
this.hds=hds;
}
/**
* 停止下载线程
*/
public void StopThread(){
this.stopFlag=true;
}
}
package com.download.service;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 计算各个线程下载开始和结束位置
* @author dream
*
*/
public class DownUtil {
public static long getContentLength(String url){
try{
HttpURLConnection http= DownUtil.getDownConnection(url);
long len=http.getContentLength();
http.disconnect();
return len;
}catch(Exception e){
throw new RuntimeException(e);
}
}
/**
* 获取Http连接
* @param url
* @return
*/
public static HttpURLConnection getDownConnection(String url){
try{
URL hurl=new URL(url);
HttpURLConnection http= (HttpURLConnection) hurl.openConnection();
http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; InfoPath.3; MALCJS)");
http.setRequestProperty("Connection", "Keep-Alive");
http.setRequestMethod("GET");
return http;
}catch(Exception e){
throw new RuntimeException(e);
}
}
/***
* 获取Http连接
* @param url
* @param startposition
* @param endposition
* @return
*/
public static HttpURLConnection getDownConnection(String url,long startposition,long endposition){
try{
URL hurl=new URL(url);
HttpURLConnection http= (HttpURLConnection) hurl.openConnection();
http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; InfoPath.3; MALCJS)");
http.setRequestProperty("Connection", "Keep-Alive");
http.setRequestMethod("GET");
http.setRequestProperty("Range", "bytes=" + startposition + "-"+ endposition);
return http;
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
package com.download.service;
import java.io.File;
import android.os.Environment;
public class FileUtil {
public static File createFile(String dir,String filename){
Environment ev=new Environment();
String diry= ev.getExternalStorageDirectory().getPath()+"/"+dir;
File fdir=new File(diry);
if(!fdir.exists()){
fdir.mkdirs();
}
String path= ev.getExternalStorageDirectory().getPath()+"/"+dir+"/"+filename;
File file=new File(path);
try{
if(file.exists()){
return file;
}else{
file.createNewFile();
return file;
}
}catch(Exception e){
throw new RuntimeException(e);
}
}
public static boolean Exists(String dir,String filename){
Environment ev=new Environment();
String path= ev.getExternalStorageDirectory().getPath()+"/"+dir+"/"+filename;
File file=new File(path);
return file.exists();
}
}
package com.download.service;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import android.os.Handler;
/**
* 多线程下载/断点续
* @author dream
*
*/
public class HttpDownService {
/**
* 线程状态记录文件目录(处于SD卡)
*/
public static final String DIR="downtemp";
/**
* 下载进度
*/
private int jd=0;
/**
* 下载链接
*/
private String url;
/**
* 总大小
*/
private int total;
/**
* 获取总大小
* @return
*/
public int getTotal() {
return total;
}
/**
* 设置总大小
* @param total
*/
public void setTotal(int total) {
this.total = total;
}
/**
* 开启的下载线程数量(数量越多下载效率越高)
*/
private int threadcount;
/**
* 保存文件路径
*/
private String filepath;
/**
* 下载线程集合
*/
private List<DownThread> list;
/**
* 界面UI handler处理
*/
private Handler handler;
/**
* 下载状态信息处理
*/
private ProcessHandler ph;
/**
* 扫描下载状态的线程
*/
private ScanThread st;
public int getJd() {
return this.jd;
}
public List<DownThread> getList() {
return list;
}
/**
* 设置当前下载进度(线程安全)
* @param jd
* @param oldjd
*/
public void setJd(int jd,int oldjd) {
synchronized (this) {
this.jd=this.jd-oldjd;
this.jd = this.jd+ jd;
}
}
public HttpDownService(String url,String filepath,Handler handler,ProcessHandler ph){
this.url=url;
this.filepath=filepath;
this.total=(int) DownUtil.getContentLength(url);
this.handler=handler;
this.ph=ph;
}
/***
* 启动下载
* @param threadCount
*/
public void StartDown(int threadCount){
this.threadcount=threadCount;
if(this.list==null){
this.list=new ArrayList<DownThread>();
}
this.list.clear();
int blocksize=this.total/this.threadcount;
for(int i=0;i<this.threadcount;i++){
int startposition=i*blocksize;
int endposition=(i+1)*blocksize;
if(this.threadcount-i==1){
endposition=this.total;
}
DownThread dt=new DownThread(this.filepath, "e"+i, startposition,endposition, this.url, this);
dt.start();
this.list.add(dt);
}
st=new ScanThread(this, this.handler, this.ph);
st.start();
}
/**
* 停止下载
*/
public void StopDown(){
for(DownThread dt:this.list){
dt.StopThread();
}
this.st.StopThread();
}
/**
* 下载是否完成
* @return
*/
public boolean IsDownComplete(){
boolean ret=false;
int i=0;
for(DownThread dt:this.list){
if(dt.isSuccess()){
i++;
}
}
if(this.threadcount==i){
ret=true;
}
return ret;
}
/**
* 下载进度
* @return
*/
public int DownProcess(){
int process=0;
for(DownThread dt:this.list){
process=process+dt.getCurrentjd();
}
return process;
}
/**
* 删除临时文件
*/
public void DeleteStateFile(){
for(DownThread dt:this.list){
File file=FileUtil.createFile(HttpDownService.DIR, dt.getName()+".txt");
if(file.exists()){
file.delete();
}
}
}
}
package com.download.service;
import android.os.Handler;
/**
* 下载信息转发处理
* @author dream
*
*/
public interface ProcessHandler {
public void Process(Handler handler,int total,int current,boolean iscomplete);
}
package com.download.service;
import android.os.Handler;
import android.os.Message;
/**
* 扫描下载状态,并转发状态信息
* @author dream
*
*/
public class ScanThread extends Thread {
/**
* 下载服务类
*/
private HttpDownService hds;
/**
* 界面UI Handler处理
*/
private Handler handler;
/**
* 线程下载状态处理器
*/
private ProcessHandler ph;
/**
* 停止线程标识
*/
private boolean Stopflag=false;
public ScanThread(HttpDownService hds,Handler handler,ProcessHandler ph){
this.handler=handler;
this.hds=hds;
this.ph=ph;
}
@Override
public void run() {
this.Stopflag=false;
try{
while(!Stopflag){
Thread.sleep(10);
this.ph.Process(this.handler, this.hds.getTotal(),this.hds.DownProcess(),this.hds.IsDownComplete());
//当所有线程下载完毕时,转发下载完毕信息
if(this.hds.IsDownComplete()){
this.ph.Process(this.handler, this.hds.getTotal(),this.hds.DownProcess(),this.hds.IsDownComplete());
this.hds.DeleteStateFile();
this.Stopflag=true;
return;
}
}
}catch(Exception e){
throw new RuntimeException(e);
}
}
/**
* 停止线程
*/
public void StopThread(){
this.Stopflag=true;
}
}
效果图: