Java4Android之APP自动升级

一个成熟的商业APP必须不断的退出新的版本。那么,不可能让用户自己去应用市场去下载新版本的应用,我们应该在应用内部提供自动升级的功能。自动升级其实包含两个层面,一个是整个APP的升级,也就是下载新版本的APP,然后安装替换掉现有的。还有一种升级是模块升级,这种升级一般采用静默升级,就是用户完全不知道。这个在我大迅雷里面经常做的,拿各个渠道去试错,对于一个互联网公司而言是再普通不过的了。而这些模块,肯定是诸如,解析库,下载库,播放库,这些后台库。。

不过今天,我要说的是APP的自动升级,模块的静默升级我们下次有时间再说。

APP升级流程

盗用别人的图,来说明一下升级APP的整体流程。

对,这个图是盗用别人的。因为,这就是APP升级的一般流程。

所以,我们知道了,第一步,我们需要去服务器查询版本信息,确定是不是要进行升级。

到服务器查询版本信息

具体见代码,

private static final class UpgradeLoader extends AsyncTask<Void, Void, UpdateInfo> {
        private WeakReference<Activity> mContext;
        private boolean mAuto;
        private IUpgradeCheck mUpgradeCheckListener;
        protected boolean mChecked;

        public UpgradeLoader(Activity context, boolean auto, IUpgradeCheck listener) {
            mContext = new WeakReference<Activity>(context);
            mAuto = auto;
            mUpgradeCheckListener = listener;
        }

        @Override
        protected void onPreExecute() {
            if (mUpgradeCheckListener != null) {
                mUpgradeCheckListener.beforeCheck();
            }
        }

        @Override
        protected UpdateInfo doInBackground(Void... params) {
            if (mUpgradeCheckListener != null) {
                mUpgradeCheckListener.onCheck();
            }
            Context ctx = mContext.get();
            String channel = "";
            if (ctx != null) {
                channel = Util.getChannelID(ctx);
            }

            return DataProxy.getInstance().getUpdateInfo(Util.getVersionName(MyApplication.sInstance),
                    Util.getOSVersion(), channel); //去服务器查询版本信息,这个是我们对http的一个封装,在这里,每个公司可以自己定义一些自己的地址和参数,非常简单的。
        }

        @Override
        protected void onPostExecute(UpdateInfo result) {//从服务器查询回来,决定要不要升级
            if (mUpgradeCheckListener != null) {
                mUpgradeCheckListener.afterCheck();
            }
            if (!isCancelled()) {
                if (result == null) {
                    if (!mAuto) {
                        UIHelper.showToast(MyApplication.sInstance, "检查更新失败", Toast.LENGTH_SHORT);
                    }
                } else {
                    switch (result.type) {
                    case UpdateInfo.NO_UPGRADE:
                        if (!mAuto) {
                            UIHelper.showToast(KankanApplication.sInstance, "已经是最新版本,没有更新", Toast.LENGTH_SHORT);
                        }
                        break;

                    case UpdateInfo.UPDATE_NOT_TIPS:
                        if (!mAuto) {
                            buildDialog(result);
                        } else {
                            downloadApk(KankanApplication.sInstance, result.latestUrl);
                        }

                        break;
                    case UpdateInfo.UPDATE_TIPS:
                    case UpdateInfo.UPDATE_FOURCE:
                        if (!(mAuto && PreferenceManager.instance(mContext.get()).isVerionSkiped(result.latestVersion))) {
                            buildDialog(result);
                        }

                    default:
                        break;
                    }
                }
            }
        }

注意上述代码。我们仅仅是示意,所以不可能把所有代码提供给大家学习。就是你第一步是去服务器查询版本信息。然后确定要下载APK的时候,则会调用downloadApk函数。对APK进行下载。

下载APK

在网上,很多人提供了采用httpclient去下载APK的方法,我这里给出另外一种思路。两种方法都可以,建议采用我们的提供的,因为,这个是针对下载较大文件的系统方法。

详见代码:

private static void downloadApk(Context context, String url) {
        DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        Uri uri = Uri.parse(url);
        String scheme = uri.getScheme();
        if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) {
            LOG.error("only supports http/https url={}", url);
        } else {
            try {
                DownloadManager.Request down = new DownloadManager.Request(uri);
                down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE
                        | DownloadManager.Request.NETWORK_WIFI);
                down.setShowRunningNotification(true);
                down.setVisibleInDownloadsUi(true);
                down.setDestinationInExternalFilesDir(context, null, APK_NAME);
                manager.enqueue(down);//开始下载
            } catch (Exception e) {
                e.printStackTrace();

                UIHelper.showToast(context, "下载应用失败,请您去应用市场升级", Toast.LENGTH_LONG);
            }
        }
    }

