国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

基于Retrofit2+RxJava2實現Android App自動更新

2019-10-22 18:11:49
字體:
來源:轉載
供稿:網友

本文實例為大家分享了Retrofit2 RxJava2實現Android App自動更新,具體內容如下

功能解析

自動更新可以說已經是App的標配了,很多第三方平臺也都支持這個功能,最近手頭上的項目需要加入這個App自動更新,考慮到項目里有用到Retrofit2和RxJava2,于是打算使用它倆自己實現這個功能。

分析App自動更新,可以分為以下三個功能點:

1.APK文件的下載
2.下載進度的實時更新顯示
3.下載完成后的自動安裝

其中比較難的一點是下載進度的實時更新顯示,更難的是如何優雅的進行下載進度的更新顯示,這也是為什么我用Retrofit2和RxJva2實現的原因。

用過Retrofit的人都知道他的內部是基于OkHttp實現的,OkHttp大家可能都不陌生,本次解決如何優雅的進行下載進度的更新顯示的關鍵就在OkHttp的攔截器中,攔截器可謂是OKHttp的一大精髓,通過攔截器我們可以拿到Http的請求和響應信息,拿到了這些,你想干什么都行了。本次解決問題的核心就是在攔截器中拿到下載內容的長度并通過自定義的RxBus發送事件將下載信息發送出去,然后在合適的地方拿到這些下載信息,通過Notification實時展示下載進度。

先上一張App自動更新的流程圖

Retrofit2,RxJava2,Android,App自動更新

功能實現

首先根據功能需求我創建了七個類:

