关于Android的自动更新库(使用心得)

起因

公司是工厂类型的,App是内部的员工使用的,所以我的App不需要上线,每次用AndroidStudio写好新版本之后,拿到车间给他们一个个装好就行。但是这样就很麻烦,而且还有比较远的工厂里面的工人,我总不能每次都跑大老远过去给他们装吧。所以,由于工作的需要,我得为我的App加上一个自动更新功能。这样我每次更新都只要自己操作一下,然后他们就可以远程更新了,说了半天都是废话,下面写经过。

经过

上网看了看,发现了两个可以试试的库,分别是https://github.com/yoojia/NextVersions和https://github.com/hugeterry/UpdateDemo ,
由于UpdateDemo比较简单,我就先尝试了这个。

1.hugeterry/UpdateDemo

这个库的用法我搬运一下。

Step 1

在gradle文件中加入下面的依赖:

dependencies {
    compile 'cn.hugeterry.updatefun:updatefun:1.9.0'
}

如果你使用Maven,那么加入下面的依赖:


  cn.hugeterry.updatefun
  updatefun
  1.9.0
  pom

Step 2

在主界面activity的onCreate()中加上以下语句进行初始化(请放在setContentView()方法的后面):

UpdateKey.API_TOKEN = "写上你fir.im账号的API_TOKEN";
UpdateKey.APP_ID = "写上APP的应用ID";
//下载方式:
//UpdateKey.DialogOrNotification=UpdateKey.WITH_DIALOG;通过Dialog来进行下载
//UpdateKey.DialogOrNotification=UpdateKey.WITH_NOTIFITION;通过通知栏来进行下载(默认)
UpdateFunGO.init(this);

Step 3

在主界面Activity中加上以下语句:

 @Override
    protected void onResume() {
        super.onResume();
        UpdateFunGO.onResume(this);
    }
  @Override
     protected void onStop() {
         super.onStop();
         UpdateFunGO.onStop(this);
     }

是不是特别简单好用?事实上的确如此,虽然我也遇到了不少的坑。怪我自己蠢。

注意点

  1. 第二步的初始化是在Activity里面初始化,并不是在Application里面!我习惯性的去Application里面进行了初始化,导致了程序安装好就崩溃的现象,后来才发现初始化的位置出错了,真是粗心,后来放到了Activity里面就没问题了。

  2. 另外,我们需要在fir.im这个网站上注册一个账号,然后你就可以获取AppId和API_TOKEN了。免费账号的话,一天可以进行10次下载,对我来说是够用的。但是要注意一点,就是这个库的更新依据就是版本号的变化,所以你上传apk文件的时候必须让版本号增加。(听起来是废话,不过我一开始没有升级自己的版本号,以为只要上传了以后就可以,结果就一直是1.0版本,导致手机端请求网络时一直为最新版本,不用更新,就不会自动下载了。)

  3. 那么在Android上怎么修改版本号呢?我习惯性的去修改Manifest文件了,但是这貌似没用,后来才发现我得修改build.gradle(Module:app)这个里面的配置。
    关于Android的自动更新库(使用心得)_第1张图片
    把versionName修改以后,apk的版本才会变化。

  4. 那么怎么生成新版本的Apk呢?我总得生成新的apk才可以上传吧。
    由于我的apk不需要签名,直接用就行,所以需要别的方式生成apk。
    首先,点击右侧的Gradle,进入:app下的build目录,双击assemble,就可以生成apk。(可能需要等一段时间)
    关于Android的自动更新库(使用心得)_第2张图片

然后把左侧的项目目录改成project模式的,去app-build-outputs-apk下面,找到app-debug.apk,这就是我们刚刚生成的apk,右键复制到桌面上就可以用了。
关于Android的自动更新库(使用心得)_第3张图片

