Cordova webapp实战开发:(5)如何写一个Andorid下自动更新的插件?

在 《Cordova webapp实战开发:(4)Android环境搭建》中我们搭建好了开发环境,也给大家布置了调用插件的预习作业,做得如何了呢?今天我们来学一下如何自己从头建立一个Andorid下的cordova插件。

本次练习你能学到的

  1. 学习如何实现自动更新功能
  2. 学习插件类的编写
  3. 学习插件的配置
  4. 学习插件的调用

主要内容

  • 打开APP后检查版本更新,如果有更新则弹出更新对话框

  • APP中【检查更新】显示当前版本号,并可以点击进行版本检查更新

如何实现自动更新功能

你可以自己写代码,也可以网上找代码抄一下,我之前的 敏捷个人APP 就是从网上下的一个代码片段放进我的项目中的。不过今天和大家说的不是如何编写自动更新代码,因为我们今天要做的是如何更快的用别人写好的东西来加速自己产品开发的进度和质量。

自动更新这个东西也不涉及到什么技术难度,一般第三方要是提供了也不会出什么质量问题,能够拿来就用岂不是很好呢?网上找了一下,发现 友盟提供自动更新

很好,那就直接用这个吧,Andorid和iOS都可以用。

如何集成到我们的产品中,看他们自己写的文档:自动更新android文档 ,我就不多说了,如果遇到问题,可以在咱们群里问问大家。

插件类的编写

原生Andorid中如果调用,就看上面说的他们自己写的文档。如果我们现在要在APP中【设置】中增加自动检查和显示当前版本,则需要我们开始学习如何编写cordova插件了。

这里我们会编写一个插件,两个方法,一个方法用来检测更新,另一个方法用来获得当前APP的版本号。

闲话不说了,直接来代码。

public class GCAppPlugin extends CordovaPlugin {

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if ("version".equals(action)) {
            version(callbackContext);
            return true;
        }
        else if ("checkUpdate".equals(action)) {
            final Context mContext = this.cordova.getActivity();
            UmengUpdateAgent.setUpdateAutoPopup(false);
            UmengUpdateAgent.setUpdateListener(new UmengUpdateListener() {
                @Override
                public void onUpdateReturned(int updateStatus, UpdateResponse updateInfo) {
                      switch (updateStatus) {
                        case UpdateStatus.Yes: // has update
                            UmengUpdateAgent.showUpdateDialog(mContext, updateInfo);
                            break;
                        case UpdateStatus.No: // has no update
                            Toast.makeText(mContext, "现在使用的已是最新版本了", Toast.LENGTH_SHORT).show();
                            break;
                        case UpdateStatus.NoneWifi: // none wifi
                            Toast.makeText(mContext, "没有wifi连接, 只在wifi下更新", Toast.LENGTH_SHORT).show();
                            break;
                        case UpdateStatus.Timeout: // time out
                            Toast.makeText(mContext, "超时", Toast.LENGTH_SHORT).show();
                            break;
                        }
                }
            });
            UmengUpdateAgent.forceUpdate(mContext);
            return true;
        }
}

private synchronized void version(CallbackContext callbackContext) {
  PackageInfo packInfo;
  try {
    packInfo = this.cordova.getActivity().getPackageManager().getPackageInfo(this.cordova.getActivity().getPackageName(),0);
    String version = packInfo.versionName +"("+packInfo.versionCode+")";
    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, version));
  } catch (NameNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }
}

Javascript如何得到插件调用后的返回结果?主要通过类似 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, version)); 代码返回PluginResult,失败和成功都可以触发Javascript执行对应的自定义函数

插件的配置

插件写完了,很多人遇到的下一个问题就是怎么配置才能在Javascript中调用呢?我们今天也不解析源码,为什么呢?因为我没看:)不过,我一定要给大家说清楚如何配置,否则就永远调用不了插件。

打开res/xml/config.xml文件,添加feature,必须匹配类名,因为源码中是通过这些去配对的。上面我们写了更新插件,现在就是要配置一下这个插件类到功能名称,我在配置文件中加入了下文粗体部分内容

