当前位置: 移动技术网 > IT编程>开发语言>Java > 基于Retrofit+Rxjava实现带进度显示的下载文件

基于Retrofit+Rxjava实现带进度显示的下载文件

2019年07月19日  | 移动技术网IT编程  | 我要评论

本文实例为大家分享了retrofit rxjava实现下载文件的具体代码,供大家参考,具体内容如下

本文采用 :retrofit + rxjava

1.引入:

//rxjava
 compile 'io.reactivex:rxjava:latest.release'
 compile 'io.reactivex:rxandroid:latest.release'
 //network - squareup
 compile 'com.squareup.retrofit2:retrofit:latest.release'
 compile 'com.squareup.retrofit2:adapter-rxjava:latest.release'
 compile 'com.squareup.okhttp3:okhttp:latest.release'
 compile 'com.squareup.okhttp3:logging-interceptor:latest.release'

2.增加下载进度监听:

public interface downloadprogresslistener {
 void update(long bytesread, long contentlength, boolean done);
}
public class downloadprogressresponsebody extends responsebody {

 private responsebody responsebody;
 private downloadprogresslistener progresslistener;
 private bufferedsource bufferedsource;

 public downloadprogressresponsebody(responsebody responsebody,
          downloadprogresslistener progresslistener) {
  this.responsebody = responsebody;
  this.progresslistener = progresslistener;
 }

 @override
 public mediatype contenttype() {
  return responsebody.contenttype();
 }

 @override
 public long contentlength() {
  return responsebody.contentlength();
 }

 @override
 public bufferedsource source() {
  if (bufferedsource == null) {
   bufferedsource = okio.buffer(source(responsebody.source()));
  }
  return bufferedsource;
 }

 private source source(source source) {
  return new forwardingsource(source) {
   long totalbytesread = 0l;

   @override
   public long read(buffer sink, long bytecount) throws ioexception {
    long bytesread = super.read(sink, bytecount);
    // read() returns the number of bytes read, or -1 if this source is exhausted.
    totalbytesread += bytesread != -1 ? bytesread : 0;

    if (null != progresslistener) {
     progresslistener.update(totalbytesread, responsebody.contentlength(), bytesread == -1);
    }
    return bytesread;
   }
  };

 }
}

public class downloadprogressinterceptor implements interceptor {

 private downloadprogresslistener listener;

 public downloadprogressinterceptor(downloadprogresslistener listener) {
  this.listener = listener;
 }

 @override
 public response intercept(chain chain) throws ioexception {
  response originalresponse = chain.proceed(chain.request());

  return originalresponse.newbuilder()
    .body(new downloadprogressresponsebody(originalresponse.body(), listener))
    .build();
 }
}

3.创建下载进度的元素类:

public class download implements parcelable {

 private int progress;
 private long currentfilesize;
 private long totalfilesize;

 public int getprogress() {
  return progress;
 }

 public void setprogress(int progress) {
  this.progress = progress;
 }

 public long getcurrentfilesize() {
  return currentfilesize;
 }

 public void setcurrentfilesize(long currentfilesize) {
  this.currentfilesize = currentfilesize;
 }

 public long gettotalfilesize() {
  return totalfilesize;
 }

 public void settotalfilesize(long totalfilesize) {
  this.totalfilesize = totalfilesize;
 }

 @override
 public int describecontents() {
  return 0;
 }

 @override
 public void writetoparcel(parcel dest, int flags) {
  dest.writeint(this.progress);
  dest.writelong(this.currentfilesize);
  dest.writelong(this.totalfilesize);
 }

 public download() {
 }

 protected download(parcel in) {
  this.progress = in.readint();
  this.currentfilesize = in.readlong();
  this.totalfilesize = in.readlong();
 }

 public static final parcelable.creator<download> creator = new parcelable.creator<download>() {
  @override
  public download createfromparcel(parcel source) {
   return new download(source);
  }

  @override
  public download[] newarray(int size) {
   return new download[size];
  }
 };
}

4.下载文件网络类:

public interface downloadservice {

 @streaming
 @get
 observable<responsebody> download(@url string url);
}

注:这里@url是传入完整的的下载url;不用截取

public class downloadapi {
 private static final string tag = "downloadapi";
 private static final int default_timeout = 15;
 public retrofit retrofit;


 public downloadapi(string url, downloadprogresslistener listener) {

  downloadprogressinterceptor interceptor = new downloadprogressinterceptor(listener);

  okhttpclient client = new okhttpclient.builder()
    .addinterceptor(interceptor)
    .retryonconnectionfailure(true)
    .connecttimeout(default_timeout, timeunit.seconds)
    .build();


  retrofit = new retrofit.builder()
    .baseurl(url)
    .client(client)
    .addcalladapterfactory(rxjavacalladapterfactory.create())
    .build();
 }

