Android应用客户端通常会需要更新,而且根据需求分为普通更新和强制更新。是否强制更新可通过检查更新时从服务器获取的标志位来判断。

public class UpdateManager {
private Context mContext; //上下文 private String apkUrl =
"http://183.232.83.10/dd.myapp.com/16891/" +
"C4F9FF39FAE9184222DC278DC7309611.apk?mkey" +
"=5541c92b6a9cca8d&f=d388&fsname=com.yangmbin" +
".beauty_1.1_2.apk&asr=8eff&p=.apk"; //apk下载地址
private static final String savePath = "/sdcard/updateAPK/"; //apk保存到SD卡的路径
private static final String saveFileName = savePath + "apkName.apk"; //完整路径名 private ProgressBar mProgress; //下载进度条控件
private static final int DOWNLOADING = 1; //表示正在下载
private static final int DOWNLOADED = 2; //下载完毕
private static final int DOWNLOAD_FAILED = 3; //下载失败
private int progress; //下载进度
private boolean cancelFlag = false; //取消下载标志位 private double serverVersion = 2.0; //从服务器获取的版本号
private double clientVersion = 1.0; //客户端当前的版本号
private String updateDescription = "更新描述"; //更新内容描述信息
private boolean forceUpdate = true; //是否强制更新 private AlertDialog alertDialog1, alertDialog2; //表示提示对话框、进度条对话框 /** 构造函数 */
public UpdateManager(Context context) {
this.mContext = context;
} /** 显示更新对话框 */
public void showNoticeDialog() {
//如果版本最新,则不需要更新
if (serverVersion <= clientVersion)
return;
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle("发现新版本 :" + serverVersion);
dialog.setMessage(updateDescription);
dialog.setPositiveButton("现在更新", new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
arg0.dismiss();
showDownloadDialog();
}
});
//是否强制更新
if (forceUpdate == false) {
dialog.setNegativeButton("待会更新", new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
arg0.dismiss();
}
});
}
alertDialog1 = dialog.create();
alertDialog1.setCancelable(false);
alertDialog1.show();
} /** 显示进度条对话框 */
public void showDownloadDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle("正在更新");
final LayoutInflater inflater = LayoutInflater.from(mContext);
View v = inflater.inflate(R.layout.softupdate_progress, null);
mProgress = (ProgressBar) v.findViewById(R.id.update_progress);
dialog.setView(v);
//如果是强制更新,则不显示取消按钮
if (forceUpdate == false) {
dialog.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
arg0.dismiss();
cancelFlag = false;
}
});
}
alertDialog2 = dialog.create();
alertDialog2.setCancelable(false);
alertDialog2.show(); //下载apk
downloadAPK();
} /** 下载apk的线程 */
public void downloadAPK() {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
URL url = new URL(apkUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect(); int length = conn.getContentLength();
InputStream is = conn.getInputStream(); File file = new File(savePath);
if(!file.exists()){
file.mkdir();
}
String apkFile = saveFileName;
File ApkFile = new File(apkFile);
FileOutputStream fos = new FileOutputStream(ApkFile); int count = 0;
byte buf[] = new byte[1024]; do{
int numread = is.read(buf);
count += numread;
progress = (int)(((float)count / length) * 100);
//更新进度
mHandler.sendEmptyMessage(DOWNLOADING);
if(numread <= 0){
//下载完成通知安装
mHandler.sendEmptyMessage(DOWNLOADED);
break;
}
fos.write(buf, 0, numread);
}while(!cancelFlag); //点击取消就停止下载. fos.close();
is.close();
} catch(Exception e) {
mHandler.sendEmptyMessage(DOWNLOAD_FAILED);
e.printStackTrace();
}
}
}).start();
} /** 更新UI的handler */
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case DOWNLOADING:
mProgress.setProgress(progress);
break;
case DOWNLOADED:
if (alertDialog2 != null)
alertDialog2.dismiss();
installAPK();
break;
case DOWNLOAD_FAILED:
Toast.makeText(mContext, "网络断开,请稍候再试", Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
}; /** 下载完成后自动安装apk */
public void installAPK() {
File apkFile = new File(saveFileName);
if (!apkFile.exists()) {
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + apkFile.toString()), "application/vnd.android.package-archive");
mContext.startActivity(intent);
}
}
对话框中进度条用到的布局:softupdate_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="@+id/update_progress"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
style="?android:attr/progressBarStyleHorizontal" />
</RelativeLayout>

使用方法:

//这里来检测版本是否需要更新
mUpdateManager = new UpdateManager(this);
mUpdateManager.showNoticeDialog();

检查更新通常是在初始化的时候,请求服务器检查版本,如果有更新,则把相关url、是否强制更新和版本号等信息通过showNoticeDialog的参数传递进去,做相关的初始化即可。