<?xml version=‘1.0‘ encoding=‘utf-8‘?>
<widget id="com.glodon.gcapp" version="2.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>掌中广材</name>
    <description> 随时随地查找全国最完整最及时的信息价   </description>
    <author email="[email protected]" href="http://www.中国信息价.cn">  周金根    </author>
    <content src="html/scj/scj.html" />
    <access origin="*" />
    <access origin="tel:*" launch-external="yes"/>
    <access origin="geo:*" launch-external="yes"/>
    <access origin="mailto:*" launch-external="yes"/>
    <access origin="sms:*" launch-external="yes"/>
    <access origin="market:*" launch-external="yes"/>

    <preference name="SplashScreen" value="screen" />
    <preference name="SplashScreenDelay" value="30000" />
    <preference name="SplashMaintainAspectRatio" value="false" />
    <preference name="LoadingDialog" value="正在加载中..." />

    <feature name="Device">
        <param name="android-package" value="org.apache.cordova.device.Device" />
    </feature>
     <feature name="NetworkStatus">
        <param name="android-package" value="org.apache.cordova.networkinformation.NetworkManager" />
    </feature>
    <feature name="SplashScreen">
        <param name="android-package" value="org.apache.cordova.splashscreen.SplashScreen" />
    </feature>
    <feature name="Camera">
        <param name="android-package" value="org.apache.cordova.camera.CameraLauncher" />
    </feature>
    <feature name="BarcodeScanner">
        <param name="android-package" value="com.phonegap.plugins.barcodescanner.BarcodeScanner" />
    </feature>
    <feature name="Gcapp">
        <param name="android-package" value="com.gldjc.guangcaiclient.GCAppPlugin" />
    </feature>
</widget>

代码贴完了,我还是要再多说一下,

  • com.gldjc.guangcaiclient.GCAppPlugin  是插件类的全面
  • Gcapp是 feature 名称,下面大家就知道在哪里会用到了

以上文件就是告诉cordova,我们新增了一个Gcapp功能,这个功能会调用我们的原生插件Java对象,接下来就是Javascript如何能调用到这个类了,最重要的就是这个Gcapp功能名称。

我们接着就要写Javascript代码来调用这个功能了,如何写呢?继续往下看,我在assets/www/plugins/下新增目录并建立了文件gcapp.js,完整路径是 assets/www/plugins/com.gldjc.guangcaiclient/www/gcapp.js,代码如下:

cordova.define(‘com.gldjc.guangcaiclient.gcapp‘, function(require, exports, module) {
        var exec = require("cordova/exec");

        function Gcapp() {};

        Gcapp.prototype.version = function (getversion) {
            exec(getversion, null, ‘Gcapp‘, ‘version‘, []);
        };   

      Gcapp.prototype.checkUpdate = function () {
            exec(null, null, ‘Gcapp‘, ‘checkUpdate‘, []);
        };   

        var gcapp = new Gcapp();
        module.exports = gcapp;
});

exec是cordova.js中内部的函数,当插件返回 PluginResult.Status.OK 时会执行exec的成功回调函数,如果插件返回的是错误,则会执行exec的错误回调函数。这里我们解释一下

 exec(null, null, ‘Gcapp‘, ‘checkUpdate‘, []);

其中Gcapp就是我们在上一步骤加的feature名称,大小写匹配着写,通过这个名称,cordova才能找到调用那个java插件类,然后通过checkUpdate知道调用这个插件类的哪个方法,后面[]中则是参数。因为我这个插件不需要参数,所以为空。

Javascript插件类也配对成功了,那如何调用呢?你可以直接在html中包括这个js,不过我们一般会再配置一个js,那就是assets/www/cordova_plugins.js,这样就不用对每个插件类都去写一遍了,cordova会遍历你的配置去加载它们。

