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

    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. PlayJava Day020

    1.异常Exception补充: ①错误(Error)指的是致命性错误,一般无法处理 ②异常以类的形式封装 程序可以处理的异常对应的类是java.lang.Exception及其子类 运行时异常对应的 ...

  2. CSS学习笔记-盒子阴影及文字阴影

    盒子阴影:    1.格式:        box-shadow:h-shadow v-shadow blur spread color insert;        box-shadow:水平偏移 ...

  3. java简单实现用语音读txt文档

    最近比较无聊,随便翻着博客,无意中看到了有的人用VBS读文本内容,也就是读几句中文,emmm,挺有趣的,实现也很简单,都不需要安装什么环境,直接新建txt文件,输入一些简单的vbs读文本的代码,然后将 ...

  4. windows提权

    提权辅助 https://bugs.hacking8.com/tiquan/

  5. 更改组织属性-以更改maxrecordsforexporttoexcel为例

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复232或者20161101可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  6. Acwing40. 顺时针打印矩阵

    地址 https://www.acwing.com/solution/acwing/content/3623/ 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 样例 输入: [ [, ...

  7. vivado2017.1和modelsim10.5联合仿真

    vivado2017.1和modelsim版本 vivado可在xilinx官网查询匹配的modelsim最低版本,下载modelsim前记得选用合适的版本号,如图 查询地址:https://www. ...

  8. C# List<T> 转 DataTable

    C# List<T>转DataTable 学习自:博客园 Overview 数据!!个人认为程序就是将数据变着花样的显示它.那么这个时候我们的数据处理和获取就时我们的关键一步,如果你数据都 ...

  9. 利用Python几行代码批量生成验证码

    几行代码批量生成authCode 整体步骤: 1.创建图片 2.创建画笔 3.在图片上生成点 4.在图片上画线 5.在图片在画圆 6.在图片在写文本 7.在图片在生成指定字体的文本 代码奉上 #!/u ...

  10. 报错:Something is already running on port 8000.

    在用react框架的时候,用cnpm run dev命令执行项目时,有时会出现这种错误, 这是因为你之前执行过该命令,但是没关闭,解决办法是打开任务管理器, 在进程中找到node.exe,右键关闭这个 ...