接着就可以拖拽桌面上的apk进行上传了。
关于Android的自动更新库(使用心得)_第4张图片
上传以后,我们在 编辑 里面,就可以看到我们刚刚上传的版本了,这才是可以进行更新的版本,所以重点是,一定要让版本号增加!
关于Android的自动更新库(使用心得)_第5张图片
这里显示的1.02就是我们刚刚修改的那个versionName,现在就可以进行更新操作啦。 如果现在打开我们最开始的1.0app,当然是已经配置好这个库的,就会发现刚打开app就会弹出对话框询问我们是否更新。对了,这里的标记上线按钮我以为要点了才可以更新的,后来我发邮件问了作者hugeTerry,作者说不用,只要有版本号的变化就行。(作者的回复效率很高,github上找到他的邮箱给他发邮件,很快就回复我了,而且很耐心,非常感谢他教我)

这里1.02是versionName,Build 1 指的是versionCode,我现在才明白,判断是否更新的依据是versionCode的大小而不是versionName,至于我这里为什么也成功了我想大概是我运气好,也许这个库加入了当versionCode相同时,对比versionName的大小?总之,以后更新还是要依据versionCode 变化,因为这个是整数,而且方便比较。

基本上就是这样了,然而我并不能进行使用!因为我老大告诉我,必须使用内网来进行更新,所以这个要链接外网的库就不能用了!好不容易研究出来,这样一个简单的库却不能使用还是挺可惜的,不过也没事,的确,内部使用的app就是应该连内网,也就是我们自己的服务器,所以我打算使用最开始第一个库试试。

2.yoojia/NextVersions

首先先搬运一下步骤:

Step 1 - 依赖

AnyVersion 最新版本已推送到 Maven Central 和 JCenter 两个服务中。请查看项目根build.gradle文件配置信息中是否存在 jcenter 或者 mavenCentral 选项。如果没有,请添加。

allprojects {
    repositories {
        jcenter()
        // OR: mavenCentral()
    }
}

然后,在 Android Studio 项目使用 AnyVersion 库的模块的 build.gradle 中添加如下依赖项:

dependencies {
   ... others ...
   compile 'com.github.yoojia:anyversion:1.0@aar'
}

Step 2 - Android 权限

AnyVersion 需要的权限非常少,在 App 模块的 AndroidManifest.xml 文件中添加以下内容:




注意:不要嵌套在 application 中,在它的外层。

Step 3 - 初始化

AnyVersion 被设计成一个单例。因此,每个 App 中只允许存在一个 AnyVersion 实例。建议在自定义 Application 类的 onCreate(...) 方法中初始化 AnyVersion 单例。

例如:

public class AnyVersionApplication extends Application {
   @Override
   public void onCreate() {
       super.onCreate();
       AnyVersion.init(this, new VersionParser() {
           @Override
           public Version onParse(String response) {
               final JSONTokener tokener = new JSONTokener(response);
               try {
                   JSONObject json = (JSONObject) tokener.nextValue();
                   return new Version(
                           json.getString("name"),
                           json.getString("note"),
                           json.getString("url"),
                           json.getInt("code")
                   );
               } catch (JSONException e) {
                   e.printStackTrace();
               }
               return null;
           }
       });
   }
}

这样可以保证 AnyVersion 只初始化一次。如果初始化多次,AnyVersion 只使用首次初始化的 VersionParser 接口。其它的初始化操作将会被忽略。

- 设置检查新版本 API 的 URL

AnyVersion 允许改变检查新版本 API 的 URL 地址。在初始化 AnyVersion 单例后,需要设置检查新版本的 URL 地址。

AnyVersion version = AnyVersion.getInstance();
version.setURL("http://192.168.1.2:8082/android/release.json");

AnyVersion 内置了 HTTP 请求,可以获取此 URL 的响应数据,交由 VersionParser 接口解析。

- VersionParser 版本数据解析接口

由于每个项目需求不同,服务端返回的数据格式也不同。因此,需要实现 VersionParser 接口来将不同的服务端响应数据解析成 Vesion 对象。

new Parser() { 
    @Override public Version onParse(String response) {
    return 
        new Version(versionName, versionNote, downloadURL, versionCode);
   }
}

接口的实现类,需要将 onParse(response) 回调方法中的的 response 字符串解析,获取其中的 versionName,versionNote, versionCode,downloadURL 解析,并创建和返回 Version 对象。

Step 4 - 检查 APP 新版本

