<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'io.reactivex.rxjava2:rxjava:2.1.13' implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
UpdateBean
public class UpdateBean { /** * msg : 获取版本信息成功 * code : 0 * data : {"apkUrl":"https://www.zhaoapi.cn/version/app.apk","desc":"V2.0升级,修复部分bug,优化程序性能!","type":2,"vId":3, * "versionCode":"200","versionName":"2.0"} */ private String msg; private String code; private DataBean data; private boolean flag; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public DataBean getData() { return data; } public void setData(DataBean data) { this.data = data; } public static class DataBean { /** * apkUrl : https://www.zhaoapi.cn/version/app.apk * desc : V2.0升级,修复部分bug,优化程序性能! * type : 2 * vId : 3 * versionCode : 200 * versionName : 2.0 */ private String apkUrl; private String desc; private int type; private int vId; private String versionCode; private String versionName; public String getApkUrl() { return apkUrl; } public void setApkUrl(String apkUrl) { this.apkUrl = apkUrl; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public int getType() { return type; } public void setType(int type) { this.type = type; } public int getVId() { return vId; } public void setVId(int vId) { this.vId = vId; } public String getVersionCode() { return versionCode; } public void setVersionCode(String versionCode) { this.versionCode = versionCode; } public String getVersionName() { return versionName; } public void setVersionName(String versionName) { this.versionName = versionName; } } }UpdateApi
package com.example.updatedemo.net; import com.example.updatedemo.bean.UpdateBean; import io.reactivex.Observable; import okhttp3.ResponseBody; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; public class UpdateApi { private static UpdateApi updateApi; private UpdateApi() { } public static UpdateApi getUpdateApi() { if (updateApi == null) { synchronized (UpdateApi.class) { if (updateApi == null) { updateApi = new UpdateApi(); } } } return updateApi; } public Observable<UpdateBean> update() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://www.zhaoapi.cn/") .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); UpdateApiService updateApiService = retrofit.create(UpdateApiService.class); return updateApiService.update(); } public Observable<ResponseBody> download(String url) { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://www.zhaoapi.cn/") .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); UpdateApiService updateApiService = retrofit.create(UpdateApiService.class); return updateApiService.download(url); } }UpdateApiService
package com.example.updatedemo.net; import com.example.updatedemo.bean.UpdateBean; import io.reactivex.Observable; import okhttp3.ResponseBody; import retrofit2.http.GET; import retrofit2.http.Url; public interface UpdateApiService { @GET("quarter/getVersion") Observable<UpdateBean> update(); @GET Observable<ResponseBody> download(@Url String url); }
AppVersion
package com.example.updatedemo.util; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; public class AppVersion { /** * 获取版本号 * * @param context * @return */ public static int getVersionCode(Context context) { PackageInfo pi = null; try { pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return pi.versionCode; } }MainActivity
package com.example.updatedemo; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import com.example.updatedemo.bean.UpdateBean; import com.example.updatedemo.net.UpdateApi; import com.example.updatedemo.util.AppVersion; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import io.reactivex.Observable; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import okhttp3.ResponseBody; public class MainActivity extends AppCompatActivity { private UpdateApi updateApi; private File appFile; private String apkUrl = "https://www.zhaoapi.cn/version/app.apk"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); File cacheDir = getExternalCacheDir(); appFile = new File(cacheDir, "app.apk"); //调用更新接口 updateApi = UpdateApi.getUpdateApi(); Observable<UpdateBean> observable = updateApi.update(); observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<UpdateBean>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(UpdateBean updateBean) { //调用更新接口成功,判断是否需要更新 String nCode = updateBean.getData().getVersionCode(); if (TextUtils.isEmpty(nCode)) { return; } if (checkIsUpdate(Integer.parseInt(nCode))) { //弹出对话框给用户提示是否更新 if (updateBean.isFlag()) { alert2(updateBean.getData().getDesc()); } else { alert(updateBean); } } } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); } private void alert2(String str) { new AlertDialog.Builder(MainActivity.this) .setTitle("是否更新") .setMessage(str) .setCancelable(false) .setPositiveButton("更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //去下载apk的包 } }).setNegativeButton("退出", null) .show(); } private void alert(final UpdateBean updateBean) { new AlertDialog.Builder(MainActivity.this) .setTitle("是否更新") .setMessage(updateBean.getData().getDesc()) .setPositiveButton("更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //去下载apk的包 apkDownload(updateBean.getData().getApkUrl()); } }).setNegativeButton("取消", null) .show(); } private void apkDownload(String url) { Observable<ResponseBody> observable = updateApi.download("version/app.apk"); observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<ResponseBody>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(ResponseBody responseBody) { InputStream inputStream = responseBody.byteStream(); //保存到本地sd卡 try { FileOutputStream fos = new FileOutputStream(appFile); int len = 0; byte[] buffer = new byte[1024]; while ((len = inputStream.read(buffer)) != -1) { fos.write(buffer, 0, len); fos.flush(); } fos.close(); inputStream.close(); } catch (Exception e) { e.printStackTrace(); } } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); } private boolean checkIsUpdate(int nCode) { //拿到当前app的versionCode版本 int versionCode = AppVersion.getVersionCode(MainActivity.this); return versionCode < nCode ? true : false; } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> </android.support.constraint.ConstraintLayout>