Android App自动更新解决方案(DownloadManager)
一开始,我们先向服务器请求数据获取版本
- public ObservableField<VersionBean> appVersion = new ObservableField<>();
- /**
- * 获取服务器版本并判断是否需要更新
- */
- public void getServiceAppVersionEvent() {
- resource.getAppVersionEvent()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(response -> {
- if (EmptyUtil.isNotEmpty(response.body)) {
- appVersion.set(response.body);
- if (UpdateAppUtil.checkAppVersion(response.body)) {
- checkUpdate.set("发现新版本" + response.body.getVersion());
- }
- }
- });
- }
服务器返回的数据
- /**
- * Created by hyx on 17-9-29.
- */
- public class VersionBean {
- private String description;
- private String url;
- private String version;
- public String getUrl() {
- return url;
- }
- public void setUrl(String url) {
- this.url = url;
- }
- public String getVersion() {
- return version;
- }
- public void setVersion(String version) {
- this.version = version;
- }
- public String getDescription() {
- return description;
- }
- public void setDescription(String description) {
- this.description = description;
- }
- }
对比服务器和本地判断是否需要更新,我这里是根据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去查询下载状态,因为有可能用户之前已经下载了,没有安装,亦或正在下载中,下载暂停等情况,
- if (UpdateAppUtil.checkAppVersion(getViewModel().appVersion.get())) {
- //根据downloadId查询下载状态
- long downloadId = (long) SPUtil.get(PersonalActivity.this, "downloadId", -1L);
- UpdateAppUtil.checkDownloadStatus(downloadId, new DataBack<Integer>() {
- @Override
- public void take(Integer status) {
- if (status == -1) {
- new MaterialDialog.Builder(PersonalActivity.this)
- .title("版本更新")
- .content("发现新版本,是否更新?")
- .positiveText("确定")
- .negativeText("取消")
- .onPositive(((materialDialog, dialogAction) -> {
- ToastUtil.showShortToast("正在后台为您下载");
- UpdateAppUtil.downloadAPK(getViewModel().appVersion.get(), "ctrshoppix.apk");
- }))
- .onNegative((materialDialog, dialogAction) -> {
- materialDialog.dismiss();
- })
- .show();
- } else if (status == DownloadManager.STATUS_FAILED) {
- ToastUtil.showShortToast("下载失败,正在为您重新下载");
- UpdateAppUtil.downloadAPK(getViewModel().appVersion.get(), "ctrshoppix.apk");
- } else if (status == DownloadManager.STATUS_SUCCESSFUL) {
- if (UpdateAppUtil.compareApk(UpdateAppUtil.getApkInfo(UpdateAppUtil.getDownloadPath(downloadId)))) {
- UpdateAppUtil.installApp(UpdateAppUtil.getDownloadUri(downloadId));
- } else {
- UpdateAppUtil.removeDownloadId(downloadId);
- }
- }
- }
- });
具体的方法在下面UpdateAppUtil中查看,备注写的很清楚
- import android.app.Activity;
- import android.app.DownloadManager;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Build;
- import android.os.Environment;
- import android.support.v4.content.FileProvider;
- import android.text.BoringLayout;
- import java.io.File;
- import java.io.IOException;
- import ppm.ctr.cctv.ctr.application.CtrAppImpl;
- import ppm.ctr.cctv.ctr.common.AsyncCall;
- import ppm.ctr.cctv.ctr.common.DataBack;
- import ppm.ctr.cctv.ctr.network.entity.VersionBean;
- import ppm.ctr.cctv.ctr.services.file.UriPraseUtil;
- /**
- * Created by css on 2017/10/30.
- */
- public class UpdateAppUtil {
- private static DownloadManager downloadManager;
- /**
- * 获取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;
- }
- /**
- * 检查下载状态
- *
- * @param downloadId
- * @param dataBack
- */
- public static void checkDownloadStatus(long downloadId, DataBack<Integer> dataBack) {
- DownloadManager.Query query = new DownloadManager.Query();
- //通过下载的id查找
- query.setFilterById(downloadId);
- //获取DownloadManager
- if (EmptyUtil.isEmpty(downloadManager)) {
- downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
- }
- Cursor c = downloadManager.query(query);
- if (c.moveToFirst()) {
- int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
- switch (status) {
- case -1:
- dataBack.take(-1);
- break;
- //下载暂停
- case DownloadManager.STATUS_PAUSED:
- ToastUtil.showShortToast("下载暂停");
- break;
- //下载延迟
- case DownloadManager.STATUS_PENDING:
- ToastUtil.showShortToast("下载延迟");
- break;
- //正在下载
- case DownloadManager.STATUS_RUNNING:
- ToastUtil.showShortToast("正在下载");
- break;
- //下载完成
- case DownloadManager.STATUS_SUCCESSFUL:
- dataBack.take(DownloadManager.STATUS_SUCCESSFUL);
- break;
- //下载失败
- case DownloadManager.STATUS_FAILED:
- dataBack.take(DownloadManager.STATUS_FAILED);
- break;
- default:
- dataBack.take(-1);
- break;
- }
- dataBack.take(status);
- } else {
- //可能用户误删之前已经下载得apk
- dataBack.take(-1);
- }
- c.close();
- }
- /**
- * 根据downloadID获取本地存储的文件path
- *
- * @param downloadId
- * @return
- */
- public static String getDownloadPath(long downloadId) {
- //获取DownloadManager
- if (EmptyUtil.isEmpty(downloadManager)) {
- downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
- }
- String downloadPath = new File(UriPraseUtil.uriToFile(downloadManager.getUriForDownloadedFile(downloadId), CtrAppImpl.getContext())).toString();
- return downloadPath;
- }
- /**
- * 根据downloadID 获取获取本地文件存储的uri
- *
- * @param downloadId
- * @return
- */
- public static Uri getDownloadUri(long downloadId) {
- //获取DownloadManager
- if (EmptyUtil.isEmpty(downloadManager)) {
- downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
- }
- Uri downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId);
- //适配不同的手机,有的手机不能识别,所以再转一遍
- Uri uri = Uri.fromFile(new File(UriPraseUtil.uriToFile(downloadFileUri, CtrAppImpl.getContext())));
- return uri;
- }
- /**
- * 获取apk程序信息
- *
- * @param path apk path
- */
- public static PackageInfo getApkInfo(String path) {
- PackageManager pm = CtrAppImpl.getContext().getPackageManager();
- PackageInfo info = pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
- if (info != null) {
- return info;
- }
- return null;
- }
- /**
- * 下载的apk和当前程序版本比较
- *
- * @param apkInfo apk file's packageInfo
- * @return 如果当前应用版本小于apk的版本则返回true
- */
- public static boolean compareApk(PackageInfo apkInfo) {
- if (apkInfo == null) {
- return false;
- }
- if (!apkInfo.versionName.equals(getAppVersionName())) {
- return true;
- }
- return false;
- }
- /**
- * 下载apk
- *
- * @param versionBean
- * @param apkName
- */
- public static void downloadAPK(VersionBean versionBean, String apkName) {
- //创建下载任务
- DownloadManager.Request request = new DownloadManager.Request(Uri.parse(versionBean.getUrl()));
- //移动网络情况下是否允许漫游
- request.setAllowedOverRoaming(false);
- // 设置在通知栏是否显示下载通知(下载进度), 有 3 个值可选:
- // VISIBILITY_VISIBLE: 下载过程中可见, 下载完后自动消失 (默认)
- // VISIBILITY_VISIBLE_NOTIFY_COMPLETED: 下载过程中和下载完成后均可见
- // VISIBILITY_HIDDEN: 始终不显示通知
- request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
- request.setTitle("单单拍");
- request.setDescription("");
- request.setVisibleInDownloadsUi(true);
- //设置下载的路径
- request.setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory().getAbsolutePath(), apkName);
- //获取DownloadManager
- if (EmptyUtil.isEmpty(downloadManager)) {
- downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
- }
- //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
- long downloadId = downloadManager.enqueue(request);
- SPUtil.put(CtrAppImpl.getContext(), "downloadId", downloadId);
- }
- /**
- * 移除本地存储的downloadid 和相关文件
- *
- * @param downloadId
- */
- public static void removeDownloadId(long downloadId) {
- //获取DownloadManager
- if (EmptyUtil.isEmpty(downloadManager)) {
- downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
- }
- downloadManager.remove(downloadId);
- SPUtil.remove(CtrAppImpl.getContext(), "downloadId");
- }
- /**
- * 安装app
- *
- * @param uri
- */
- public static void installApp(Uri uri) {
- Intent intent = new Intent();
- intent.setDataAndType(uri, "application/vnd.android.package-archive");
- intent.setAction(Intent.ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- CtrAppImpl.getContext().startActivity(intent);
- }
- /**
- * 安装app
- *
- * @param apkPath
- */
- public static void installApp(String apkPath) {
- File file = new File(apkPath);
- Uri uri = null;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- String command = "chmod " + "777" + " " + file;
- Runtime runtime = Runtime.getRuntime();
- try {
- runtime.exec(command);
- } catch (IOException e) {
- e.printStackTrace();
- }
- uri = FileProvider.getUriForFile(CtrAppImpl.getContext(), "ppm.ctr.cctv.ctr.provider", file);
- } else {
- uri = Uri.fromFile(file);
- }
- Intent intent = new Intent();
- intent.setDataAndType(uri, "application/vnd.android.package-archive");
- intent.setAction(Intent.ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- CtrAppImpl.getContext().startActivity(intent);
- }
- }
Android App自动更新解决方案(DownloadManager)的更多相关文章
- Android学习系列(3)--App自动更新之自定义进度视图和内部存储
友好的视觉感知和稳定的不出错表现,来自于我们追求美感和考虑的全面性,博客园从技术的角度,一直我都很欣赏.这篇文章是android开发人员的必备知识,是我特别为大家整理和总结的,不求完美,但是有用. 这 ...
- H5+app -- 自动更新
一.最近做了一个app自动更新功能,用的基本都是网上找得到的. 1.h5+ 规范 : http://www.html5plus.org/doc/zh_cn/maps.html 2.环形进度条插件:h ...
- web app升级—带进度条的App自动更新
带进度条的App自动更新,效果如下图所示: 技术:vue.vant-ui.5+ 封装独立组件AppProgress.vue: <template> <div> <va ...
- Android实现自动更新功能
Android实现自动更新功能 Android自动更新的功能可以使用第三方的SDK来实现,但是类似友盟,就不支持x86手机的自动更新,科大讯飞,弹窗是全局的,小米手机就会默认把弹窗权限关掉不允许弹出提 ...
- Android应用自动更新功能的实现!
Android应用自动更新功能的实现!http://blog.csdn.net/android_tutor/article/details/7015986 private static final i ...
- Web APP自动更新
我们的手机软件每天都要经营,经常需要更新,比如程序的Bug,好的功能,好的洁面... ... 这就需要我们的用户打开web app时候自动更新客户端程序,而不是再去应用程序商店从新下载.今天的笔记就是 ...
- NEO4J中文分词全文索引自动更新解决方案
NEO4J中文分词全文索引自动更新解决方案 一.样例数据 二.英文与中文全文索引差别 1.创建NEO4J默认索引 2.删除索引 3.创建支持中文分词的索引 三.APOC自带英文全文索引过程(可自动更新 ...
- App自动更新(DownloadManager下载器)
一.开门见山 代码: object AppUpdateManager { const val APP_UPDATE_APK = "update.apk" private var b ...
- Android 云服务器的搭建和友盟APP自动更新功能的实现
setContentView(R.layout.activity_splash); //Bmob SDK初始化--只需要这一段代码即可完成初始化 //请到Bmob官网(http://www.bmob. ...
随机推荐
- 深入selenium三种等待方式使用
深入selenium三种等待方式使用 处理由于网络延迟造成没法找到网页元素 方法一 用time模块不推荐使用 用time模块中的time.sleep来完成等待 from selenium import ...
- win7系统防止中招勒索病毒
echo @@ netsh advfirewall firewall add rule name= netsh advfirewall firewall add rule name= netsh ad ...
- Pandas处理超大规模数据
对于超大规模的csv文件,我们无法一下将其读入内存当中,只能分块一部分一部分的进行读取: 首先进行如下操作: import pandas as pd reader = pd.read_csv('dat ...
- Violet音乐社区设计文档
目录 Violet音乐社区设计文档 一.引言 1.1 编写目的 1.2 开发背景 二.用例图设计 2.1游客实例设计 2.2 管理员实例设计 2.3 普通用户实例设计 三.类图设计 3.1 歌手类 3 ...
- 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁
一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...
- QPNP 8909 8916 充电相关(1)【转】
最近一直在搞电源管理相关内容,之前是8610的bms,现在8916的bms,发现两者还是有点区别的,8916把对last_ocv_uv的估值算法分装成执行文件,作为服务一直运行. 电源管理方面,应该是 ...
- [Linux] ubuntu环境安装和使用elasticsearch
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -apt-get install ap ...
- Codeforces Round #594 (Div. 2)
传送门 C. Ivan the Fool and the Probability Theory 题意: 给出一个\(n*m\)的方格,现在要给方格中的元素黑白染色,要求任一颜色最多有一个颜色相同的格子 ...
- oracle xmltype + blob + clob
oracle varchar2最大存储长度为4000,所以当字段长度超限时可尝试存储为blob或xmltype格式 xmltype --1.创建xml表 Create TABLE testxml( i ...
- 开放平台API接口安全策略汇总
在设计开放平台接口过程中,往往会涉及接口传输安全性相关的问题,本文对接口加密及签名的相关知识做了一个总结,在方便自己查阅的同时也分享给大家做一些参考. 接口安全性问题思考 接口安全性问题主要来源于几方 ...