斷點下載由于4g比較慢 所以廣泛應(yīng)用,但是出了5g后估計就沒啥用了哈哈
主要就是兩點
第一:添加動態(tài)請求頭 Range:bytes=start-end
范圍 從開始到結(jié)束的位置
第二:就是RandomAccessFile類的使用
下載代碼
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
File directory = Environment.getExternalStorageDirectory();
final File file = new File(directory, "4567.apk");
final RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wandoujia.com/")
.build();
RetrofitService retrofitService = retrofit.create(RetrofitService.class);
String range=String.format("bytes=%d-",file.length());
Call<ResponseBody> call = retrofitService.breadPointRetrofit(range);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
ResponseBody body = response.body();
InputStream inputStream = body.byteStream();
long contentLength = body.contentLength();
byte[] bytes = new byte[1024];
int len;
accessFile.seek(file.length());
while ((len=inputStream.read(bytes))!=-1){
accessFile.write(bytes,0,len);
long length = file.length();
int l = (int) (length * 100 / contentLength);
Log.i("tag", "onResponse: "+l);
if (l == 50) {
Log.i("tag", "onResponse: "+"下載一半可以打一次性斷點來實驗");
}
EventBus.getDefault().post(l);
}
EventBus.getDefault().post(file);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return super.onStartCommand(intent, flags, startId);
}
response接口
public interface RetrofitService {
@GET("https://www.wandoujia.com/apps/604363/download/dot?ch=detail_normal_dl")
Call<ResponseBody> breadPointRetrofit(@Header("range") String range);
}
下載進度和下載安裝
@Subscribe(threadMode = ThreadMode.MAIN)
public void breadPoint(Integer index) {
progressbar.setProgress(index);
tv.setText("當前進度:" + index);
}
@Subscribe(threadMode = ThreadMode.MAIN)
private void downloadApp(File file) {
// 判斷小于7.0版本
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
Intent intent = new Intent(Intent.ACTION_VIEW);
// 7.0版本的uri方法
Uri uri = Uri.fromFile(file);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivityForResult(intent, 2);
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
// 7.0以上版本用fileprovider
Uri uri = FileProvider.getUriForFile(this, "com.example.breadpointdownload" + "" +
".provider", file);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent, 2);
}
}
fileprovider之前有提過 這里也就不多說它的注冊了
其實上面的代碼有兩個坑 專業(yè)人士可能看出來了有些新手估計還是一臉懵逼狀態(tài) 第一在服務(wù)里retrofit的call請求是主線程工作 所以發(fā)送eventbus的時候雖然刷新ui但是最終結(jié)果還是一下就出了 如果沒有evenbus直接會報錯 第二就是eventbus在view中接收file值的時候用的修飾符錯誤 應(yīng)該是public否則會接收不到值 以下是修改后的代碼
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
File directory = Environment.getExternalStorageDirectory();
final File file = new File(directory, "4567.apk");
final RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wandoujia.com/")
.build();
RetrofitService retrofitService = retrofit.create(RetrofitService.class);
String range = String.format("bytes=%d-", file.length());
final Call<ResponseBody> call = retrofitService.breadPointRetrofit(range);
//我們在這里開了一個線程池來操作耗時操作
Executors.newCachedThreadPool().execute(new Runnable() {
@Override
public void run() {
try {
//查看當前線程名字
Log.i("tag", "run: " + Thread.currentThread().getName());
Response<ResponseBody> response = call.execute();
Log.i("tag", "onResponse: " + Thread.currentThread().getName());
ResponseBody body = response.body();
InputStream inputStream = body.byteStream();
long contentLength = body.contentLength();
byte[] bytes = new byte[1024];
int len;
accessFile.seek(file.length());
while ((len = inputStream.read(bytes)) != -1) {
accessFile.write(bytes, 0, len);
long length = file.length();
int l = (int) (length * 100 / contentLength);
Log.i("tag", "下載進度: " + l);
EventBus.getDefault().post(l);
}
EventBus.getDefault().post(file);
} catch (IOException e) {
e.printStackTrace();
}
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return super.onStartCommand(intent, flags, startId);
}
view界面的private修飾符改成public就可以了