欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Retrofit2+RxJava2實現(xiàn)Android App自動更新

 更新時間:2018年05月08日 17:14:53   作者:Ever69  
這篇文章主要為大家詳細(xì)介紹了基于Retrofit2+RxJava2實現(xiàn)Android App自動更新,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Retrofit2 RxJava2實現(xiàn)Android App自動更新,具體內(nèi)容如下

功能解析

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

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

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

其中比較難的一點是下載進(jìn)度的實時更新顯示,更難的是如何優(yōu)雅的進(jìn)行下載進(jìn)度的更新顯示,這也是為什么我用Retrofit2和RxJva2實現(xiàn)的原因。

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

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

功能實現(xiàn)

首先根據(jù)功能需求我創(chuàng)建了七個類:

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

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

ApkResponseBody:

public class ApkResponseBody extends ResponseBody { 
 
 private Response originalResponse;//原responsebody 
 
 public ApkResponseBody(Response originalResponse) { 
  this.originalResponse = originalResponse; 
 } 
 
 /** 
  * 返回內(nèi)容類型 
  * 
  * @return 
  */ 
 @Override 
 public MediaType contentType() { 
  return originalResponse.body().contentType(); 
 } 
 
 /** 
  * 內(nèi)容總長度 
  * @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發(fā)送出去。并在ApiManager中初始化Retrofit的時候設(shè)置給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; 
 } 
 
 /** 
  * 發(fā)送一個事件 
  * 
  * @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();//訂閱下載進(jìn)度 
    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中訂閱下載進(jìn)度,拿到攔截器里發(fā)送的封裝好的下載信息Bean,通過計算出進(jìn)度顯示在Notification上,這樣就可以實現(xiàn)我們實時更新下載進(jìn)度的需求了。

貼一張以上幾個類的關(guān)聯(lián)圖,提大家梳理一下。

總結(jié)

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 關(guān)于Android Studio封裝SDK的那些事兒

    關(guān)于Android Studio封裝SDK的那些事兒

    這篇文章主要給大家介紹了關(guān)于Android Studio封裝SDK的那些事兒,文中通過圖文以及示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • Android Studio使用ButterKnife和Zelezny的方法

    Android Studio使用ButterKnife和Zelezny的方法

    這篇文章主要為大家詳細(xì)介紹了Android Studio使用ButterKnife和Zelezny的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Android編程學(xué)習(xí)之抽象類AbsListView用法實例分析

    Android編程學(xué)習(xí)之抽象類AbsListView用法實例分析

    這篇文章主要介紹了Android編程學(xué)習(xí)之抽象類AbsListView用法,較為詳細(xì)的分析了抽象類AbsListView的功能、結(jié)構(gòu)、定義及使用注意事項等,需要的朋友可以參考下
    2015-10-10
  • 超簡單Android集成華為HMS Scankit 掃碼SDK實現(xiàn)掃一掃二維碼

    超簡單Android集成華為HMS Scankit 掃碼SDK實現(xiàn)掃一掃二維碼

    這篇文章主要介紹了超簡單Android集成華為HMS Scankit 掃碼SDK實現(xiàn)掃一掃二維碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Android實現(xiàn)GPS定位代碼實例

    Android實現(xiàn)GPS定位代碼實例

    這篇文章主要介紹了Android實現(xiàn)GPS定位實例,對關(guān)鍵操作部份給出代碼示例并做了一定的注釋,需要的朋友可以參考下
    2014-07-07
  • Android中使用Intent在Activity之間傳遞對象(使用Serializable或者Parcelable)的方法

    Android中使用Intent在Activity之間傳遞對象(使用Serializable或者Parcelable)的

    這篇文章主要介紹了 Android中使用Intent在Activity之間傳遞對象(使用Serializable或者Parcelable)的方法的相關(guān)資料,需要的朋友可以參考下
    2016-01-01
  • Android實現(xiàn)游戲中的漸隱和漸現(xiàn)動畫效果

    Android實現(xiàn)游戲中的漸隱和漸現(xiàn)動畫效果

    本文給大家分享android中實現(xiàn)游戲中的漸隱漸現(xiàn)的動畫效果,在游戲開發(fā)中經(jīng)常會遇到,對android漸隱漸現(xiàn)效果感興趣的朋友可以參考下本教程
    2016-09-09
  • android handler.post和handler.sendMessage的區(qū)別和聯(lián)系

    android handler.post和handler.sendMessage的區(qū)別和聯(lián)系

    handler.post和handler.sendMessage本質(zhì)上是沒有區(qū)別的,都是發(fā)送一個消息到消息隊列中,而且消息隊列和handler都是依賴于同一個線程的。接下來通過本文給大家分享android handler.post和handler.sendMessage的區(qū)別和聯(lián)系,一起看看吧
    2017-08-08
  • Android控件實現(xiàn)水滴效果

    Android控件實現(xiàn)水滴效果

    這篇文章主要為大家詳細(xì)介紹了Android控件實現(xiàn)水滴效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • Kotlin掛起函數(shù)應(yīng)用介紹

    Kotlin掛起函數(shù)應(yīng)用介紹

    掛起函數(shù)用狀態(tài)機(jī)以掛起點將協(xié)程的運算邏輯拆分成不同的片段,每次執(zhí)行協(xié)程運行不同的邏輯片段,由此可以知道協(xié)程是運行在線程中的,線程的并發(fā)處理方式也可以用在協(xié)程上
    2022-11-11

最新評論