 public void downloadapk(@nonnull string url, final file file, subscriber subscriber) {
  log.d(tag, "downloadapk: " + url);

  retrofit.create(downloadservice.class)
    .download(url)
    .subscribeon(schedulers.io())
    .unsubscribeon(schedulers.io())
    .map(new func1<responsebody, inputstream>() {
     @override
     public inputstream call(responsebody responsebody) {
      return responsebody.bytestream();
     }
    })
    .observeon(schedulers.computation())
    .doonnext(new action1<inputstream>() {
     @override
     public void call(inputstream inputstream) {
      try {
       fileutils.writefile(inputstream, file);
      } catch (ioexception e) {
       e.printstacktrace();
       throw new customizeexception(e.getmessage(), e);
      }
     }
    })
    .observeon(androidschedulers.mainthread())
    .subscribe(subscriber);
 }


}

然后就是调用了:

该网络是在service里完成的

public class downloadservice extends intentservice {
 private static final string tag = "downloadservice";

 private notificationcompat.builder notificationbuilder;
 private notificationmanager notificationmanager;


 private string apkurl = "http://download.fir.im/v2/app/install/595c5959959d6901ca0004ac?download_token=1a9dfa8f248b6e45ea46bc5ed96a0a9e&source=update";

 public downloadservice() {
  super("downloadservice");
 }

 @override
 protected void onhandleintent(intent intent) {
  notificationmanager = (notificationmanager) getsystemservice(context.notification_service);

  notificationbuilder = new notificationcompat.builder(this)
    .setsmallicon(r.mipmap.ic_download)
    .setcontenttitle("download")
    .setcontenttext("downloading file")
    .setautocancel(true);

  notificationmanager.notify(0, notificationbuilder.build());

  download();
 }

 private void download() {
  downloadprogresslistener listener = new downloadprogresslistener() {
   @override
   public void update(long bytesread, long contentlength, boolean done) {
    download download = new download();
    download.settotalfilesize(contentlength);
    download.setcurrentfilesize(bytesread);
    int progress = (int) ((bytesread * 100) / contentlength);
    download.setprogress(progress);

    sendnotification(download);
   }
  };
  file outputfile = new file(environment.getexternalstoragepublicdirectory
    (environment.directory_downloads), "file.apk");
  string baseurl = stringutils.gethostname(apkurl);

  new downloadapi(baseurl, listener).downloadapk(apkurl, outputfile, new subscriber() {
   @override
   public void oncompleted() {
    downloadcompleted();
   }

   @override
   public void onerror(throwable e) {
    e.printstacktrace();
    downloadcompleted();
    log.e(tag, "onerror: " + e.getmessage());
   }

   @override
   public void onnext(object o) {

   }
  });
 }

 private void downloadcompleted() {
  download download = new download();
  download.setprogress(100);
  sendintent(download);

  notificationmanager.cancel(0);
  notificationbuilder.setprogress(0, 0, false);
  notificationbuilder.setcontenttext("file downloaded");
  notificationmanager.notify(0, notificationbuilder.build());
 }

 private void sendnotification(download download) {

  sendintent(download);
  notificationbuilder.setprogress(100, download.getprogress(), false);
  notificationbuilder.setcontenttext(
    stringutils.getdatasize(download.getcurrentfilesize()) + "/" +
      stringutils.getdatasize(download.gettotalfilesize()));
  notificationmanager.notify(0, notificationbuilder.build());
 }

 private void sendintent(download download) {

  intent intent = new intent(mainactivity.message_progress);
  intent.putextra("download", download);
  localbroadcastmanager.getinstance(downloadservice.this).sendbroadcast(intent);
 }

 @override
 public void ontaskremoved(intent rootintent) {
  notificationmanager.cancel(0);
 }
}

mainactivity代码:

public class mainactivity extends appcompatactivity {

 public static final string message_progress = "message_progress";

 private appcompatbutton btn_download;
 private progressbar progress;
 private textview progress_text;


 private broadcastreceiver broadcastreceiver = new broadcastreceiver() {
  @override
  public void onreceive(context context, intent intent) {

   if (intent.getaction().equals(message_progress)) {

    download download = intent.getparcelableextra("download");
    progress.setprogress(download.getprogress());
    if (download.getprogress() == 100) {

     progress_text.settext("file download complete");

    } else {

     progress_text.settext(stringutils.getdatasize(download.getcurrentfilesize())
       +"/"+
       stringutils.getdatasize(download.gettotalfilesize()));

    }
   }
  }
 };

 @override
 protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);
  btn_download = (appcompatbutton) findviewbyid(r.id.btn_download);
  progress = (progressbar) findviewbyid(r.id.progress);
  progress_text = (textview) findviewbyid(r.id.progress_text);

  registerreceiver();

  btn_download.setonclicklistener(new view.onclicklistener() {
   @override
   public void onclick(view view) {
    intent intent = new intent(mainactivity.this, downloadservice.class);
    startservice(intent);
   }
  });
 }

 private void registerreceiver() {

  localbroadcastmanager bmanager = localbroadcastmanager.getinstance(this);
  intentfilter intentfilter = new intentfilter();
  intentfilter.addaction(message_progress);
  bmanager.registerreceiver(broadcastreceiver, intentfilter);

 }
}

本文源码:retrofit rxjava实现下载文件

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网