cordova.define(‘cordova/plugin_list‘, function(require, exports, module) {
module.exports = [
    {
        "file": "plugins/org.apache.cordova.device/www/device.js",
        "id": "org.apache.cordova.device.device",
        "clobbers": [
            "device"
        ]
    },
    {
        "file": "plugins/org.apache.cordova.networkinformation/www/network.js",
        "id": "org.apache.cordova.networkinformation.network",
        "clobbers": [
            "navigator.connection",
            "navigator.network.connection"
        ]
    },
     {
        "file": "plugins/org.apache.cordova.networkinformation/www/Connection.js",
        "id": "org.apache.cordova.networkinformation.Connection",
        "clobbers": [
            "Connection"
        ]
    },
     {
        "file": "plugins/org.apache.cordova.splashscreen/www/splashscreen.js",
        "id": "org.apache.cordova.splashscreen",
        "clobbers": [
            "navigator.splashscreen"
        ]
    },
        {
        "file" : "plugins/org.apache.cordova.camera/www/CameraConstants.js",
        "id" : "org.apache.cordova.camera.Camera",
        "clobbers" : [ "Camera" ]
    },
    {
        "file" : "plugins/org.apache.cordova.camera/www/CameraPopoverOptions.js",
        "id" : "org.apache.cordova.camera.CameraPopoverOptions",
        "clobbers" : [ "CameraPopoverOptions" ]
    },
    {
        "file" : "plugins/org.apache.cordova.camera/www/Camera.js",
        "id" : "org.apache.cordova.camera.camera",
        "clobbers" : [ "navigator.camera" ]
    },
    {
        "file" : "plugins/org.apache.cordova.camera/www/CameraPopoverHandle.js",
        "id" : "org.apache.cordova.camera.CameraPopoverHandle",
        "clobbers" : [ "CameraPopoverHandle" ]
    },
    {
        "file" : "plugins/com.phonegap.plugins.barcodescanner/www/barcodescanner.js",
        "id" : "com.phonegap.plugins.barcodescanner.barcodescanner",
        "clobbers" : [ "barcodescanner" ]
    },
    {
        "file": "plugins/com.gldjc.guangcaiclient/www/gcapp.js",
        "id": "com.gldjc.guangcaiclient.gcapp",
        "clobbers": [
            "gcapp"
        ]
    }
];
module.exports.metadata =
// TOP OF METADATA
{
    "org.apache.cordova.device": "0.2.13"
}
// BOTTOM OF METADATA
});

file表示我们去哪里找脚本插件定义js,id是之前我们在gcapp.js中开头cordova.define中写的标识,cordova通过这个标志去找到我们的Javascript插件定义,而clobbers则是我们在前端通过什么对象名来调用这个插件。这里我写的是gcapp,则后面调用则只需要写成gcapp.checkUpdate 即可

插件的调用

万事俱备,只欠东风,你们可以开始看到结果了,如果从头到这里一步成功,那应该还是蛮兴奋的事情吧。

具体前端页面如何设计我就不说了,我的页面效果就如本文最前面的图片,在js中我是这些调用version的,至于checkUpdate就是一样了,在按钮的click事件中调用 gcapp.checkUpdate(); 即可

$(document).on("PG_pageinit", function(event) {
    gcapp.version(function(version){
            $("#version").html(version);
    });
});

如果你对以上内容感兴趣,那就继续关注吧,依旧如此,喜欢这个系列的就点赞,点的越多,更新就会越快,超过20个赞或20个回复后,开始写下一篇,欢迎你写下你想要我写的内容

PhoneGap App开发 348192525   

时间: 2024-10-09 19:34:42

Cordova webapp实战开发:(5)如何写一个Andorid下自动更新的插件?的相关文章

Cordova webapp实战开发:(6)如何写一个iOS下自动更新的插件?

上一篇我们学习了如何写一个Andorid下自动更新的插件,我想还有一部分看本系列blog的开发人员希望学习在iOS下如何做插件的吧,那么今天你就可以来看看这篇文字了. 本次练习你能学到的 学习如何获取iOS当前版本号 学习iOS下插件类的编写 学习iOS下插件的配置 学习iOS下插件的调用 主要内容 APP中[检查更新]显示当前版本号 插件类的编写 在上一篇介绍Andorid插件时我们贴出了很多源码,这里也直接贴出代码,首先是iOS下插件的代码. 我们在Plugins下新建两个文件,一个头文件

Cordova webapp实战开发:(4)Android环境搭建

在<Cordova webapp实战开发:(3)后面可能会学到的东西>中我们说了一下后续大致包括的内容,今天我们继续.上周我在掌中广材集成了友盟的社交分享,今天想集成iOS应该很顺利的,但是只要一加入libSocialQQ.a就错.我对iOS也不太熟,没找到原因,头晕了,写一篇博客权当休息一下.今天我们就来搭建一下Android环境,并编写一个hello world吧.准备好了吗?Web app开发旅程即将正式开始了....... JAVA环境 安装JAVA JDK 打开我的电脑--属性--高

Cordova webapp实战开发:(3)后面可能会学到的东西

