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

本文实例为大家分享了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实现下载文件

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

您可能感兴趣的文章:

  • Retrofit+Rxjava下载文件进度的实现
  • Retrofit+Rxjava实现文件上传和下载功能
  • RxJava+Retrofit+OkHttp实现多文件下载之断点续传
  • RxJava2.x+ReTrofit2.x多线程下载文件的示例代码
  • Retrofit Rxjava实现图片下载、保存并展示实例
(0)

相关推荐

  • RxJava+Retrofit+OkHttp实现多文件下载之断点续传

    背景 断点续传下载一直是移动开发中必不可少的一项重要的技术,同样的Rxjava和Retrofit的结合让这个技术解决起来更加的灵活,我们完全可以封装一个适合自的下载框架,简单而且安全! 效果 实现 下载和之前的http请求可以相互独立,所以我们单独给download建立一个工程moudel处理 1.创建service接口 和以前一样,先写接口 注意:Streaming是判断是否写入内存的标示,如果小文件可以考虑不写,一般情况必须写:下载地址需要通过@url动态指定(不适固定的),@head标签是

  • Retrofit+Rxjava实现文件上传和下载功能

    Retrofit简介: 在Android API4.4之后,Google官方使用了square公司推出的okHttp替换了HttpClient的请求方式.后来square公司又推出了基于okHttp的网络请求框架:Retrofit. 什么是 RxJava? RxJava 是一个响应式编程框架,采用观察者设计模式.所以自然少不了 Observable 和 Subscriber 这两个东东了. RxJava 是一个开源项目,地址:https://github.com/ReactiveX/RxJava

  • Retrofit+Rxjava下载文件进度的实现

    前言 最近在学习Retrofit,虽然Retrofit没有提供文件下载进度的回调,但是Retrofit底层依赖的是OkHttp,实际上所需要的实现OkHttp对下载进度的监听,在OkHttp的官方Demo中,有一个Progress.java的文件,顾名思义.点我查看. 准备工作 本文采用Dagger2,Retrofit,RxJava. compile'com.squareup.retrofit2:retrofit:2.0.2' compile'com.squareup.retrofit2:con

  • RxJava2.x+ReTrofit2.x多线程下载文件的示例代码

    写在前面: 接到公司需求:要做一个apk升级的功能,原理其实很简单,百度也一大堆例子,可大部分都是用框架,要么就是HttpURLConnection,实在是不想这么干.正好看了两天的RxJava2.x+ReTrofit2.x,据说这俩框架是目前最火的异步请求框架了.固本文使用RxJava2.x+ReTrofit2.x实现多线程下载文件的功能. 如果对RxJava2.x+ReTrofit2.x不太了解的请先去看相关的文档. 大神至此请无视. 思路分析: 思路及其简洁明了,主要分为以下四步 1.获取

  • Retrofit Rxjava实现图片下载、保存并展示实例

    首先我们看一下Retrofit常规的用法,在不使用Rxjava的情况下,我们默认返回的是Call. public interface ServiceApi { //下载文件 @GET Call<ResponseBody> downloadPicFromNet(@Url String fileUrl); } 但是如果我们要配合Rxjava使用,那么就要按照如下方式来重新定义我们的方法: @GET Observable<ResponseBody> downloadPicFromNet(

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

    本文实例为大家分享了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

  • Retrofit+RxJava实现带进度下载文件

    Retrofit+RxJava已经是目前市场上最主流的网络框架,使用它进行平常的网络请求异常轻松,之前也用Retrofit做过上传文件和下载文件,但发现:使用Retrofit做下载默认是不支持进度回调的,但产品大大要求下载文件时显示下载进度,那就不得不深究下了. 接下来我们一起封装,使用Retrofit+RxJava实现带进度下载文件. github:JsDownload 先来看看UML图: 大家可能还不太清楚具体是怎么处理的,别急,我们一步步来: 1.添依赖是必须的啦 compile 'io.

  • Retrofit+RxJava实现带进度条的文件下载

    项目中需要使用到更新版本,因此研究了一下Retrofit的下载文件,和进度条效果,其间也遇到了一些坑,写出来加深一下记忆,也为别的同学提供一下思路. 先说一下版本控制吧,通用做法基本上是通过接口获取服务器存储的app版本号,与应用的版本号进行比较,版本较低就去更新,先看一下如何获取应用版本号吧 PackageManager packageManager = mActivity.getPackageManager(); PackageInfo packageInfo = null; try { p

  • PHP实现带进度条的Ajax文件上传功能示例

    本文实例讲述了PHP实现带进度条的Ajax文件上传功能.分享给大家供大家参考,具体如下: 之前分享了一篇关于 php使用FileApi实现Ajax上传文件 的文章,里面的Ajax文件上传是不带进度条的,今天分享一篇关于带进度条的Ajax文件上传文章. 效果图: 项目结构图: 12-progress-upload.html文件: 页面中主要有一个上传文件控件,有文件被选择时响应selfile()方法,接着利用js读取上传文件.创建FormData对象和xhr对象,利用xhr2的新标准,写一个监听上

  • PHP+AjaxForm异步带进度条上传文件实例代码

    在使用ajaxForm方法之前,首先需要安装form.js的插件,网上有: 一.首先说用法,ajaxForm可以接收0或1个参数,该参数可以是一个变量.一个对象或回调函数,这个对象主要有以下参数: var object= { url:url, //form提交数据的地址 type:type, //form提交的方式(method:post/get) target:target, //服务器返回的响应数据显示的元素(Id)号 beforeSerialize:function(){} //序列化提交

  • PHP+Ajax异步带进度条上传文件实例

    最近项目中要做一个带进度条的上传文件的功能,学习了Ajax,使用起来比较方便,将几个方法实现就行. 前端引入文件 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min

  • node.js实现带进度条的多文件上传

    用node.js实现多文件上传并携带进度条的demo,供大家参考,具体内容如下 这个独立封装的需求来自一个朋友公司,他说需要写一个带进度条动画的批量上传文件的组件,结果他们后端跟他说不能多文件上传,我一听就很尴尬了,怎么可能不能多文件呢哈哈,后来我只是告诉他进度条的实现方式,在过了2天后我一直对此事耿耿于怀,所以干脆自己动手用node写了一个多文件上传的demo,并记录下来. 前端: http请求为自己封装的一个原生请求函数,一切以原生代码为主: 后端(nodeJs): express + mu

  • 基于SecureCRT向远程Linux主机上传下载文件步骤图解

    有时候直接在Linux服务器上通过 wget 或 curl 工具下截比较大的网络文件时会比较慢,这时我们通常会改用在Windows平台通过迅雷等更加现代化的下载功具下好目标文件(迅雷开会员才能更高速的恶心操作是题外话哈,话说我也送了不少钱给迅雷~~~),这时就面临要把Windows平台下的文件传送到远程Linux服务器上的问题了. 把Windows平台下的文件传送到远程Linux服务器上的方法有很多,这里简单记录下在当前流行的Linux远程管理工具SecureCRT下如何操作及注意事项! 先使用

  • Android带进度条的下载图片示例(AsyncTask异步任务)

    为什么要用异步任务? 在Android中只有在主线程才能对ui进行更新操作,而其它线程不能直接对ui进行操作 android本身是一个多线程的操作系统,我们不能把所有的操作都放在主线程中操作 ,比如一些耗时操作.如果放在主线程中 会造成阻塞 而当阻塞事件过长时 系统会抛出anr异常.所以我们要使用异步任务.android为我们提供了一个封装好的组件asynctask. AsyncTask可以在子线程中更新ui,封装简化了异步操作.适用于简单的异步处理.如果多个后台任务时就要使用Handler了

  • 基于Java写minio客户端实现上传下载文件

    前言: 确保已经安装了minio的服务端 代码: pom.xml <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.0.2</version> </dependency> application.yml server: port:90 minio: url: http://10.69.94.140

随机推荐