在 《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 {

    @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="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);
});
});

PhoneGap App开发 477842664  

随机推荐

  1. redis五种数据类型的使用(zz)

    redis五种数据类型的使用 redis五种数据类型的使用 (摘自:http://tech.it168.com/a2011/0818/1234/000001234478_all.shtml ) 1.S ...

  2. 【bzoj2809】[Apio2012]dispatching 左偏树

    2016-05-31  15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...

  3. Spotlight实时监控Windows Server 2008

    Windows Server 2008作为服务器平台已逐渐被推广和应用,丰富的功能和良好的稳定性为其赢得了不错的口碑.但是和Windows Server 2003相比,其系统的自我监控功能并没有多大的 ...

  4. IIS6的SSL配置,如何配置SSL到登陆页,如何将SSL证书设置成受信任的证书

    一. 申请证书1. 到受信任的机构申请 略 2. 到自建的证书服务器申请 a. 安装证书服务 通过控制面板中的“添加/删除程序”,选择“添加/删除Windows组件”.在Windows组件向导中找到“ ...

  5. MyEclipse下查看Java API帮助文档

    每次重装JDK或者升级JDK时,都会忘了如何使MyEclipse关联帮助文档.然后,再花十几分钟重新google搜索,麻烦! 首先下载Javadoc api帮助文档,google搜一下就行了. MyE ...

  6. Linux磁盘管理:LVM逻辑卷的创建及使用

    一.创建LVM逻辑卷 事先添加了三块虚拟物理磁盘/dev/sdb 1G, /dev/sdc 2G, /dev/sdd 3G 使用fdisk –l命令查看: [root@localhost ~]# fd ...

  7. c/c++ 有向无环图 directed acycline graph

    c/c++ 有向无环图 directed acycline graph 概念: 图中点与点之间的线是有方向的,图中不存在环.用邻接表的方式,实现的图. 名词: 顶点的入度:到这个顶点的线的数量. 顶点 ...

  8. HDU 1796 How many integers can you find 【容斥】

    <题目链接> 题目大意: 给你m个数,其中可能含有0,问有多少小于n的正数能整除这个m个数中的某一个. 解题分析: 容斥水题,直接对这m个数(除0以外)及其组合的倍数在[1,n)中的个数即 ...

  9. HTML编码规范 - (WEB前端命名规范)

    HTML编码规范 (一)命名规则: 头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体布局宽度:wr ...

  10. Android美丽的对话框项目sweet-alert-dialog

    美丽的对话框 sweet-alert-dialog 项目地址: https://github.com/pedant/sweet-alert-dialog android原生的dialog太生硬了,之前 ...