您好,登錄后才能下訂單哦!
這篇文章主要介紹了基于Ok+Rxjava如何實現斷點續傳下載,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
具體內容如下
1、基于Ok+Rxjava實現斷點續傳下載
2、基于Ok+Rxjava+Retrofit實現斷點續傳下載
最近總結一下了一下之前學過以及用到過得功能,整理了一個基于Ok+Rxjava實現斷點續傳下載的demo。下面先給大家展示一下使用效果吧。
說下我的大致思路吧:根據文件下載url按照自己定義的規則生成文件名,判斷本地同路徑下是否存在此文件,如果存在,文件大小與服務器上獲取的文件大小一致的情況下,則生成新的文件名重新下載;如果文件比服務器獲取的文件大小小,則執行斷點下載,從本地文件長度處開始下載。如果文件不存在,則從0字節開始下載。
DownloadSubscribe(被觀察者)中執行下載存入本地操作
核心還是:addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength)
DownLoadObserver(觀察者)通過onnext(DownloadInfo downloadInfo)方法回調下載進度
下面上主要代碼:
/** * 開始下載 * @param url 下載請求的網址 * @param downFileCallback 用來回調的接口 */ public void download(final String url, final DownFileCallback downFileCallback) { if (url == null || downCalls.get(url) != null) { return; } Observable.just(url) .filter(new Predicate<String>() { @Override public boolean test(String s) throws Exception { //過濾條件 若map中存在,則這次不下載 return !downCalls.containsKey(s); } }) .flatMap(new Function<String, ObservableSource<DownloadInfo>>() { @Override public ObservableSource<DownloadInfo> apply(String s) throws Exception { //創建下載實體類 return Observable.just(createDownInfo(s)); } }) .map(new Function<DownloadInfo, DownloadInfo>() { @Override public DownloadInfo apply(DownloadInfo s) throws Exception { //根據本地是否存在此文件,來設置文件名及文件初始下載大小 return getRealFileName(s); } }) .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() { @Override public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) throws Exception { //創建被觀察者 return Observable.create(new DownloadSubscribe(downloadInfo)); } })//下載 .observeOn(AndroidSchedulers.mainThread())//在主線程回調 .subscribeOn(Schedulers.io())//在子線程執行 .subscribe(new DownLoadObserver() {//添加觀察者 @Override public void onNext(DownloadInfo downloadInfo) { super.onNext(downloadInfo); downFileCallback.onProgress(downloadInfo.getTotal(), downloadInfo.getProgress()); } @Override public void onError(Throwable e) { super.onError(e); if (!(e instanceof SocketException)) { downFileCallback.onFail(e.getMessage()); } } @Override public void onComplete() { downFileCallback.onSuccess(url); } }); }
/** * 根據url暫停下載操作 * @param url */ public void cancel(String url) { Call call = downCalls.get(url); if (call != null) { call.cancel();//取消 } downCalls.remove(url); }
/** * 創建被觀察者DownloadSubscribe */ private class DownloadSubscribe implements ObservableOnSubscribe<DownloadInfo> { private DownloadInfo downloadInfo; public DownloadSubscribe(DownloadInfo downloadInfo) { this.downloadInfo = downloadInfo; } @Override public void subscribe(ObservableEmitter<DownloadInfo> e) throws Exception { String url = downloadInfo.getUrl(); long downloadLength = downloadInfo.getProgress();//已經下載好的長度 long contentLength = downloadInfo.getTotal();//文件的總長度 //初始進度信息 e.onNext(downloadInfo); Request request = new Request.Builder() //斷點續傳的核心 .addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength) .url(url) .build(); Call call = mClient.newCall(request); //根據下載url,把call存放在map中,取消的時候就可以通過call.cancle()來實現 downCalls.put(url, call); Response response = call.execute(); File file = new File(getTemporaryPath(), downloadInfo.getFileName()); InputStream is = null; FileOutputStream fileOutputStream = null; try { is = response.body().byteStream(); fileOutputStream = new FileOutputStream(file, true); byte[] buffer = new byte[2048];//緩沖數組2kB int len; while ((len = is.read(buffer)) != -1) { fileOutputStream.write(buffer, 0, len); downloadLength += len; downloadInfo.setProgress(downloadLength); e.onNext(downloadInfo); } fileOutputStream.flush(); downCalls.remove(url); } finally { //關閉IO流 IOUtil.closeAll(is, fileOutputStream); } e.onComplete();//完成 } }
/** * 從服務器獲取文件長度 * * @param downloadUrl * @return */ private long getContentLength(String downloadUrl) { Request request = new Request.Builder() .url(downloadUrl) .build(); try { Response response = mClient.newCall(request).execute(); if (response != null && response.isSuccessful()) { long contentLength = response.body().contentLength(); response.close(); return contentLength == 0 ? DownloadInfo.TOTAL_ERROR : contentLength; } } catch (IOException e) { e.printStackTrace(); } return DownloadInfo.TOTAL_ERROR; }
從服務器獲取文件長度的時候注意一下,Android P之后,也就是api 28以上禁止明文網絡傳輸。需要在你的AndroidManifest中的application標簽中聲明"android:usesCleartextTraffic="true",允許應用進行明文傳輸。
使用方法:首先要獲取sd卡權限
DownloadManager.getInstance().downloadPath(本地存在地址).download(url1, new DownFileCallback() { @Override public void onProgress(long totalSize, long downSize) { progress1.setMax((int) totalSize); progress1.setProgress((int) downSize); } @Override public void onSuccess(String url) { Toast.makeText(MainActivity.this, url1 + "下載完成", Toast.LENGTH_SHORT).show(); } @Override public void onFail(String msg) { Toast.makeText(MainActivity.this, url1 + "下載失敗", Toast.LENGTH_SHORT).show(); } });
感謝你能夠認真閱讀完這篇文章,希望小編分享的“基于Ok+Rxjava如何實現斷點續傳下載”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。