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

news/2024/12/22 14:50:55/

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

本次练习你能学到的

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

主要内容

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

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

如何实现自动更新功能

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

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

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

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

插件类的编写

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

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

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

public class GCAppPlugin extends CordovaPlugin {@Overridepublic 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() {@Overridepublic void onUpdateReturned(int updateStatus, UpdateResponse updateInfo) {switch (updateStatus) {case UpdateStatus.Yes: // has updateUmengUpdateAgent.showUpdateDialog(mContext, updateInfo);break;case UpdateStatus.No: // has no updateToast.makeText(mContext, "现在使用的已是最新版本了", Toast.LENGTH_SHORT).show();break;case UpdateStatus.NoneWifi: // none wifiToast.makeText(mContext, "没有wifi连接, 只在wifi下更新", Toast.LENGTH_SHORT).show();break;case UpdateStatus.Timeout: // time outToast.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 blocke.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="22626496@qq.com" 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);});
});


http://www.ppmy.cn/news/69871.html

相关文章

智能的本质人工智能与机器人领域的64个大问题阅读笔记(三)

目录 机器智能提高到人类的水平或者人类智能下降到机器的水平&#xff0c;都可以到达图灵点。 或许图灵测试是一个自我实现的预言&#xff1a;我们&#xff08;声称&#xff09;在打造“聪明”机器的同时&#xff0c;我们也在把人变笨。 不长脑的机器和不思考的人没什么两样&…

Kubernetes架构与组件详解

Kubernetes架构与组件详解 一、Kubernetes 简介1 什么是 Kubernetes2 Kubernetes 的优势3 Kubernetes 的应用场景 二、Kubernetes 架构1 Kubernetes 架构概述2 Kubernetes 架构组件介绍2.1 控制面板组件2.2 API Server2.3 etcd2.4 kubelet2.5 kube-proxy2.6 CNI 插件2.7 容器运…

API常用类

Java API概述 API(Application Programming Interface) 应用程序编程接口 是对Java预先定义的类或接口功能和函数功能的说明文档,目的是提供给开发人员进行使用帮助说明 基本数据类型封装类 基本数据类型包装类byte ByteshortShortcharCharacterint Integerl…

在外Windows公网远程连接MongoDB数据库

文章目录 前言1. 安装数据库2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射2.3 测试随机公网地址远程连接 3. 配置固定TCP端口地址3.1 保留一个固定的公网TCP端口地址3.2 配置固定公网TCP端口地址3.3 测试固定地址公网远程访问 转载自远程内网穿透的文章&#xff1a;公网远…

OPPO关停哲库业务,工程师造芯何去何从?

5月12日&#xff08;上周五&#xff09;&#xff0c;新浪科技从OPPO处了解到&#xff0c;OPPO将终止ZEKU业务。3000多人团队突然原地解散&#xff0c;网上唏嘘声一片&#xff01; ZEKU最初成立于2019年&#xff0c;是OPPO的全资子公司&#xff0c;欧加集团百分之百注资成立。总…

Elasticsearch:结合两全其美:Elasticsearch 与 BM25 和 HNSW 的混合搜索

就搜索算法而言&#xff0c;没有万能的解决方案。 不同的算法在不同的场景下效果更好&#xff0c;有时需要算法的组合才能达到最好的效果。 在 Elasticsearch 中&#xff0c;一种流行的组合搜索算法的方法是使用混合搜索&#xff0c;将用于文本搜索的 BM25 算法与用于最近邻搜索…

分布式消息队列RocketMQ概念详解

目录 1.MQ概述 1.1 RocketMQ简介 1.2 MQ用途 1.3 常见MQ产品 2.RocketMQ 基本概念 2.1 消息 2.2 主题 2.3 标签 2.4 队列 2.5 Producer 2.6 Consumer 2.7 NameServer 2.8 Broker 2.9 RocketMQ 工作流程 1.MQ概述 1.1 RocketMQ简介 RocketMQ 是阿里开源的分布式消…

实验10 人工神经网络(1)

1. 实验目的 ①理解并掌握误差反向传播算法&#xff1b; ②能够使用单层和多层神经网络&#xff0c;完成多分类任务&#xff1b; ③了解常用的激活函数。 2. 实验内容 ①设计单层和多层神经网络结构&#xff0c;并使用TensorFlow建立模型&#xff0c;完成多分类任务&#xf…