Android检查更新(是否强制更新)的更多相关文章

  1. Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理

    RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加Header ...

  2. Android 5.X新特性之为RecyclerView添加HeaderView和FooterView

    上一节我们讲到了 Android 5.X新特性之RecyclerView基本解析及无限复用 相信大家也应该熟悉了RecyclerView的基本使用,这一节我们来学习下,为RecyclerView添加H ...

  3. 【Android】一种提高Android应用进程存活率新方法

    [Android]一种提高Android应用进程存活率新方法 SkySeraph Jun. 19st 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph ...

  4. Android下添加新的自定义键值和按键处理流程

            Android下添加新的自定义键值和按键处理流程     说出来不怕大家笑话,我写这篇博客的原因在于前几天去一个小公司面试Android系统工程师,然后在面试的时候对方的技术总监问了我 ...

  5. Android系统在新进程中启动自定义服务过程(startService)的原理分析

    在编写Android应用程序时,我们一般将一些计算型的逻辑放在一个独立的进程来处理,这样主进程仍然可以流畅地响应界面事件,提高用户体验.Android系统为我们提供了一个Service类,我们可以实现 ...

  6. 《Android群英传》读书笔记 (5) 第十一章 搭建云端服务器 + 第十二章 Android 5.X新特性详解 + 第十三章 Android实例提高

    第十一章 搭建云端服务器 该章主要介绍了移动后端服务的概念以及Bmob的使用,比较简单,所以略过不总结. 第十三章 Android实例提高 该章主要介绍了拼图游戏和2048的小项目实例,主要是代码,所 ...

  7. Android群英传》读书笔记 (1) 第一章 Android体系与系统架构 + 第二章 Android开发工具新接触

    第一章 Android体系与系统架构 1.Dalvik 和 ARTDalvik好比是一辆可折叠的自行车,平时是折叠的,只有骑的时候,才需要组装起来用.ART好比是一辆组装好了的自行车,装好就可以骑了. ...

  8. Android 6.0 新特性 整理 资料来自网络

    Android 6.0新特性 Runtime Permissions Doze and App Standby Apache HTTP Client Removal BoringSSL Access ...

  9. android 5.0新特性

    Android Lollipop 面向开发人员的主要功能 Material Design 设计 注重性能 通知 以大屏幕呈现 以文档为中心 连接性能再上一级 高性能图形 音频处理功能更强 摄像头和视频 ...

随机推荐

  1. CPU的CAS操作

    https://blog.csdn.net/qq_35492857/article/details/78471032 https://www.cnblogs.com/gdjdsjh/p/5076815 ...

  2. canvas基础入门(一)canvas的width、height于css样式中的宽高区别

    canvas的width.height于css样式中的宽高对画布的内容显示是有所区别的 1.在canvas标签下调用他的width和height,而且是没有单位的宽高,这种指定canvas大小的方法也 ...

  3. my.宠物升级79级

    1.蚌仙子 74级半不到的时候,吃  月华露(500000经验的那种)  吃3个 正好 79级半 我记得 之前 是升满75级 再吃月华露 到79级的时候 经验溢出了.不突破还好,突破的话 宠物就升级了 ...

  4. OS---外存分配方式

    1.概述 1.1 在为文件分配外存空间时,所考虑的主要问题:如何有效利用外存空间?如何提高对文件的访问速度? 1.2 常用的外存分配方法:连续分配.链接分配.索引分配(在一个系统中,仅采用一种分配方式 ...

  5. 持久层框架---jdbc

    1.JDBC编程步骤: 1.1 加载数据库驱动: 1.2 获取数据库连接: 1.3 通过Connection对象创建Statement对象: 1.4 使用Statement对象执行SQL语句: 1.5 ...

  6. Django-4 模板层

    你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. def current_datetime(request): now = datet ...

  7. 利用Intent.ACTION_SEND进行分享

    安卓系统本身可以很简便的实现分享功能,因为我们只需向startActivity传递一个ACTION_SEND的Intent,系统就为我们弹出一个应用程序列表.其实在系统的文件管理器中,这应该是我们常用 ...

  8. http三次握手四次挥手

    最近一直忙于看前端vue相关内容,后端相关内容没有跟进,文章停了3周,,,哎,还是懒吧!子曰生命在于运动,该学习还是要学的,文章嘛也还是要整理滴,不扯了--- 参考: https://blog.csd ...

  9. 实例化php类的时候如何传参

    当我们实例化一个php类的时候,要怎么传递参数呢?这取决于该类的构造方法. 例: person.class.php <?php class person{ var $name; var $col ...

  10. Js获取移动设备分辨率

    在<head>中引入  <meta name="viewport" content="width=device-width, initial-scale ...