Android实现多线程断点下载的方法
本文实例讲述了Android实现多线程断点下载的方法。分享给大家供大家参考。具体实现方法如下:
packagecn.itcast.download;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.RandomAccessFile;
importjava.net.HttpURLConnection;
importjava.net.MalformedURLException;
importjava.net.ProtocolException;
importjava.net.URL;
importcn.itcast.mutiledownload.StreamTool;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.ProgressBar;
importandroid.widget.TextView;
importandroid.widget.Toast;
publicclassMutiledownloadActivityextendsActivityimplementsOnClickListener{
privateProgressBarpb;
privateButtonbt;
privateTextViewtv;
privateEditTextet;
booleanflag=true;
booleanstopflag=false;
privateHandlerhandler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
pb.setProgress(total);
intmax=pb.getMax();
if(total>=(max-1)){
total=max;
flag=false;
}
intresult=total*100/max;
tv.setText("当前进度:"+result+"%");
super.handleMessage(msg);
}
};
inttotal=0;
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pb=(ProgressBar)this.findViewById(R.id.pb);
bt=(Button)this.findViewById(R.id.bt);
tv=(TextView)this.findViewById(R.id.tv_process);
et=(EditText)this.findViewById(R.id.et);
bt.setOnClickListener(this);
}
@Override
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.bt:
//创建一个子线程定期的更新ui
if("开始下载".equals(bt.getText().toString())){
bt.setText("暂停");
stopflag=false;//开始下载
}
else{
bt.setText("开始下载");
stopflag=true;
}
newThread(){
@Override
publicvoidrun(){
super.run();
while(flag){
try{
sleep(1000);
//如果total>=文件长度
Messagemsg=newMessage();
handler.sendMessage(msg);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}.start();
//开始执行下载的操作
Stringpath=et.getText().toString().trim();
if("".equals(path)){
Toast.makeText(this,"路径不能为空",1).show();
return;
}
try{
URLurl=newURL(path);
HttpURLConnectionconn=(HttpURLConnection)url
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setRequestProperty("User-Agent",
"Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1)");
intcode=conn.getResponseCode();
if(code==200){
intlen=conn.getContentLength();
RandomAccessFilefile=newRandomAccessFile(
"/mnt/sdcard/"+getFilenName(path),"rwd");
//1.设置本地文件大小跟服务器的文件大小一致
file.setLength(len);
//设置进度条的最大值
pb.setMax(len);
//2.假设开启3个线程
intthreadnumber=3;
intblocksize=len/threadnumber;
/**
*线程10~blocksize线程21*bolocksize~2*blocksize线程3
*2*blocksize~文件末尾
*/
for(inti=0;i<threadnumber;i++){
intstartposition=i*blocksize;
intendpositon=(i+1)*blocksize;
if(i==(threadnumber-1)){
//最后一个线程
endpositon=len;
}
DownLoadTasktask=newDownLoadTask(i,path,
startposition,endpositon);
task.start();
}
}
}catch(Exceptione){
Toast.makeText(this,"下载出现异常",0).show();
e.printStackTrace();
}
break;
}
}
classDownLoadTaskextendsThread{
intthreadid;
Stringfilepath;
intstartposition;
intendpositon;
publicDownLoadTask(intthreadid,Stringfilepath,intstartposition,
intendpositon){
this.threadid=threadid;
this.filepath=filepath;
this.startposition=startposition;
this.endpositon=endpositon;
}
@Override
publicvoidrun(){
try{
Filepostionfile=newFile("/mnt/sdcard/"+threadid+".txt");
URLurl=newURL(filepath);
HttpURLConnectionconn=(HttpURLConnection)url
.openConnection();
System.out.println("线程"+threadid+"正在下载"+"开始位置:"
+startposition+"结束位置"+endpositon);
if(postionfile.exists()){
FileInputStreamfis=newFileInputStream(postionfile);
byte[]result=StreamTool.getBytes(fis);
Stringstr=newString(result);
if(!"".equals(str)){
intnewstartposition=Integer.parseInt(str);
if(newstartposition>startposition){
startposition=newstartposition;
}
}
}
//"Range","bytes=2097152-4194303")
conn.setRequestProperty("Range","bytes="+startposition+"-"
+endpositon);
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setRequestProperty("User-Agent",
"Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1)");
InputStreamis=conn.getInputStream();
RandomAccessFilefile=newRandomAccessFile("/mnt/sdcard/"
+getFilenName(filepath),"rwd");
//设置数据从文件哪个位置开始写
file.seek(startposition);
byte[]buffer=newbyte[1024];
intlen=0;
//代表当前读到的服务器数据的位置,同时这个值已经存储的文件的位置
intcurrentPostion=startposition;
//创建一个文件对象,记录当前某个文件的下载位置
while((len=is.read(buffer))!=-1){
if(stopflag){
return;
}
file.write(buffer,0,len);
synchronized(MutiledownloadActivity.this){
total+=len;
}
currentPostion+=len;
//需要把currentPostion信息给持久化到存储设备
Stringposition=currentPostion+"";
FileOutputStreamfos=newFileOutputStream(postionfile);
fos.write(position.getBytes());
fos.flush();
fos.close();
}
file.close();
System.out.println("线程"+threadid+"下载完毕");
//当线程下载完毕后把文件删除掉
if(postionfile.exists()){
postionfile.delete();
}
}catch(Exceptione){
e.printStackTrace();
}
super.run();
}
}
publicStringgetFilenName(Stringpath){
intstart=path.lastIndexOf("/")+1;
returnpath.substring(start,path.length());
}
}
希望本文所述对大家的Android程序设计有所帮助。