这样,使用DownloadManager可以非常方便的实现APK的下载。如果想对这个类进行更加深入的了解,大家可以去查询相关的资料。你可以查询下载进度等等相关的信息。

下载完成了,接下来就是要安装了。我们需要一个事件去触发安装。做法是,我们应该监听下载完成这件事情,下载完成之后,会有个广播发生,当监听到这个广播的时候我们就开始安装。

安装APK

监听下载完成,并安装。

    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {//监听下载完成
            long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            if (id > -1) {
                File file = queryFile(context, id);
                if (file != null && file.exists()) {
                    Intent startInent = new Intent();
                    startInent.setAction(Intent.ACTION_VIEW);
                    startInent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startInent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                    context.startActivity(startInent);//安装APK
                }
            }
        }
    }

至此,一个APK的自动升级就完成了。其实还有一些善后工作需要做的是,你需要删除APK,删除APK的方法应该是在安装完成之后删除,网上有说通过广播监听的方法来删除,就是监听到安装完成之后删除。这个大家去搜索一下就可以。

删除APK文件

这里,我还是给出点示例:

首先是要获取应用的安装状态,通过广播的形式

以下是和应用程序相关的Broadcast Action

ACTION_PACKAGE_ADDED 一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)

ACTION_PACKAGE_REPLACED 一个新版本的应用安装到设备,替换之前已经存在的版本

ACTION_PACKAGE_CHANGED 一个已存在的应用程序包已经改变,包括包名

ACTION_PACKAGE_REMOVED 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)

ACTION_PACKAGE_RESTARTED 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)

ACTION_PACKAGE_DATA_CLEARED 用户已经清楚一个包的数据,包括包名(清除包程序不能接收到这个广播)

代码实现

AndroidManifest.xml中定义广播

<receiver android:name=".AppInstallReceiver"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_REPLACED" />
                <action android:name="android.intent.action.PACKAGE_REMOVED" />
                <data android:scheme="package" />
            </intent-filter>
        </receiver>

然后是接收端:

public class AppInstallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        PackageManager manager = context.getPackageManager();
        if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
            String packageName = intent.getData().getSchemeSpecificPart();
            Toast.makeText(context, "安装成功"+packageName, Toast.LENGTH_LONG).show();
        }
        if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
            String packageName = intent.getData().getSchemeSpecificPart();
            Toast.makeText(context, "卸载成功"+packageName, Toast.LENGTH_LONG).show();
        }
        if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
            String packageName = intent.getData().getSchemeSpecificPart();
            Toast.makeText(context, "替换成功"+packageName, Toast.LENGTH_LONG).show();
<span style="white-space:pre">		</span>doanloadApk.delete();//从SD中删除刚刚下载的APK文件
        }

    }
}

好。APK自动升级就说道这里。

有时间,给大家说一下模块的静默升级的实现。

时间: 2024-12-07 15:17:38

Java4Android之APP自动升级的相关文章

Ionic实战 自动升级APP(Android版)

Ionic 框架介绍 Ionic是一个基于Angularjs.可以使用HTML5构建混合移动应用的用户界面框架,它自称为是"本地与HTML5的结合".该框架提供了很多基本的移动用户界面范例,例如像列表(lists).标签页栏(tab bars)和触发开关(toggle switches)这样的简单条目.它还提供了更加复杂的可视化布局示例,例如在下面显示内容的滑出式菜单. Ionic 自动升级APP一.准备工作 1.Cordova插件: cordova plugin add https:

自动更新(自动升级)组件分享

