隨筆,註釋寫得很清楚了,如有不明白的地方,相互交流.....
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;
}
}
效果圖: