一开始,我们先向服务器请求数据获取版本

    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)的更多相关文章

  1. Android学习系列(3)--App自动更新之自定义进度视图和内部存储

    友好的视觉感知和稳定的不出错表现,来自于我们追求美感和考虑的全面性,博客园从技术的角度,一直我都很欣赏.这篇文章是android开发人员的必备知识,是我特别为大家整理和总结的,不求完美,但是有用. 这 ...

  2. H5+app -- 自动更新

    一.最近做了一个app自动更新功能,用的基本都是网上找得到的. 1.h5+ 规范 :  http://www.html5plus.org/doc/zh_cn/maps.html 2.环形进度条插件:h ...

  3. web app升级—带进度条的App自动更新

    带进度条的App自动更新,效果如下图所示:   技术:vue.vant-ui.5+ 封装独立组件AppProgress.vue: <template> <div> <va ...

  4. Android实现自动更新功能

    Android实现自动更新功能 Android自动更新的功能可以使用第三方的SDK来实现,但是类似友盟,就不支持x86手机的自动更新,科大讯飞,弹窗是全局的,小米手机就会默认把弹窗权限关掉不允许弹出提 ...

  5. Android应用自动更新功能的实现!

    Android应用自动更新功能的实现!http://blog.csdn.net/android_tutor/article/details/7015986 private static final i ...

  6. Web APP自动更新

    我们的手机软件每天都要经营,经常需要更新,比如程序的Bug,好的功能,好的洁面... ... 这就需要我们的用户打开web app时候自动更新客户端程序,而不是再去应用程序商店从新下载.今天的笔记就是 ...

  7. NEO4J中文分词全文索引自动更新解决方案

    NEO4J中文分词全文索引自动更新解决方案 一.样例数据 二.英文与中文全文索引差别 1.创建NEO4J默认索引 2.删除索引 3.创建支持中文分词的索引 三.APOC自带英文全文索引过程(可自动更新 ...

  8. App自动更新(DownloadManager下载器)

    一.开门见山 代码: object AppUpdateManager { const val APP_UPDATE_APK = "update.apk" private var b ...

  9. Android 云服务器的搭建和友盟APP自动更新功能的实现

    setContentView(R.layout.activity_splash); //Bmob SDK初始化--只需要这一段代码即可完成初始化 //请到Bmob官网(http://www.bmob. ...

随机推荐

  1. CSS定位和滚动条

    0805自我总结 一.绝对定位 position: absolute; /*绝对定位: 1.定位属性值:absolute 2.在页面中不再占位(浮起来了),就无法继承父级的宽度(必须自己自定义宽度) ...

  2. css盒子布局,浮动布局以及显影与简单的动画

    08.05自我总结 一.盒子布局 1.盒子布局的组成 margin border padding content 2.margin margin是外边距,控制盒子的显示位置相对于他的上一级 left. ...

  3. Business Model Design 业务模型设计

    Note This section is split into two parts, which describe the use of two different Object-relational ...

  4. Pandas:DataFrame数据选择方法(索引)

    #首先创建我们的Series对象,然后合并到dataframe对象里面去 import pandas as pd import numpy as np area=pd.Series({,,,}) po ...

  5. 远程访问阿里云服务器jupyter

    官网链接 一.pip安装jupyter安装Anaconda的话,会自动按照jupyter,就不需要再使用pip安装了 pip3 install jupyter 二.生成jupyter notebook ...

  6. 小程序组件化开发框架---wepy 项目创建

    wepy是一个优秀的微信小程序组件化框架,突破了小程序的限制,支持了npm包加载以及组件化方案.这里就以我个人的经历讲下怎么创建wepy项目. 1.首先 在桌面(自己选定目录下)新建一个文件夹,注意需 ...

  7. ubuntu下需要补充安装 manpages手册; 安装linux 社区最新的linux manpages 文档;

    使用man手册的方式,能大大加快开发速度,可能安装的时候有些安装不完整,下面结合网络上搜索信息进行补充: $ sudo apt-get install manpages $ sudo apt-get ...

  8. Scrapy对接Selenium

    首先pip安装selenium,然后下载浏览器驱动 WebDrive下载地址 chrome的webdriver:http://chromedriver.storage.googleapis.com/i ...

  9. 《icra16_slam_tutorial_tardos.pdf》

    icra16_slam_tutorial_tardos.pdf EKF: https://www.cnblogs.com/gaoxiang12/p/5560360.html 7. 小结 卡尔曼滤波是递 ...

  10. Linux学习笔记-第19天 结束了。突然感觉配置一个服务好简单的样子

    课程结束了,这本书又过了一遍,感觉学习到了不少的新知识.虽然整个过程老师讲的有点仓促,但回头想想身处于这个知识大爆炸的时代,学习不单要追求知识面宽广,更需要注重学习的效率,某种角度来讲,这也是一种鞭策 ...