Retrofit 2+RxJava 2 기반 Android 앱 자동 업데이트 실현

본 논문 의 사례 는 Retrofit 2 RxJava 2 가 Android App 자동 업 데 이 트 를 실현 하 는 것 을 공유 하 였 으 며,구체 적 인 내용 은 다음 과 같다.
기능 분석
자동 업 데 이 트 는 이미 App 의 레이 블 이 라 고 할 수 있 습 니 다.많은 제3자 플랫폼 도 이 기능 을 지원 합 니 다.최근 에 가지 고 있 는 프로젝트 는 이 App 에 가입 하여 자동 업 데 이 트 를 해 야 합 니 다.프로젝트 에 Retrofit 2 와 RxJava 2 가 유용 하 다 는 것 을 고려 하여 두 사람 이 스스로 이 기능 을 실현 하려 고 합 니 다.
App 자동 업 데 이 트 를 분석 하면 다음 과 같은 세 가지 기능 으로 나 눌 수 있 습 니 다.
1.APK 파일 다운로드
2.진행 중인 실시 간 업데이트 디 스 플레이 다운로드
3.다운로드 완료 후 자동 설치
그 중에서 어 려 운 점 은 다운로드 진도 의 실시 간 업데이트 디 스 플레이 입 니 다.더 어 려 운 것 은 다운로드 진도 의 업 데 이 트 를 어떻게 우아 하 게 진행 하 는 지 하 는 것 입 니 다.이것 도 제 가 Retrofit 2 와 RxJva 2 로 이 루어 진 이유 입 니 다.
Retrofit 를 사용 한 사람들 은 모두 그의 내부 가 OkHttp 를 바탕 으로 이 루어 진 것 을 알 고 있다.OkHttp 는 모두 가 낯 설 지 않 을 것 이다.이번 다운로드 진 도 를 우아 하 게 진행 하 는 업데이트 디 스 플레이 를 해결 하 는 관건 은 바로 OkHttp 의 차단기 이다.차단 기 는 OKHttp 의 큰 정수 라 고 할 수 있다.차단 기 를 통 해 우 리 는 Http 의 요청 과 응답 정 보 를 얻 을 수 있다.뭐 공부 해요?이번 문제 해결 의 핵심 은 차단기 에서 다운로드 콘 텐 츠 의 길 이 를 가 져 오고 사용자 정의 RxBus 발송 이 벤트 를 통 해 다운로드 정 보 를 전송 한 뒤 적절 한 곳 에서 이 다운로드 정 보 를 받 아 Notification 을 통 해 실시 간 으로 다운로드 진 도 를 보 여 주 는 것 이다.
이전 App 에서 자동 으로 업 데 이 트 된 프로 세 스 맵

기능 실현
우선 기능 수요 에 따라 저 는 7 가지 종 류 를 만 들 었 습 니 다.
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 에 표시 하면 실시 간 으로 다운로드 진 도 를 업데이트 하 는 수 요 를 실현 할 수 있 습 니 다.
상기 몇 가지 유형의 관련 도 를 한 장 붙 여 모두 가 정리 하 는 것 을 제시한다.

총결산
Retrofit 2+RxJava 2 를 통 해 App 자동 업 데 이 트 를 실 현 했 고 이 두 프레임 워 크 에 대한 이해 와 사용 기 교 를 깊이 있 게 했 으 며 자신의 사고방식 도 넓 혔 다.예전 에 자신 이 자동 업 데 이 트 를 썼 을 때 생각 이 혼 란 스 러 웠 고 코드 가 눈 에 띄 지 않 았 던 것 을 기억한다.이번 에는 자동 업데이트 뿐 아니 라 상당히 우아 한 해결 방식 을 사용 했다.

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기