1.ApiManager(Retrofit初始化和Api接口定義)
2.ApkLoadingBean(下載長度和文件總長度的數據類)
3.ApkResponseBody(自定義繼承OKHttp的ResponseBody的類)重點
4.RxBus(使用RxJava實現的‘EventBus')重點
5.UpdateApkService(更新服務,在這里開啟下載和訂閱下載進度)重點
6.UpdateHelper(檢查更新、彈出更新對話框)
7.UpdateManager(調用ApiManager接口進行下載)

先講一下OKHttp里對攔截器的操作,我們在攔截器里拿到請求到的響應,對響應信息進行一些封裝并通過RxBus發送出去。接下來看重點代碼。

ApkResponseBody:

public class ApkResponseBody extends ResponseBody {   private Response originalResponse;//原responsebody   public ApkResponseBody(Response originalResponse) {   this.originalResponse = originalResponse;  }   /**   * 返回內容類型   *   * @return   */  @Override  public MediaType contentType() {   return originalResponse.body().contentType();  }   /**   * 內容總長度   * @return   */  @Override  public long contentLength() {   return originalResponse.body().contentLength();  }   /**   * 返回緩存源,類似于io中的BufferedReader   *   * @return   */  @Override  public BufferedSource source() {    return Okio.buffer(new ForwardingSource(originalResponse.body().source()) {    long totalRead = 0;     //返回讀取的長度    @Override    public long read(Buffer sink, long byteCount) throws IOException {     long bytesRead = super.read(sink, byteCount);     totalRead += bytesRead == -1 ? 0 : bytesRead;     Log.i("test", "本次下載:" + bytesRead);     Log.i("test", "總共下載:" + totalRead);     RxBus.getDefault().post(new ApkLoadingBean(contentLength(), totalRead));     return bytesRead;    }     @Override    public Timeout timeout() {     return super.timeout();    }     @Override    public void close() throws IOException {     super.close();    }     @Override    public String toString() {     return super.toString();    }   });  } } 

在source()方法中拿到下載長度和文件總長度,封裝成Bean通過RxBus發送出去。并在ApiManager中初始化Retrofit的時候設置給OKHttp。

OkHttpClient client = new OkHttpClient().newBuilder()     .addInterceptor(new Interceptor() {      @Override      public Response intercept(Chain chain) throws IOException {       Response originalResponse = chain.proceed(chain.request());       return originalResponse         .newBuilder()         .body(new ApkResponseBody(originalResponse))         .build();      }     }).build(); 

RxBus:

public class RxBus {   private static volatile RxBus mInstance;   private final Subject<Object> mBus;   private RxBus() {   this.mBus = PublishSubject.create().toSerialized();  }   public static RxBus getDefault() {   if (mInstance == null) {    synchronized (RxBus.class) {     if (mInstance == null) {      mInstance = Holder.BUS;     }    }   }   return mInstance;  }   /**   * 發送一個事件   *   * @param obj   */  public void post(Object obj) {   mBus.onNext(obj);  }   /**   * 暴露出RxBus的Observable供我們訂閱事件   *   * @param tClass   * @param <T>   * @return   */  public <T> Observable<T> toObservable(Class<T> tClass) {   return mBus.ofType(tClass);  }   private static class Holder {   private static final RxBus BUS = new RxBus();  } } 

UpdateService:

public class UpdateApkService extends IntentService {   private static Context mContext;  public static final String ACTION_DOWNLOAD = "intentservice.ACTION_DOWNLOAD";  public static final String DOWNLOAD_URL = "DOWNLOAD_URL";  public static final String APK_PATH = "APK_PATH";  private CompositeDisposable mCompositeDisposable = new CompositeDisposable();  private NotificationCompat.Builder mBuilder;  private NotificationManager mNotificationManager;   public UpdateApkService() {   super("UpdateApkService");  }   public static void startUpdateService(Context context, String url, String apkPath) {   mContext = context;   Intent intent = new Intent(context, UpdateApkService.class);   intent.setPackage(context.getPackageName());   intent.setAction(ACTION_DOWNLOAD);   intent.putExtra(DOWNLOAD_URL, url);   intent.putExtra(APK_PATH, apkPath);   context.startService(intent);  }   @Override  protected void onHandleIntent(@Nullable Intent intent) {   if (intent != null) {    String action = intent.getAction();    if (ACTION_DOWNLOAD.equals(action)) {     T.showShort(mContext,"開始下載...");     mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);     mBuilder = new NotificationCompat.Builder(this)       .setSmallIcon(R.drawable.ic_launcher)       .setContentTitle("下載最新版中")       .setProgress(100, 0, false)       .setAutoCancel(true);     mNotificationManager.notify(0, mBuilder.build());     String url = intent.getStringExtra(DOWNLOAD_URL);     String apkPath = intent.getStringExtra(APK_PATH);     subscribeEvent();//訂閱下載進度     UpdateManager.downLoadApk(this, url, apkPath, mCompositeDisposable);    }   }  }   private void subscribeEvent() {   RxBus.getDefault().toObservable(ApkLoadingBean.class)     .subscribe(new Observer<ApkLoadingBean>() {      @Override      public void onSubscribe(Disposable d) {       mCompositeDisposable.add(d);      }       @Override      public void onNext(ApkLoadingBean bean) {       int progress = (int) Math.round(bean.getProgress() / (double) bean.getTotal() * 100);       mBuilder.setProgress(100, progress, false);       mNotificationManager.notify(0, mBuilder.build());       if (progress==100)        mNotificationManager.cancel(0);      }       @Override      public void onError(Throwable e) {       subscribeEvent();      }       @Override      public void onComplete() {       subscribeEvent();      }     });  }   @Override  public void onDestroy() {   super.onDestroy();   Log.i("test", "UpdateService is destory");  } } 

在Service中訂閱下載進度,拿到攔截器里發送的封裝好的下載信息Bean,通過計算出進度顯示在Notification上,這樣就可以實現我們實時更新下載進度的需求了。

貼一張以上幾個類的關聯圖,提大家梳理一下。

Retrofit2,RxJava2,Android,App自動更新

總結

通過Retrofit2+RxJava2實現了App自動更新,加深了我對這兩個框架的理解和使用技巧,也擴展了自己的思路,記得以前自己寫自動更新的時候,思緒混亂,代碼不堪入目。。這次不僅實現了自動更新,還使用了相當優雅的解決方式。

Retrofit2,RxJava2,Android,App自動更新

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 仁布县| 五指山市| 图木舒克市| 武穴市| 临夏县| 曲沃县| 信宜市| 唐海县| 富蕴县| 祁门县| 寻乌县| 连州市| 宜宾市| 夹江县| 营口市| 容城县| 临朐县| 长泰县| 泰顺县| 嘉峪关市| 青龙| 兰溪市| 万全县| 东台市| 四川省| 彰化县| 义马市| 八宿县| 象州县| 辽中县| 佛教| 宁武县| 潞西市| 昆明市| 唐海县| 习水县| 宣城市| 伊宁县| 白城市| 金寨县| 上饶市|