PS: Ionic 为什么要用Cordova插件?
先看下Ionic是什么?
Ionic(ionicframework)一款开源的Html5移动App开发框架,是以AngularJS为基础的移动端解决方案,Ionic以流行的跨平台移动app开发框架phoengap为蓝本,让开发者可以通过命令行工具快速生成android ios移动app应用。
phoengap又是什么?
PhoneGap是Apache Cordova最原始和最流行的分发,用基于HTML,CSS和JavaScript的,创建移动跨平台移动应用程序的快速开发平台。它使开发者能够利用iPhone,Android,Palm,Symbian,WP7,WP8,Bada和Blackberry智能手机的核心功能——包括地理定位,加速器,联系人,声音和振动。原本由Nitobi公司开发,在2011年10月4日,Adobe公司收购了这个Nitobe公司,后来Adobe把PhoneGap项目捐献给了Apache基金会。当2012年PhoneGap更新到1.4版本后,Apache又把名字更新成Cordova,有趣的是Cordova是PhoneGap团队附近一条街的名字。参考
Ionic/Angular和Cordova关系是?
可能会有人被问道:“Cordova比Ionic/Angular好吗?”,这就很尴尬了,根本是毫无意义的问题。它们在混合开发中扮演的是不同的角色–Ionic/Angular负责页面的实现,而Cordova负责将实现的页面包装成原生应用(Android:apk;iOS:ipa)。就像花生,最内层的花生仁是Angular,花生仁的表皮是Ionic,而最外层的花生壳则是Cordova。包装完成之后我们的页面才有可能调用设备的原生能力,最后才能上传到应用商店被用户使用。
关于Ionic使用Cordova插件:
Cordova插件的作用是提供一个桥梁供页面和原生通信,首先我们的页面不能直接调用设备能力,所以需要与能够调用设备能力的原生代码(Android:Java;iOS:OC)通信,此时就需要Cordova插件了。
Cordova插件能够再任何Cordova工程中使用,和使用什么前端框架(如Ionic)无关。
Ionic 2中封装了Ionic Native,方便了Cordova插件的使用,但在Ionic 2中仍然可以像Ionic 1中一样使用Cordova插件,Ionic Native不是必须的。
即使在Ionic 2中使用了Ionic Native,也首先需要手动添加插件,如:cordova plugin add cordova-plugin-pluginName。
了解这些概念之后,我们就可以愉快的创建一个cordova插件了,具体有这几个步骤:
安装插件管理脚手架:plugman
npm install -g plugman
创建插件:
plugman create --name 插件名称 --plugin_id 插件id --plugin_version 插件版本号 [--path ] [--variable NAME=VALUE]
参数说明:
pluginName: 插件名称,eg:toast
pluginID: 插件id, eg: org.my.toast
version: 版本号, eg: 0.0.1
variable NAME=VALUE: 扩展参数,如说明或者作者
例如:
plugman create --name helloPlugin --plugin_id helloPlugin --plugin_version 0.0.1
执行结果如图:
QQ20180729-151156@2x.png
为插件添加平台
添加android平台: plugman platform add --platform_name android
添加iOS平台:plugman platform add --platform_name ios
执行结果如图:
QQ20180729-152839@2x.png
在www文件夹下生成了helloPlugin.js,helloPlugin.js的作用是通过js暴露插件的功能给插件使用者,helloPlugin.js文件如下:
exports.coolMethod = function (arg0, success, error) { /** * Cordova.exec()方法说明 * function(winParam) {}:成功回调函数。假设您的 exec成功完成,此功能将随您传递给它的任何参数一起执行 * function(error) {}:错误回调函数。如果操作未成功完成,则此功能将执行可选的错误参数 * "service":在本机端呼叫的服务名称,与原生端的类名保持一致 * "action":在本机端调用的动作名称,对应原生类execute()的入参,原生代码通过对action进行判断,从而知道JS让原生端执行什么样的功能,也就是执行的方法名 * [ arguments ]:传到原生环境的参数数组 */ exec(success, error, 'helloPlugin', 'coolMethod', [arg0]); };
android目录下生成的helloPlugin.java文件:
package helloPlugin;import org.apache.cordova.CordovaPlugin;import org.apache.cordova.CallbackContext;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;/** * This class echoes a string called from JavaScript. */ //自定义插件需要继承CordovaPlugin类,并且覆盖execute方法。public class helloPlugin extends CordovaPlugin { @Override //参数action是用来判断执行哪个方法,args是json格式的参数,callbackContext响应返回结果。 public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if (action.equals("coolMethod")) { String message = args.getString(0); this.coolMethod(message, callbackContext); return true; } return false; } //私有方法--调用的功能方法 private void coolMethod(String message, CallbackContext callbackContext) { if (message != null && message.length() > 0) { //成功回调 callbackContext.success(message); } else { //失败回调 callbackContext.error("Expected one non-empty string argument."); } } }
插件配置文件:plugin.xml,关于plugin.xml的详细讲解请看这里
<?xml version='1.0' encoding='utf-8'?><plugin id="helloPlugin" version="0.0.1" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android"> <name>helloPlugin</name> <engines> <engine name="cordova" version=">=8.0.0" /> <engine name="cordova-android" version=">=7.1.0" /> <engine name="cordova-ios" version=">=4.5.4" /> </engines> <js-module name="helloPlugin" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="www/helloPlugin.js"> <clobbers target="helloPlugin" /> </js-module> <platform name="ios"> <config-file parent="/*" target="config.xml"> <feature name="helloPlugin"> <param name="ios-package" value="helloPlugin" /> </feature> <!-- 设置ALIpay 的scheme --> <config-file target="*-Info.plist" parent="CFBundleURLTypes"> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>ALI$APP_ID</string> </array> </dict> </array> </config-file> <preference name="APP_ID" value="$APP_ID" /> </config-file> <!-- 申请权限设置:比如相机权限 --> <config-file target="*-Info.plist" parent="NSCameraUsageDescription"> <string>我们的xxx功能想使用相机来为您提供更好的服务</string> </config-file> <!-- 插件源文件 --> <source-file class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="src/ios/TestPlugin.m" /> <!-- 插件依赖的iOS平台库 --> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="libz.dylib" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="libc++.dylib" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="libz.tbd" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="Security.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="VideoToolbox.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="AVFoundation.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="Contacts.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="AddressBook.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="AddressBookUI.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="CoreTelephony.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="CoreText.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="QuartzCore.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="CoreGraphics.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="CoreMotion.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="CFNetwork.framework" weak="true" /> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="SystemConfiguration.framework" weak="true" /> <!-- 插件的功能实现文件:比如把插件的某个方法执行是打开TestViewController文件 --> <header-file class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="src/ios/TestViewController.h"/> <source-file class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="src/ios/TestViewController.m"/> <!-- 插件依赖的第三方库,可以用pods管理,当插件被添加的时候,会自动帮iOS项目生成podfile文件,并自动install此处引用的框架, --> <framework class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="NIMKit" type="podspec" spec="~> 2.6.0" /> </platform> <platform name="android"> <config-file parent="/*" target="res/xml/config.xml"> <feature name="helloPlugin"> <param name="android-package" value="helloPlugin" /> </feature> </config-file> <config-file parent="/*" target="AndroidManifest.xml"> </config-file> <source-file class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="src/android/helloPlugin.java" target-dir="src/com/plugin/helloPlugin/helloPlugin" /> </platform></plugin>
我们还需要一个package.json文件
npm init
执行结果:
QQ20180729-162256@2x.png
{ "name": "helloplugin", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC"}
name等值可以自定义,也可以直接回车选择默认值。
ionic项目引用自定义插件
ionic cordova plugin add 你插件的存储路径
然后home.html文件中,添加btn click测试插件的方法有没有生效:
<ion-header> <ion-navbar> <ion-title>Home</ion-title> </ion-navbar></ion-header><ion-content padding> <h2>Welcome to Ionic!</h2> <p> This starter project comes with simple tabs-based layout for apps that are going to primarily use a Tabbed UI. </p> <p> Take a look at the <code>src/pages/</code> directory to add or change tabs, update any existing page or create new pages. </p> <button ion-button (click)="testPlugin()">测试自定义插件</button></ion-content>
home.ts:
import { Component } from '@angular/core';import { NavController } from 'ionic-angular';//定义cordova对象,注意,这个变量的定义,是个全局的引用,表示所有的插件对象都加载进来,我们的helloplugin插件也会被加载进来declare let cordova: any; @Component({ selector: 'page-home', templateUrl: 'home.html'})export class HomePage { constructor(public navCtrl: NavController) { } testPlugin(){ // alert('testPlugin'); //引用自定义插件方法,具体插件类的调用需要看被调用插件的配置文件plugin.xml中的clobbers节点 helloplugin.coolMethod("插件测试!",result=>alert(result),error=>alert(error)); } }
ionic项目真机、模拟器运行的命令简单列一下:
ionic cordova platform add ios/android //添加平台ionic cordova emulate ios/android –lc //模拟器运行ionic build ios/android //编译ionic cordova run ios/android –lc //真机运行
修改自定义插件
比如修改android平台下的插件功能:
1.修改helloplugin/src/android/helloplugin.java文件,新增一个求和方法:
package helloPlugin;import org.apache.cordova.CordovaPlugin;import org.apache.cordova.CallbackContext;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;/** * This class echoes a string called from JavaScript. */ //自定义插件需要继承CordovaPlugin类,并且覆盖execute方法。public class helloPlugin extends CordovaPlugin { @Override //参数action是用来判断执行哪个方法,args是json格式的参数,callbackContext响应返回结果。 public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if (action.equals("coolMethod")) { String message = args.getString(0); this.coolMethod(message, callbackContext); return true; }else if (action.equals("plus")) {//主方法中增加一段方法名称判断和调用的代码 int x = args.getInt(0); int y = args.getInt(1); this.plus(x, y, callbackContext); return true; } return false; } //私有方法--调用的功能方法 private void coolMethod(String message, CallbackContext callbackContext) { if (message != null && message.length() > 0) { //成功回调 callbackContext.success(message); } else { //失败回调 callbackContext.error("Expected one non-empty string argument."); } } //新增一个传入两个参数求和的方法 private void plus(int x, int y, CallbackContext callbackContext) { callbackContext.success(x + y); } }
2.修改helloplugin/www/helloplugin.js代码
// var exec = require('cordova/exec');// exports.coolMethod = function (arg0, success, error) {// /**// * Cordova.exec()方法说明// * function(winParam) {}:成功回调函数。假设您的 exec成功完成,此功能将随您传递给它的任何参数一起执行// * function(error) {}:错误回调函数。如果操作未成功完成,则此功能将执行可选的错误参数// * "service":在本机端呼叫的服务名称,与原生端的类名保持一致// * "action":在本机端调用的动作名称,对应原生类execute()的入参,原生代码通过对action进行判断,从而知道JS让原生端执行什么样的功能// * [ arguments ]:传到原生环境的参数数组// */// exec(success, error, 'helloPlugin', 'coolMethod', [arg0]);// };var exec = require('cordova/exec');var testAPI = {} testAPI.coolMethod = function(arg0, success, error) { exec(success, error, "helloPlugin", "coolMethod", [arg0]); };//求和方法testAPI.plus = function(arg0,arg1, success, error) { exec(success, error, "helloPlugin", "plus", [arg0,arg1]); };module.exports = testAPI;
3.修改自定义插件package.json和plugin.xml文件的版本号
4.自定义插件修改后必须先删除插件,然后再安装插件才可生效。
不知道自己的插件名字可以命令查看已安装的所有插件:
ionic cordova plugin list //列出所有已安装的插件
ionic cordova plugin remove helloPlugin //从ionic3项目中删除插件
ionic cordova plugin add 自定义插件路径 //安装插件到ionic3项目
以上4步就是插件的跟新步骤了~
到这里自定义插件及使用的方法就说完了,希望对您有所帮助~~~
插件配置文件详情请看:plugin.xml配置
参考文章
作者:星辰大海_王
链接:https://www.jianshu.com/p/c10593d41b8a
共同学习,写下你的评论
评论加载中...
作者其他优质文章