一开始,我们先向服务器请求数据获取版本
1 public ObservableField<VersionBean> appVersion = new ObservableField<>(); 2 3 /** 4 * 获取服务器版本并判断是否需要更新 5 */ 6 public void getServiceAppVersionEvent() { 7 resource.getAppVersionEvent() 8 .observeOn(AndroidSchedulers.mainThread()) 9 .subscribe(response -> { 10 if (EmptyUtil.isNotEmpty(response.body)) { 11 appVersion.set(response.body); 12 if (UpdateAppUtil.checkAppVersion(response.body)) { 13 checkUpdate.set("发现新版本" + response.body.getVersion()); 14 } 15 } 16 }); 17 }
服务器返回的数据
1 2 3 /** 4 * Created by hyx on 17-9-29. 5 */ 6 7 public class VersionBean { 8 9 private String description; 10 private String url; 11 private String version; 12 13 14 15 public String getUrl() { 16 return url; 17 } 18 19 public void setUrl(String url) { 20 this.url = url; 21 } 22 23 24 25 public String getVersion() { 26 return version; 27 } 28 29 public void setVersion(String version) { 30 this.version = version; 31 } 32 33 public String getDescription() { 34 return description; 35 } 36 37 public void setDescription(String description) { 38 this.description = description; 39 } 40 }
对比服务器和本地判断是否需要更新,我这里是根据VersionName判断
/** * 获取versionName * * @return */ public static String getAppVersionName() { if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) { try { PackageManager manager = CtrAppImpl.getContext().getPackageManager(); PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0); return info.versionName; } catch (Exception e) { e.printStackTrace(); return ""; } } else { return null; } } /** * 获取versionId * * @return */ public static int getAppVersionCode() { if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) { try { PackageManager manager = CtrAppImpl.getContext().getPackageManager(); PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0); return info.versionCode; } catch (Exception e) { e.printStackTrace(); return -1; } } else { return -1; } } /** * true 表示需要更新,false 表示当前版本是最新的 * * @param versionBean * @return */ public static boolean checkAppVersion(VersionBean versionBean) { if (EmptyUtil.isNotEmpty(versionBean)) { if (!getAppVersionName().equals(versionBean.getVersion())) { return true; } else { return false; } } return false; }
如果需要更新,我们根据存储的downloadId去查询下载状态,因为有可能用户之前已经下载了,没有安装,亦或正在下载中,下载暂停等情况,
1 if (UpdateAppUtil.checkAppVersion(getViewModel().appVersion.get())) { 2 //根据downloadId查询下载状态 3 long downloadId = (long) SPUtil.get(PersonalActivity.this, "downloadId", -1L); 4 UpdateAppUtil.checkDownloadStatus(downloadId, new DataBack<Integer>() { 5 @Override 6 public void take(Integer status) { 7 if (status == -1) { 8 new MaterialDialog.Builder(PersonalActivity.this) 9 .title("版本更新") 10 .content("发现新版本,是否更新?") 11 .positiveText("确定") 12 .negativeText("取消") 13 .onPositive(((materialDialog, dialogAction) -> { 14 ToastUtil.showShortToast("正在后台为您下载"); 15 UpdateAppUtil.downloadAPK(getViewModel().appVersion.get(), "ctrshoppix.apk"); 16 })) 17 .onNegative((materialDialog, dialogAction) -> { 18 materialDialog.dismiss(); 19 }) 20 .show(); 21 } else if (status == DownloadManager.STATUS_FAILED) { 22 ToastUtil.showShortToast("下载失败,正在为您重新下载"); 23 UpdateAppUtil.downloadAPK(getViewModel().appVersion.get(), "ctrshoppix.apk"); 24 } else if (status == DownloadManager.STATUS_SUCCESSFUL) { 25 if (UpdateAppUtil.compareApk(UpdateAppUtil.getApkInfo(UpdateAppUtil.getDownloadPath(downloadId)))) { 26 UpdateAppUtil.installApp(UpdateAppUtil.getDownloadUri(downloadId)); 27 } else { 28 UpdateAppUtil.removeDownloadId(downloadId); 29 } 30 } 31 } 32 });
具体的方法在下面UpdateAppUtil中查看,备注写的很清楚
1 import android.app.Activity; 2 import android.app.DownloadManager; 3 import android.content.BroadcastReceiver; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.content.pm.PackageInfo; 7 import android.content.pm.PackageManager; 8 import android.database.Cursor; 9 import android.net.Uri; 10 import android.os.Build; 11 import android.os.Environment; 12 import android.support.v4.content.FileProvider; 13 import android.text.BoringLayout; 14 15 import java.io.File; 16 import java.io.IOException; 17 18 import ppm.ctr.cctv.ctr.application.CtrAppImpl; 19 import ppm.ctr.cctv.ctr.common.AsyncCall; 20 import ppm.ctr.cctv.ctr.common.DataBack; 21 import ppm.ctr.cctv.ctr.network.entity.VersionBean; 22 import ppm.ctr.cctv.ctr.services.file.UriPraseUtil; 23 24 /** 25 * Created by css on 2017/10/30. 26 */ 27 28 public class UpdateAppUtil { 29 private static DownloadManager downloadManager; 30 31 /** 32 * 获取versionName 33 * 34 * @return 35 */ 36 public static String getAppVersionName() { 37 if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) { 38 try { 39 PackageManager manager = CtrAppImpl.getContext().getPackageManager(); 40 PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0); 41 return info.versionName; 42 } catch (Exception e) { 43 e.printStackTrace(); 44 return ""; 45 } 46 47 } else { 48 return null; 49 } 50 } 51 52 53 /** 54 * 获取versionId 55 * 56 * @return 57 */ 58 public static int getAppVersionCode() { 59 if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) { 60 try { 61 PackageManager manager = CtrAppImpl.getContext().getPackageManager(); 62 PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0); 63 return info.versionCode; 64 } catch (Exception e) { 65 e.printStackTrace(); 66 return -1; 67 } 68 69 } else { 70 return -1; 71 } 72 } 73 74 /** 75 * true 表示需要更新,false 表示当前版本是最新的 76 * 77 * @param versionBean 78 * @return 79 */ 80 public static boolean checkAppVersion(VersionBean versionBean) { 81 if (EmptyUtil.isNotEmpty(versionBean)) { 82 if (!getAppVersionName().equals(versionBean.getVersion())) { 83 return true; 84 } else { 85 return false; 86 } 87 } 88 return false; 89 } 90 91 /** 92 * 检查下载状态 93 * 94 * @param downloadId 95 * @param dataBack 96 */ 97 public static void checkDownloadStatus(long downloadId, DataBack<Integer> dataBack) { 98 DownloadManager.Query query = new DownloadManager.Query(); 99 //通过下载的id查找 100 query.setFilterById(downloadId); 101 //获取DownloadManager 102 if (EmptyUtil.isEmpty(downloadManager)) { 103 downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE); 104 } 105 Cursor c = downloadManager.query(query); 106 if (c.moveToFirst()) { 107 int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)); 108 switch (status) { 109 case -1: 110 dataBack.take(-1); 111 break; 112 //下载暂停 113 case DownloadManager.STATUS_PAUSED: 114 ToastUtil.showShortToast("下载暂停"); 115 break; 116 //下载延迟 117 case DownloadManager.STATUS_PENDING: 118 ToastUtil.showShortToast("下载延迟"); 119 break; 120 //正在下载 121 case DownloadManager.STATUS_RUNNING: 122 ToastUtil.showShortToast("正在下载"); 123 break; 124 //下载完成 125 case DownloadManager.STATUS_SUCCESSFUL: 126 dataBack.take(DownloadManager.STATUS_SUCCESSFUL); 127 128 break; 129 //下载失败 130 case DownloadManager.STATUS_FAILED: 131 dataBack.take(DownloadManager.STATUS_FAILED); 132 break; 133 default: 134 dataBack.take(-1); 135 break; 136 } 137 138 dataBack.take(status); 139 } else { 140 //可能用户误删之前已经下载得apk 141 dataBack.take(-1); 142 } 143 c.close(); 144 } 145 146 147 /** 148 * 根据downloadID获取本地存储的文件path 149 * 150 * @param downloadId 151 * @return 152 */ 153 public static String getDownloadPath(long downloadId) { 154 //获取DownloadManager 155 if (EmptyUtil.isEmpty(downloadManager)) { 156 downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE); 157 } 158 String downloadPath = new File(UriPraseUtil.uriToFile(downloadManager.getUriForDownloadedFile(downloadId), CtrAppImpl.getContext())).toString(); 159 return downloadPath; 160 } 161 162 /** 163 * 根据downloadID 获取获取本地文件存储的uri 164 * 165 * @param downloadId 166 * @return 167 */ 168 public static Uri getDownloadUri(long downloadId) { 169 //获取DownloadManager 170 if (EmptyUtil.isEmpty(downloadManager)) { 171 downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE); 172 } 173 Uri downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId); 174 //适配不同的手机,有的手机不能识别,所以再转一遍 175 Uri uri = Uri.fromFile(new File(UriPraseUtil.uriToFile(downloadFileUri, CtrAppImpl.getContext()))); 176 return uri; 177 } 178 179 180 /** 181 * 获取apk程序信息 182 * 183 * @param path apk path 184 */ 185 public static PackageInfo getApkInfo(String path) { 186 PackageManager pm = CtrAppImpl.getContext().getPackageManager(); 187 PackageInfo info = pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES); 188 if (info != null) { 189 return info; 190 } 191 return null; 192 } 193 194 195 /** 196 * 下载的apk和当前程序版本比较 197 * 198 * @param apkInfo apk file's packageInfo 199 * @return 如果当前应用版本小于apk的版本则返回true 200 */ 201 public static boolean compareApk(PackageInfo apkInfo) { 202 if (apkInfo == null) { 203 return false; 204 } 205 if (!apkInfo.versionName.equals(getAppVersionName())) { 206 return true; 207 } 208 return false; 209 210 } 211 212 213 /** 214 * 下载apk 215 * 216 * @param versionBean 217 * @param apkName 218 */ 219 public static void downloadAPK(VersionBean versionBean, String apkName) { 220 //创建下载任务 221 DownloadManager.Request request = new DownloadManager.Request(Uri.parse(versionBean.getUrl())); 222 //移动网络情况下是否允许漫游 223 request.setAllowedOverRoaming(false); 224 // 设置在通知栏是否显示下载通知(下载进度), 有 3 个值可选: 225 // VISIBILITY_VISIBLE: 下载过程中可见, 下载完后自动消失 (默认) 226 // VISIBILITY_VISIBLE_NOTIFY_COMPLETED: 下载过程中和下载完成后均可见 227 // VISIBILITY_HIDDEN: 始终不显示通知 228 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 229 request.setTitle("单单拍"); 230 request.setDescription(""); 231 request.setVisibleInDownloadsUi(true); 232 233 //设置下载的路径 234 request.setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory().getAbsolutePath(), apkName); 235 236 //获取DownloadManager 237 if (EmptyUtil.isEmpty(downloadManager)) { 238 downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE); 239 } 240 //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等 241 long downloadId = downloadManager.enqueue(request); 242 SPUtil.put(CtrAppImpl.getContext(), "downloadId", downloadId); 243 } 244 245 246 /** 247 * 移除本地存储的downloadid 和相关文件 248 * 249 * @param downloadId 250 */ 251 public static void removeDownloadId(long downloadId) { 252 //获取DownloadManager 253 if (EmptyUtil.isEmpty(downloadManager)) { 254 downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE); 255 } 256 downloadManager.remove(downloadId); 257 SPUtil.remove(CtrAppImpl.getContext(), "downloadId"); 258 } 259 260 261 /** 262 * 安装app 263 * 264 * @param uri 265 */ 266 public static void installApp(Uri uri) { 267 Intent intent = new Intent(); 268 intent.setDataAndType(uri, "application/vnd.android.package-archive"); 269 intent.setAction(Intent.ACTION_VIEW); 270 intent.addCategory(Intent.CATEGORY_DEFAULT); 271 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 272 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 273 CtrAppImpl.getContext().startActivity(intent); 274 } 275 276 277 /** 278 * 安装app 279 * 280 * @param apkPath 281 */ 282 public static void installApp(String apkPath) { 283 File file = new File(apkPath); 284 Uri uri = null; 285 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 286 String command = "chmod " + "777" + " " + file; 287 Runtime runtime = Runtime.getRuntime(); 288 try { 289 runtime.exec(command); 290 } catch (IOException e) { 291 e.printStackTrace(); 292 } 293 uri = FileProvider.getUriForFile(CtrAppImpl.getContext(), "ppm.ctr.cctv.ctr.provider", file); 294 } else { 295 uri = Uri.fromFile(file); 296 } 297 Intent intent = new Intent(); 298 intent.setDataAndType(uri, "application/vnd.android.package-archive"); 299 intent.setAction(Intent.ACTION_VIEW); 300 intent.addCategory(Intent.CATEGORY_DEFAULT); 301 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 302 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 303 CtrAppImpl.getContext().startActivity(intent); 304 } 305 306 }