Rxjava中怎么实现断点续传下载功能
创始人
2024-12-21 19:22:18
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() {  @Override  public boolean test(String s) throws Exception {  //过滤条件 若map中存在,则这次不下载  return !downCalls.containsKey(s);  } }) .flatMap(new Function>() {  @Override  public ObservableSource apply(String s) throws Exception {  //创建下载实体类  return Observable.just(createDownInfo(s));  } }) .map(new Function() {  @Override  public DownloadInfo apply(DownloadInfo s) throws Exception {  //根据本地是否存在此文件,来设置文件名及文件初始下载大小  return getRealFileName(s);  } }) .flatMap(new Function>() {  @Override  public ObservableSource 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 { private DownloadInfo downloadInfo;  public DownloadSubscribe(DownloadInfo downloadInfo) { this.downloadInfo = downloadInfo; }  @Override public void subscribe(ObservableEmitter 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();  } });

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...