android多線程斷點(diǎn)下載-帶進(jìn)度條和百分比進(jìn)度顯示效果
android多線程斷點(diǎn)下載,帶進(jìn)度條和百分比顯示,斷點(diǎn)下載的臨時(shí)數(shù)據(jù)保存到SD卡的文本文檔中,建議可以保存到本地?cái)?shù)據(jù)庫中,這樣可以提高存取效率,從而提高系統(tǒng)性能。
效果:
打開軟件:

下載中:

下載完畢:

附代碼如下:
package com.yy.multiDownloadOfBreakPoint;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
/**
* 多線程斷點(diǎn)下載實(shí)例
* @author YUANYUAN
*
*/
public class MainActivity extends Activity {
//下載所使用的線程數(shù)
protected static final int threadCount = 3;
//下載完畢的標(biāo)記
public static final int downloadOver = 1;
//更新下載進(jìn)度標(biāo)記
public static final int UPDATE_PROGRESS = 0;
//下載資源的路徑輸入框
private EditText et_path;
//下載的進(jìn)度條
private ProgressBar pb;
//進(jìn)度顯示
private TextView tv_pb;
//當(dāng)前累計(jì)下載的數(shù)據(jù)
int curDownCount=0;
//當(dāng)前活動(dòng)的下載線程數(shù)
protected static int activeThread;
//加入消息處理機(jī)制
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case downloadOver:
Toast.makeText(MainActivity.this, "文件已下載完畢!", Toast.LENGTH_LONG).show();
tv_pb.setText("下載完成");
break;
case UPDATE_PROGRESS:
//更新進(jìn)度顯示
tv_pb.setText("當(dāng)前進(jìn)度:"+(pb.getProgress()*100/pb.getMax())+"%");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_path=(EditText) findViewById(R.id.et_path);
et_path.setText("http://192.168.2.114:8080/sqlite.exe");
pb=(ProgressBar) findViewById(R.id.pb);
tv_pb=(TextView) findViewById(R.id.tv_pb);
}
/**
* 開始下載
* @param view
*/
public void down(View view){
//獲取下載資源的路徑
final String path=et_path.getText().toString().trim();
//判斷資源路徑是否為空
if (TextUtils.isEmpty(path)) {
Toast.makeText(this, "請(qǐng)輸入下載資源的路徑", Toast.LENGTH_LONG).show();
return;
}
//開啟一個(gè)線程進(jìn)行下載
new Thread(){
public void run() {
try {
//構(gòu)造URL地址
URL url=new URL(path);
//打開連接
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//設(shè)置請(qǐng)求超時(shí)的時(shí)間
conn.setConnectTimeout(5000);
//設(shè)置請(qǐng)求方式
conn.setRequestMethod("GET");
//獲取相應(yīng)碼
int code=conn.getResponseCode();
if (code==200) {//請(qǐng)求成功
//獲取請(qǐng)求數(shù)據(jù)的長度
int length=conn.getContentLength();
//設(shè)置進(jìn)度條的最大值
pb.setMax(length);
//在客戶端創(chuàng)建一個(gè)跟服務(wù)器文件大小相同的臨時(shí)文件
RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");
//指定臨時(shí)文件的長度
raf.setLength(length);
raf.close();
//假設(shè)3個(gè)線程去下載資源
//平均每一個(gè)線程要下載的文件的大小
int blockSize=length/threadCount;
for (int threadId = 1; threadId <= threadCount; threadId++) {
//當(dāng)前線程下載數(shù)據(jù)的開始位置
int startIndex=blockSize*(threadId-1);
//當(dāng)前線程下載數(shù)據(jù)的結(jié)束位置
int endIndex=blockSize*threadId-1;
//確定最后一個(gè)線程要下載數(shù)據(jù)的最大位置
if (threadId==threadCount) {
endIndex=length;
}
//顯示下載數(shù)據(jù)的區(qū)間
System.out.println("線程【"+threadId+"】開始下載:"+startIndex+"---->"+endIndex);
//開啟下載的子線程
new DownloadThread(path, threadId, startIndex, endIndex).start();
//當(dāng)前下載活動(dòng)的線程數(shù)加1
activeThread++;
System.out.println("當(dāng)前活動(dòng)的線程數(shù):"+activeThread);
}
}else{//請(qǐng)求失敗
System.out.println("服務(wù)器異常,下載失?。?);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("服務(wù)器異常,下載失??!");
}
};
}.start();
}
/**
* 下載文件的子線程 每一個(gè)文件都下載對(duì)應(yīng)的數(shù)據(jù)
* @author YUANYUAN
*
*/
public class DownloadThread extends Thread{
private String path;
private int threadId;
private int startIndex;
private int endIndex;
/**
* 構(gòu)造方法
* @param path 下載文件的路徑
* @param threadId 下載文件的線程
* @param startIndex 下載文件開始的位置
* @param endIndex 下載文件結(jié)束的位置
*/
public DownloadThread(String path, int threadId, int startIndex,
int endIndex) {
this.path = path;
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void run() {
//構(gòu)造URL地址
try {
File tempFile=new File("sdcard/"+threadId+".txt");
//檢查記錄是否存在,如果存在讀取數(shù)據(jù),設(shè)置真實(shí)下載開始的位置
if (tempFile.exists()) {
FileInputStream fis=new FileInputStream(tempFile);
byte[] temp=new byte[1024];
int length=fis.read(temp);
//讀取到已經(jīng)下載的位置
int downloadNewIndex=Integer.parseInt(new String(temp, 0, length));
//計(jì)算出已經(jīng)下載的數(shù)據(jù)長度
int areadyDown=downloadNewIndex-startIndex;
//累加已經(jīng)下載的數(shù)據(jù)量
curDownCount+=areadyDown;
//設(shè)置進(jìn)度條已經(jīng)下載的數(shù)據(jù)量
pb.setProgress(curDownCount);
//設(shè)置重新開始下載的開始位置
startIndex=downloadNewIndex;
fis.close();
//顯示真實(shí)下載數(shù)據(jù)的區(qū)間
System.out.println("線程【"+threadId+"】真實(shí)開始下載數(shù)據(jù)區(qū)間:"+startIndex+"---->"+endIndex);
}
URL url = new URL(path);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//設(shè)置請(qǐng)求屬性,請(qǐng)求部分資源
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
int code=conn.getResponseCode();
if (code==206) {//下載部分資源,正常返回的狀態(tài)碼為206
InputStream is=conn.getInputStream();//已經(jīng)設(shè)置了請(qǐng)求的位置,所以返回的是對(duì)應(yīng)的部分資源
//構(gòu)建隨機(jī)訪問文件
RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");
//設(shè)置 每一個(gè)線程隨機(jī)寫文件開始的位置
raf.seek(startIndex);
//開始寫文件
int len=0;
byte[] buffer=new byte[1024];
//該線程已經(jīng)下載數(shù)據(jù)的長度
int total=0;
while((len=is.read(buffer))!=-1){//讀取輸入流
//記錄當(dāng)前線程已下載數(shù)據(jù)的長度
RandomAccessFile file=new RandomAccessFile("sdcard/"+threadId+".txt","rwd");
raf.write(buffer,0,len);//寫文件
total+=len;//更新該線程已下載數(shù)據(jù)的總長度
System.out.println("線程【"+threadId+"】已下載數(shù)據(jù):"+(total+startIndex));
//將已下載數(shù)據(jù)的位置記錄寫入到文件
file.write((startIndex+total+"").getBytes());
//累加已經(jīng)下載的數(shù)據(jù)量
curDownCount+=len;
//更新進(jìn)度條【進(jìn)度條的更新可以在非UI線程直接更新,具體見底層源代碼】
pb.setProgress(curDownCount);
//更新下載進(jìn)度
Message msg=Message.obtain();
msg.what=UPDATE_PROGRESS;
handler.sendMessage(msg);
file.close();
}
is.close();
raf.close();
//提示下載完畢
System.out.println("線程【"+threadId+"】下載完畢");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("線程【"+threadId+"】下載出現(xiàn)異常!!");
}finally{
//活動(dòng)的線程數(shù)減少
activeThread--;
if (activeThread==0) {
for (int i = 1; i <= threadCount; i++) {
File tempFile=new File("sdcard/"+i+".txt");
tempFile.delete();
}
System.out.println("下載完畢,已清除全部臨時(shí)文件");
//界面消息提示下載完畢
Message msg=new Message();
msg.what=downloadOver;
handler.sendMessage(msg);
}
}
}
}
}
以上這篇android多線程斷點(diǎn)下載-帶進(jìn)度條和百分比進(jìn)度顯示效果就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Android 下載文件通知欄顯示進(jìn)度條功能的實(shí)例代碼
- Android編程實(shí)現(xiàn)顯示在標(biāo)題上的進(jìn)度條功能【附源碼下載】
- Android實(shí)現(xiàn)標(biāo)題上顯示隱藏進(jìn)度條效果
- Android多線程+單線程+斷點(diǎn)續(xù)傳+進(jìn)度條顯示下載功能
- Android自定義多節(jié)點(diǎn)進(jìn)度條顯示的實(shí)現(xiàn)代碼(附源碼)
- Android使用AsyncTask下載圖片并顯示進(jìn)度條功能
- Android 進(jìn)度條顯示在標(biāo)題欄的實(shí)現(xiàn)方法
- Android上傳文件到服務(wù)端并顯示進(jìn)度條
- Android實(shí)現(xiàn)支持進(jìn)度條顯示的短信備份工具類
- android實(shí)現(xiàn)動(dòng)態(tài)顯示隱藏進(jìn)度條
相關(guān)文章
Android實(shí)現(xiàn)滑動(dòng)刪除操作(PopupWindow)
這篇文章主要介紹了Android ListView結(jié)合PopupWindow實(shí)現(xiàn)滑動(dòng)刪除的相關(guān)資料,需要的朋友可以參考下2016-07-07
Android MenuItem 自定義長按事件的實(shí)現(xiàn)
這篇文章主要介紹了Android MenuItem 自定義長按事件的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
Android實(shí)戰(zhàn)教程第六篇之一鍵鎖屏應(yīng)用問題解決
這篇文章主要為大家詳細(xì)介紹了Android一鍵鎖屏應(yīng)用開發(fā)過程中出現(xiàn)問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Flutter List數(shù)組避免插入重復(fù)數(shù)據(jù)的實(shí)現(xiàn)
這篇文章主要介紹了Flutter List數(shù)組避免插入重復(fù)數(shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Android自定義view系列之99.99%實(shí)現(xiàn)QQ側(cè)滑刪除效果實(shí)例代碼詳解
這篇文章給大家介紹android自定義view系列之99.99%實(shí)現(xiàn)QQ側(cè)滑刪除效果,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友參考下吧2016-09-09
Flutter Http分塊下載與斷點(diǎn)續(xù)傳的實(shí)現(xiàn)
這篇文章主要介紹了Flutter Http分塊下載與斷點(diǎn)續(xù)傳的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
Android LeakCanary檢測(cè)內(nèi)存泄露原理
這篇文章主要介紹了分析LeakCanary檢測(cè)內(nèi)存泄露原理,幫助大家更好的理解和學(xué)習(xí)使用Android開發(fā),感興趣的朋友可以了解下2021-03-03
Android編譯出現(xiàn)Warning:Mapping?new?ns?to?old?ns報(bào)錯(cuò)的解決方案
android在編譯的過程中難免會(huì)出現(xiàn)些錯(cuò)誤,下面這篇文章主要給大家介紹了關(guān)于Android編譯出現(xiàn)Warning:Mapping?new?ns?to?old?ns報(bào)錯(cuò)的解決方案,需要的朋友可以參考下2023-02-02
Android 判斷當(dāng)前語言環(huán)境是否是中文環(huán)境
本文主要介紹了Android 判斷當(dāng)前語言環(huán)境是否是中文環(huán)境的方法。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-04-04

