package com.jy.day15installapkmorethreaddownload;
import android.content.Context;
import android.util.Log;
import org.greenrobot.eventbus.EventBus;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class DownLoadMoreThread {
public static String TAG = "DownLoadMoreThread";
public static int thread_count = 5;
public static void httpDownLoadByMoreThreads(
final String apkUrl, final String savePath, final Context context){
ThreadManager.getInstance().execute(new Runnable() {
@Override
public void run() {
//計算每個線程要下載的模塊的開始位置和結(jié)束位置
try {
URL url= new URL(apkUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
int len = urlConnection.getContentLength();
EventBus.getDefault().post(new MsgE(0,len));//把文件的大小設(shè)置給進度條,保存一直,后面通過下載的數(shù)據(jù)的改變進度
////2.分配任務(wù),5個線程,
//假設(shè) 20個數(shù)據(jù):0-19
//線程0:0-3,線程1:4-7,線程2:8-11 ,...
int blockSize = len/thread_count;//得到每一個線程要下載的大小 4
//每次for循環(huán)計算出本次線程下載的數(shù)據(jù)的開始和結(jié)束位置
for (int i = 0; i < thread_count; i++) {
int start = iblockSize;//開始的位置
int end = (i+1)blockSize-1;//結(jié)束的位置
if(i == thread_count-1){//如果當前是最后一個線程赶袄,則下載剩下的所有數(shù)據(jù)
end = len-1;
}
//啟動一個線程進行下載贸宏,沒有斷點
// downThread(i,start,end,apkUrl,savePath,len);
//帶斷點續(xù)傳的
downThreadCut(i,start,end,apkUrl,savePath,context,len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public static void downThread(
final int i, final int start, final int end, final String apkUrl, final String savePath, final int max) {
ThreadManager.getInstance().execute(new Runnable() {
@Override
public void run() {
//進行下載
try {
URL url= new URL(apkUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
///設(shè)置請求部分資源 Range表示隨機位置 重點1
conn.setRequestProperty("Range","bytes="+start+"-"+end); //設(shè)置當前線程從start開始 到 end結(jié)束
int responseCode = conn.getResponseCode();
//HttpURLConnection.HTTP_PARTIAL 是 206煤辨,表示允許請求部分數(shù)據(jù)
if(responseCode == HttpURLConnection.HTTP_PARTIAL){
InputStream inputStream = conn.getInputStream();//得到本線程應(yīng)該讀取的部分數(shù)據(jù)
RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//創(chuàng)建可以讀寫的隨機流 rw表示可讀可寫
rf.seek(start);//把隨機流偏移到 應(yīng)該開始的位置
byte[] bytes = new byte[2048];
int len = 0;
int count = 0;
int totalCount = end-start+1;//計算出本線程應(yīng)該下載的大小
while((len = inputStream.read(bytes)) != -1){
rf.write(bytes,0,len);
count += len;
Log.d("MainActivity", "線程:"+i+",totalCount: "+totalCount+
",百分比:"+(float)count/totalCount+"厂镇,下載大小:"+count);
EventBus.getDefault().post(new MsgE(len,max));//把當前下載的長度發(fā)出去叁丧,Activity接收,顯示在進度條上
}
Log.i("MainActivity", "run: 線程"+i+"下載完畢");
inputStream.close();
rf.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public static void downThreadCut(
final int i, final int start, final int end, final String apkUrl, final String savePath, final Context context, final int max) {
ThreadManager.getInstance().execute(new Runnable() {
@Override
public void run() {
//進行下載
try {
URL url= new URL(apkUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//得到SharedPreferences保存的本線程上傳下載的位置
int currentPosition = start; //currentPosition當前下載的開始位置
int n = (int) SharedPreferencesUtils.getParam(context, "線程" + i, 0);
if(n == 0){
Log.i("MainActivity", "run: 第一次下載");
}else {//有值岳瞭,說明上次下載沒有完成歹袁,記錄了下載到的位置,從此下載
currentPosition = n;
Log.i("MainActivity", "run:線程"+i+" 接著上次下載,開始位置是:"+currentPosition);
}
///設(shè)置請求部分資源 Range表示隨機位置
conn.setRequestProperty("Range","bytes="+currentPosition+"-"+end); //設(shè)置當前線程從start開始 到 end結(jié)束
int responseCode = conn.getResponseCode();
//HttpURLConnection.HTTP_PARTIAL 是 206寝优,表示允許請求部分數(shù)據(jù)
if(responseCode == HttpURLConnection.HTTP_PARTIAL){
InputStream inputStream = conn.getInputStream();//得到本線程應(yīng)該讀取的部分數(shù)據(jù)
RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//創(chuàng)建可以讀寫的隨機流
rf.seek(currentPosition);//把隨機流偏移到 應(yīng)該開始的位置条舔,上次下載寫入的位置(下載了一部分)
byte[] bytes = new byte[2048];
int len = 0;
int count = currentPosition-start;//計算出已經(jīng)下載的大小
EventBus.getDefault().post(new MsgE(count,max));//把得到的舊進度,設(shè)置到進度條中
// myCallBack.setProgress2(count);//把已經(jīng)下載的數(shù)據(jù)量給進度條
int totalCount = end-start+1;//計算出本線程應(yīng)該下載的大小
while((len = inputStream.read(bytes)) != -1){
rf.write(bytes,0,len);
count += len;//記錄下載的大小
currentPosition += len;//把下載位置向前移動len乏矾,以為又下載了len長度的數(shù)據(jù)
Log.d("MainActivity", "線程:"+i+",totalCount: "+totalCount+
",百分比:"+(float)count/totalCount+"孟抗,下載大星ㄑ睢:"+count);
// myCallBack.setProgress2(len);//把新下載的數(shù)據(jù)量給進度條
//通過SharedPreferencesUtils記錄當前下載到的位置,供105行獲取使用凄硼,供下次下載使用
EventBus.getDefault().post(new MsgE(len,max));//把得到的新進度铅协,設(shè)置到進度條中
SharedPreferencesUtils.setParam(context,"線程"+i,currentPosition);
}
//本線程下載完畢,重新設(shè)置為0.下回重新下載
SharedPreferencesUtils.setParam(context,"線程"+i,0);
Log.i("MainActivity", "run: 線程"+i+"下載完畢");
inputStream.close();
rf.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}