在<Cordova webapp实战开发:(2)认识一下Cordova>中我们了解了Cordova和Phonegap的关系,并简要介绍了一下它的架构,以及多平台性,并给大家留了一些作业.我看到群里也有人已经完成,真是认真学习的人!我相信这样的人一定会进步比较快,认真而踏实,即使没有其他人聪明,但是一定会比他们更优秀. 周五的时候大家就给我上一篇点了40多个赞,并有20条回复,我又要开始写下一篇了.本来决定下周一开始写,不过看群里大家聊得蛮积极的,被这种学习热情所打动,我就把这个系列写的勤快一些

Cordova webapp实战开发:(7)如何通过简单的方法做到,不重新发布APP来修复bug、增加功能、或者躲开苹果的一些严格审核?

到<Cordova webapp实战开发:(6)如何写一个iOS下获取APP版本号的插件?>为止,我们已经大体学会了如何使用Cordova了,那些都是使用Cordova的开发者必备的技能.今天我们要说一下开发者应该具备的一些额外经验,这些经验简单有效,如果希望要更系统更好的方法,那就持续关注本系列文章吧,与敏捷个人一起成长. 本次练习你能学到的 学习如何动态不发布APP来修复bug 学习如何动态增加功能 学习如何躲开苹果的一些严格审核 如何动态不发布APP来修复bug 做过网站的都知道,修复b

Cordova webapp实战开发:(1)为什么选择 Cordova webapp?

很长时间没有专注写代码了,即使写点代码也主要是写写敏捷个人app,这个App主体内容是我用了一周的时间,使用PhoneGap+JQueryMobile搭建的,之所以会比较快的完成,是因为11年我在做建筑云运维项目时使用过. 时隔几年,我在 <掌中广材产品经理日志(1)- 妈的,不想再呆在广联达了>写到,今年初我到了工信部负责一款之前已经做过一年多的APP,这款产品叫做掌中广材,大家可以各大市场下载到. 本系列初衷 现在Web App越来越流行,但是很多人却不知如何开始,自己学习使用Cordov

Cordova webapp实战开发:(2)认识一下Cordova

如何封装一个浏览器成webapp? 在群里,有个朋友问了一个问题“如何封装一个浏览器成webapp?” 每个手机就像电脑一样,都带着自己的操作系统.如果你愿意,你可以从头写一个浏览器,把浏览地址隐藏了,这就像你的一个app了,对吧.当然,我们自己写浏览器,这也太难了,所以我们肯定不是这么做的.其实,我们只是基于各种手机上Web浏览器内核去做手脚,而Js是Web开发的最佳语言,至于如何封装成一个Web app?说实话,我也没有真正去探究过是如何去做的,因为我对Andorid和iOS原生开发也不熟悉

从零开始写一个arm下的裸板程序

从零开始写一个arm下的裸板程序.我们整个程序是基于uboot运行的. 所有我们可以借助uboot中的printf来输出,默认开发版的标准输出是串口. 电脑的默认标准输出的屏幕. 1.需要创建的文件由include文件夹,用来存放头文件. 2.创建一个hw.h头文件. 3.编写一个common.h,它定义了借用uboot的printf的宏.和NULL这个宏的定义. 4.hw.c 硬件相关的文件. 5.main.c c文件. 6.start.s 汇编文件. 7.ld.lds 链接脚本, 8.Mak

我想写一个Linux下的C++程序库--记我的C++库设计历程:设计一个TCP服务程序

我想写一个Linux下的C++程序库,实现一些常用的功能. 我首先想到的就是实现一个TCP监听程序.该程序应该具有哪些功能呢? 1: 启动/停止监听 2: 有客户端连接时,通知调用者 3: 与客户端断开时,通知调用者 4: 有消息到达时,通知调用者 5: 尽量避免程序退出时有没有close的socket. 该程序的大体接口及结构主要用一个类表示,内容如下: #pragma once #include <functional> namespace Hi { /* * @ brief TCP监听会

向军laravel和vuejs webAPP实战开发

1 向军laravel开发宝典-git库与开发环境及工具软件介绍.mp42 向军laravel开发宝典-安装laravel框架.mp4 3 向军老师laravel开发宝典-安装laravel-ide-helper增强代码提示.mp4 4 向军老师laravel开发宝典-配置数据库与使用migrations创建表.mp4 5 向军老师laravel开发宝典-解决mysql5.7以下laravel不能执行数据迁移的问题.mp4 6 向军老师laravel开发宝典-合理的路由布局与分组路由.mp4 7