AnyVersion 提供了三种处理新版本的方式。 这三种方式基本满足正常的应用需求。

  • 弹出窗口 - NotifyStyle.Dialog
  • 回调接口 - NotifyStyle.Callback
  • 应用广播 - NotifyStyle.Broadcast

通过anyVerson.check(NotifyStyle)接口来触发检查新版本。

AnyVersion version = AnyVersion.getInstance();
version.check(NotifyStyle);

- 弹出窗口 Dialog

AnyVersion 的弹出窗口提醒新版本方式,需要android.permission.SYSTEM_ALERT_WINDOW 权限:


当远程服务器的版本(versionCode)大于当前应用的版本数时,AnyVersion 将弹出一个对话框让用户选择是否升级。

- 回调接口 Callback

使用 Callback 可以自定义处理新版本的方式。在 check(NotifyStyle) 前,需要设置 Callback 接口的实现。

AnyVersion version = AnyVersion.getInstance();
    version.setCallback(new Callback() {
        @Override
        public void onVersion(Version version) {
            Log.d("AnyVersion","New Version: \n" + version);
        }
    });

注意:仅当 NotifyStule.Callback 时,此 Callback 接口才会被回调。

- 应用广播 Broadcast

使用 Broadcast 来处理新版本,这种方式很不寻常,不过仍然存在。
AnyVersion 限制了接收广播的 Receiver 类型必须为 VersionReceiver 子类,此举是为少 AnyVersion 的复杂度。

class NewVersionReceiver extends VersionReceiver{
    @Override
    protected void onVersion(Version newVersion) {
        System.out.println(">> Broadcast === \n" + newVersion);
    }
}

Android 的广播机制,建议用户在 Activity.onStart() 中注册 Receiver,在 Activity.onStop() 中移除。AnyVersion 提供了注册和反注册的方法。

@Override
protected void onStart() {
    super.onStart();
    AnyVersion.registerReceiver(this, newVersionReceiver);
}

@Override
protected void onStop() {
    super.onStop();
    AnyVersion.unregisterReceiver(this, newVersionReceiver);
}

Step 5 - 自动安装 App

当 App 用户同意更新,并且应用下载完成后,AnyVersion 会检查下载文件是否为 APK 文件。如果是 APK 文件,则自动调用系统的安装程序,完全自动更新 App 任务。

注意点

  1. 前两步都比较简单,依赖和权限。如果需要用到弹出对话框的话,就需要增加一个SYSTEM_ALERT_WINDOW权限。

  2. 初始化。该库是在Application里面初始化的,所以和第一个不一样,我们需要在自己的Application里面复制那一段代码进去。一开始我很奇怪,为什么初始化方法之前有个”例如“呢?初始化的过程不是应该都是同一段代码吗?难道还可以自定义吗?后来才知道,这个库只是举了个json解析的例子作为初始化例子。如果用户的app使用的是别的解析方式,那么就按照他们的来就行,目的就是为了返回一个Version对象。这个对象包含了4个参数,分别是:versionCode,versionName,url和note。其实原理和上面第一个库差不多,都是对比versionCode。url就是apk的下载地址,note就是版本更新说明,显示在对话框上的信息。

  3. 接下来就可以引入检查新版本的API了,这个一般是放在MainActivity里面的onCreate()方法里,我是放在登录Activity里面的,总之根据需求来吧。我们只要设置一个json的地址就行,这个地址如果放到电脑的浏览器里应该是可以打开的,并且会显示那4个参数。然后如果你点击那个url的参数,弹出下载框的话,说明这些地址都是有效的。

  4. 我选择的是弹出对话框的形式,简单粗暴。如果想自己定义回调的事件的话,就可以选择callback那个设置,应该也是很方便的。广播那个我没有尝试,我想应该也没有多大的问题。

  5. 好像就搞定了。当检测到版本升级,会自动下载并更新了。

结果

总体来说这两个库原理差不多,只不过一个放在了外网的服务器上,另一个可以选择放在自己的服务器上。我感觉还是第二个更方便。。而且也没有下载次数限制。反正版本更新的重点就是versionCode。

你可能感兴趣的:(Android)