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() {
//计算每个线程要下载的模块的开始位置和结束位置
try {
URL url= new URL(apkUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
int len = urlConnection.getContentLength();
EventBus.getDefault().post(new MsgE(0,len));//把文件的大小设置给进度条,保存一直,后面通过下载的数据的改变进度
////2.分配任务,5个线程,
//假设 20个数据:0-19
//线程0:0-3,线程1:4-7,线程2:8-11 ,...
int blockSize = len/thread_count;//得到每一个线程要下载的大小 4
//每次for循环计算出本次线程下载的数据的开始和结束位置
for (int i = 0; i < thread_count; i++) {
int start = iblockSize;//开始的位置
int end = (i+1)blockSize-1;//结束的位置
if(i == thread_count-1){//如果当前是最后一个线程,则下载剩下的所有数据
end = len-1;
}
//启动一个线程进行下载,没有断点
// downThread(i,start,end,apkUrl,savePath,len);
//带断点续传的
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();
///设置请求部分资源 Range表示随机位置 重点1
conn.setRequestProperty("Range","bytes="+start+"-"+end); //设置当前线程从start开始 到 end结束
int responseCode = conn.getResponseCode();
//HttpURLConnection.HTTP_PARTIAL 是 206,表示允许请求部分数据
if(responseCode == HttpURLConnection.HTTP_PARTIAL){
InputStream inputStream = conn.getInputStream();//得到本线程应该读取的部分数据
RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//创建可以读写的随机流 rw表示可读可写
rf.seek(start);//把随机流偏移到 应该开始的位置
byte[] bytes = new byte[2048];
int len = 0;
int count = 0;
int totalCount = end-start+1;//计算出本线程应该下载的大小
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));//把当前下载的长度发出去,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);
}
///设置请求部分资源 Range表示随机位置
conn.setRequestProperty("Range","bytes="+currentPosition+"-"+end); //设置当前线程从start开始 到 end结束
int responseCode = conn.getResponseCode();
//HttpURLConnection.HTTP_PARTIAL 是 206,表示允许请求部分数据
if(responseCode == HttpURLConnection.HTTP_PARTIAL){
InputStream inputStream = conn.getInputStream();//得到本线程应该读取的部分数据
RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//创建可以读写的随机流
rf.seek(currentPosition);//把随机流偏移到 应该开始的位置,上次下载写入的位置(下载了一部分)
byte[] bytes = new byte[2048];
int len = 0;
int count = currentPosition-start;//计算出已经下载的大小
EventBus.getDefault().post(new MsgE(count,max));//把得到的旧进度,设置到进度条中
// myCallBack.setProgress2(count);//把已经下载的数据量给进度条
int totalCount = end-start+1;//计算出本线程应该下载的大小
while((len = inputStream.read(bytes)) != -1){
rf.write(bytes,0,len);
count += len;//记录下载的大小
currentPosition += len;//把下载位置向前移动len,以为又下载了len长度的数据
Log.d("MainActivity", "线程:"+i+",totalCount: "+totalCount+
",百分比:"+(float)count/totalCount+",下载大小:"+count);
// myCallBack.setProgress2(len);//把新下载的数据量给进度条
//通过SharedPreferencesUtils记录当前下载到的位置,供105行获取使用,供下次下载使用
EventBus.getDefault().post(new MsgE(len,max));//把得到的新进度,设置到进度条中
SharedPreferencesUtils.setParam(context,"线程"+i,currentPosition);
}
//本线程下载完毕,重新设置为0.下回重新下载
SharedPreferencesUtils.setParam(context,"线程"+i,0);
Log.i("MainActivity", "run: 线程"+i+"下载完毕");
inputStream.close();
rf.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}