再设置它的布局内容为ProgressBar
//連接服務器
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
//獲取返回狀態碼
int code = conn.getResponseCode();
if(code == 200) {
//請求成功,獲取服務器返回文件的大小
int length = conn.getContentLength();
Log.d("文件大小為:", length + "");
}
//請求成功,獲取服務器返回文件的大小
int length = conn.getContentLength();
LogUtil.d("文件大小為:", length + "");
RandomAccessFile raf = new RandomAccessFile(sdPath + "/" + getFileName(urlStr), "rw");
//為將要下載的文件預先分配空間
raf.setLength(length);
//開啟多個線程,分段下載
for(int i=0; i//計算每個線程應該下載的字節範圍
int startIndex = i * blockSize;
int endIndex = (i + 1) * blockSize - 1;
//如果是最後一個線程,就下載到文件末尾
if(i == threadCount - 1) {
endIndex = length - 1;
}
new DownLoadThread(startIndex, endIndex, i).start();
}
HttpURLConnection conn = connct2Server(urlStr);
//設置Range頭屬性
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
if(code == 206) {
//部份資源請求成功
LogUtil.d("線程" + threadId + "請求成功", code + "");
//拿到要寫入的文件
RandomAccessFile raf = new RandomAccessFile(sdPath + "/" + getFileName(urlStr), "rw");
//設置要寫入的文件光標位置
raf.seek(startIndex);
//獲取輸入流并寫入文件
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024 * 1024];
int len = 0;
while((len = bis.read(buffer)) != -1) {
raf.write(buffer, 0, len);
}
raf.close();
bis.close();
}
//下載完畢后提示
synchronized (DownLoadThread.class) {
threadCount --;
if(threadCount == 0) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "下載完畢", 1).show();
}
});
}
}
此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。
构造方法:RandomAccessFile raf = new RandomAccessFile(sdPath + "/" + getFileName(urlStr), "rw");
写入方法:raf.write(buffer, 0, len);
设置文件指针位置:raf.seek(startIndex);
当线程被结束时,把当前下载到的文件字节下标保存到文件中。
当下载线程再次开启时,从文件中读取下载到的位置,从这里开始下载。
fos.close();
//使用原来的方法可能导致没有来得及保存
RandomAccessFile pos = new RandomAccessFile(sdDir + "/" + getFileName(path) + "Thread-" + threadId + ".txt", "rwd");
pos.write(String.valueOf(currentTreadPostion).getBytes());
pos.close();
把从文件读取出来 的位置赋值给startIndex
//打开保存断点位置的文件
File file = new File(sdDir + "/" + getFileName(path) + "Thread-" + threadId + ".txt");
if(file.exists() && file.length() > 0) {
//说明中断过,把上次断点位置读取出来
FileInputStream fis = new FileInputStream(file);
BufferedReader br= new BufferedReader(new InputStreamReader(fis));
String lastPos = br.readLine();
//获取上次下载的进度条位置
pbLastPosition = Integer.parseInt(lastPos) - startIndex;
//改变下一次的开始位置
startIndex = Integer.parseInt(lastPos);
br.close();
}
每下载一次就设置一次进度条的位置
//进度条的初始化
ll_progress.removeAllViews();//加载进度条之前先清除之前的进度条
//动态加载进度条
for(int i=0; i//使用打气筒服务用布局文件创建一个进度条对象
ProgressBar pb = (ProgressBar) View.inflate(getApplicationContext(), R.layout.pb, null);
pb.setMax(100);//设置进度条的最大值
pb.setProgress(50);//设置进度条的当前进度
pbs.add(pb);//进度条对象添加 到集合
ll_progress.addView(pb);//添加一个进度条到总布局
}
//进度条的更新,子线程可以更新进度条
pbs.get(threadId).setMax(pbMax);
pbs.get(threadId).setProgress(pbLastPosition + total);
了解了多线程断点下载的原理,在实际应用中更多的是使用开源项目,可以大大降低成本,节省时间。
使用方法如下 :
导入xUtils包,使用就行
path = tv_url.getText().toString().trim();
//创建HttpUtils对象
HttpUtils httpUtils = new HttpUtils();
//autoResume支持断点续传
httpUtils.download(path, "mnt/sdcard/haha.exe", true, new RequestCallBack() {
@Override
public void onSuccess(ResponseInfo responseInfo) {
Toast.makeText(getApplicationContext(), "下载成功", 1).show();
}
//更新进度条的方法
@Override
public void onLoading(long total, long current, boolean isUploading) {
pb.setMax((int)total);
pb.setProgress((int)current);
super.onLoading(total, current, isUploading);
}
@Override
public void onFailure(HttpException error, String msg) {
}
http://download.csdn.net/detail/jianbiao426/9553462