原文:自动更新(自动升级)组件分享 自从接触安装部署以来就有软件升级的需求,最简单的就是clickonce,但无法做到深入控制,本寄希望于WIX可以自己实现,但现在还没有找到例子.然后才自己实现. 要声明一下,这是在圣殿骑士AutoUpdater基础上改动过来的.基于他分享的精神,我也继续分享.我主要做了以下改动. 1.加入客服端安装版本和下载版本检测. 2.加入更新提示. 3.做了一些异常处理,增加了接口方法. 4.加入了皮肤. 按照国际惯例,先上图:    原理简介 最基本原理还是借助于圣殿

MVP+多线程+断电续传 实现app在线升级库 (手把手教你打造自己的lib)

作者: 夏至 欢迎转载,也请保留这份申明,谢谢. http://blog.csdn.net/u011418943/article/details/70562580 1.需求分析 App 在线升级是比较传统的修复bug的一种方式,一般添加新功能或者说修改一下比较严重的bug的时候,我们都是会升级apk来实现我们的目的:当然,其实一些紧急的bug的其实是用 热修复 的方法,毕竟有时候只是一行代码出了问题,而你却要升级一整个apk,下载安装等等,除了代价有点高,也会影响口碑的. 等等,你都说成这样,还

基于esky实现python应用的自动升级

一.esky介绍 Esky is an auto-update framework for frozen Python applications. It provides a simple API through which apps can find, fetch and install updates, and a bootstrapping mechanism that keeps the app safe in the face of failed or partial updates.

C# Xamarin For Android自动升级项目实战

一.课程介绍 "明人不说暗话,跟着阿笨一起玩Xamarin",本次分享课程阿笨将带来大家一起学习Xamarin For Android系列<C# Xamarin For Android自动升级项目实战>.如果您同样对本次分享课程感兴趣的话,那么请跟着阿笨一起学习吧. 本次分享课程适合人群如下: 1. 热爱Xamarin跨平台移动开发. 2.进一步了解和学习Xamarin For Android移动开发实战知识. 本次分享课包含实战分享知识点如下: 1.C# Android 

HTML5进阶 二 HBuilder实现软件自动升级

HBuilder实现软件自动升级 前言 移动APP开发好后需要实现软件自动升级功能,经过一番搜索,发现HBuilder具有"App资源在线升级更新"的功能,遂研究之. 经过一番测试,在源码思想的基础之上对其进行了优化.代码如下: var wgtVer = null; function plusReady(){ // 获取本地应用资源版本号 plus.runtime.getProperty(plus.runtime.appid,function(inf){ wgtVer=inf.vers

C#Winform程序如何发布并自动升级(图解)

有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布 关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解) 其实打包是打包,发布是发布两者是没有任何关系的,只是有些同志会分不清楚.混在一起了. 下在面大家就和我一起来做一个发布并升级的程序吧. 首先我们准备几个工作 1.新建一个存储发布后程序的目录比如D:\iis\textWinform  以下简称-- 发布目录 2.在IIS新建一个网站并指向目录D:\iis\auto

实全软件产品自动升级管理解决方案

实全软件产品自动升级管理解决方案 目 录 1.    描述... 1 2.    产品管理后台系统... 1 2.1.     产品发布... 1 2.2.     产品下载... 2 2.3.     下载日志... 3 2.4.     异常日志... 3 3.    产品Web Service服务接口... 3 3.1.     接口说明... 4 4.    产品升级更新程序... 4 4.1.     产品升级自动更新工具... 5 4.2.     产品版本信息... 5 5.   

Delphi : 自动升级组件AutoUpgrader简单教程(初学者)

AutoUpgrader简单教程(写给初学者) 1.放置一个TauAutoUpgrader在窗体上 2.双击auAutoUpgrader1,在弹出的对话框中设定一些要件: 首先选择按日期还是按版本号检查更新并填好日期或版本号(该日期或版本号也可以在会同时记录在VersionData属性里,版本号主要通过该属性来检查),然后单击add按钮添加需要更新的文件的http下载地址,因AutoUpgrader仅支持http方式,不支持ft方式,所以不要填错.Upgrade method默认即可:然后在“R