为ionic2项目创建自定义cordova插件

Sre*_*ari 4 javascript plugins android cordova ionic2

我们中的许多人都会经历类似的问题,但即使经过以下大多数相关链接引用link1参考link2,我也无法解决.

问题:

创建一个自定义插件(Cordova)以便在ionic2项目中使用它.

期望:此插件将能够与IOS和Android的本机功能进行交互.确切地说,我正在尝试使用cordova访问Ionic项目的本机SDK(Aruba内部定位SDK)的功能.

步骤1根据参考链接1初始创建插件

第2步创建Ionic 2项目(使用基本步骤创建)

步骤3插件中的JavaScript文件无法在Ionic2中引用和访问.

谷歌搜索后,我发现了这个讨论,由于以下原因,它被告知在插件中创建界面.

从'../../../plugins/xxx/*.js'导入{myPluginName}

因为插件不是离子本机包的一部分而无法工作.

如果你有自定义插件,你可以做一些事情.

1)制作PR以将其添加到离子原生物中

2)使用原始插件API.您可以使用原始插件API,而不必将其作为Ionic Native的一部分.该插件位于窗口对象上,因此您可以正常定位api

window.plugin.myPlugin.myMethod()

根据GITHUB Example项目,这种方式应该实现接口

interface CordovaPlugins {
  ZPLPrinter: ZPLPrinter;
}

interface ZPLPrinter {

  print(
    ipaddress: string,
    bclabels: any,
    printSuccess: (ip: string, labels: string[]) => void,
    printError: (message: string) => void): void;

}
Run Code Online (Sandbox Code Playgroud)

现在我在我的插件中创建了一个类似的界面,插件的www文件夹中有以下内容

interface CordovaPlugins {
  Communicator: Communicator;
}

interface Communicator {

  getInfo(successCallback: any, errorCallback: any);

}
Run Code Online (Sandbox Code Playgroud)

理想情况下,此接口将在JS文件中定位此方法

Device.prototype.getInfo = function(successCallback, errorCallback) {
    console.log("device.js: getInfo function called");
    argscheck.checkArgs('fF', 'Device.getInfo', arguments);
    exec(successCallback, errorCallback, "Device", "getDeviceInfo", []);
};
Run Code Online (Sandbox Code Playgroud)

现在我卡住了,因为我的Ionic项目本身并没有打字文件夹.

在示例Github项目中,cordova包使用typings文件夹引用.在项目打字稿文件是指Cordova使用index.t.js

用来引用的导入应该是这样的

declare var cordova: Cordova;
Run Code Online (Sandbox Code Playgroud)

释疑:

  1. 我是在这个过程的正确方向
  2. 这是创建Cordova插件和在离子中使用的方法吗?
  3. 为什么我无法typings在Ionic2中获取文件夹

编辑1:

刚刚添加插件后,甚至没有参考Ionic项目,我尝试在Android设备上运行.但它给了我以下错误.

主要错误是这个

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ionicframework.cutepuppypics234138/com.ionicframework.cutepuppypics234138.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void org.apache.cordova.CordovaPlugin.privateInitialize(java.lang.String, org.apache.cordova.CordovaInterface, org.apache.cordova.CordovaWebView, org.apache.cordova.CordovaPreferences)' on a null object reference
Run Code Online (Sandbox Code Playgroud)

为什么会导致此错误?详细日志如下

12-08 16:10:49.079 20555-20555/? E/ApkAssets: Error while loading asset assets/natives_blob_64.bin: java.io.FileNotFoundException: assets/natives_blob_64.bin
12-08 16:10:49.079 20555-20555/? E/ApkAssets: Error while loading asset assets/snapshot_blob_64.bin: java.io.FileNotFoundException: assets/snapshot_blob_64.bin
12-08 16:10:49.682 20555-20555/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ionicframework.cutepuppypics234138, PID: 20555
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ionicframework.cutepuppypics234138/com.ionicframework.cutepuppypics234138.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void org.apache.cordova.CordovaPlugin.privateInitialize(java.lang.String, org.apache.cordova.CordovaInterface, org.apache.cordova.CordovaWebView, org.apache.cordova.CordovaPreferences)' on a null object reference
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
   at android.app.ActivityThread.access$800(ActivityThread.java:155)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:135)
   at android.app.ActivityThread.main(ActivityThread.java:5343)
   at java.lang.reflect.Method.invoke(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void org.apache.cordova.CordovaPlugin.privateInitialize(java.lang.String, org.apache.cordova.CordovaInterface, org.apache.cordova.CordovaWebView, org.apache.cordova.CordovaPreferences)' on a null object reference
   at org.apache.cordova.PluginManager.getPlugin(PluginManager.java:171)
   at org.apache.cordova.PluginManager.startupPlugins(PluginManager.java:97)
   at org.apache.cordova.PluginManager.init(PluginManager.java:86)
   at org.apache.cordova.CordovaWebViewImpl.init(CordovaWebViewImpl.java:115)
   at org.apache.cordova.CordovaActivity.init(CordovaActivity.java:149)
   at org.apache.cordova.CordovaActivity.loadUrl(CordovaActivity.java:224)
   at com.ionicframework.cutepuppypics234138.MainActivity.onCreate(MainActivity.java:39)
   at android.app.Activity.performCreate(Activity.java:6010)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413) 
   at android.app.ActivityThread.access$800(ActivityThread.java:155) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:135) 
   at android.app.ActivityThread.main(ActivityThread.java:5343) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at java.lang.reflect.Method.invoke(Method.java:372) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700) 
12-08 16:10:49.879 20656-20656/? E/SubDex: SubDex Config : .dex 2
12-08 16:10:50.285 20656-20656/? E/project: extsdcard==/storage/emulated/0/Android/data/com.cleanmaster.mguard/files
12-08 16:10:50.303 20656-20656/? E/project: extsdcard==/storage/emulated/0/Android/data/com.cleanmaster.mguard/files
Run Code Online (Sandbox Code Playgroud)

Sre*_*ari 10

经过多次试验和错误后,我找到了解决方案.

我正在记下以下细节,以便将来参考尝试类似内容的任何人!

代码问题如下(我的插件名称是Inject)

  • Inject\www\Inject.js 没有安装插件的基本功能
  • 提到的任何方法名称Inject.js应该相同,直到Inject\src\Inject.java方法中有选项execute来根据收到的标记引用不同的方法名称

脚步:

  1. 使用plugman创建插件参考链接的骨架
  2. 而不是使用类似名称cordova-plugin-am-i-late,使用cordova.plugin.Inject .我使用-符号面对编译/运行时问题
  3. 添加目标平台 plugman platform add --platform_name android
  4. 验证plugin.xml比较相同的引用
  5. plugin.xml如果需要,请包含权限
  6. 现在验证Inject.js缺少必要的方法调用.目前它只有以下代码.

var exec = require('cordova/exec');
exports.coolMethod = function(arg0, success, error) {
exec(success, error, "Inject", "coolMethod", [arg0]);
};
Run Code Online (Sandbox Code Playgroud)
  1. 但是我们还需要在下面包含它以使其安装和工作

function Inject(){
}
Inject.install = function () {
  if (!window.plugins) {
    window.plugins = {};
  }

  window.plugins.Inject = new Inject();
  return window.plugins.Inject;
};

cordova.addConstructor(Inject.install);
Run Code Online (Sandbox Code Playgroud)
  1. 例如,我的目标是显示Toast消息,以下是我的完整Inject.js文件

function Inject(){
}

Inject.prototype.coolMethod = function (options, successCallback, errorCallback) {
  cordova.exec(successCallback, errorCallback, "Inject", "coolMethod", []);
};

Inject.install = function () {
  if (!window.plugins) {
    window.plugins = {};
  }

  window.plugins.Inject = new Inject();
  return window.plugins.Inject;
};

cordova.addConstructor(Inject.install);
Run Code Online (Sandbox Code Playgroud)
  1. 现在让我们来实现 Inject.java

public class Inject extends CordovaPlugin {

private static final int GRAVITY_CENTER = Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL;
private static final String TAG = "InjectCordovaPlugin";
String messageReceived;

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        Log.v(TAG, "execute , action =" + action);
        if (action.equals("coolMethod")) {
            String message = args.getString(0);
            Log.v(TAG, "coolMethod called with message =" + message);
            this.coolMethod(message, callbackContext);
            return true;
        }

        return false;
    }
    private void coolMethod(String message, CallbackContext callbackContext) {
    Log.v(TAG, "Inject's coolMethod called ,message="+message);
    messageReceived = message;
        if (message != null && message.length() > 0) {
            cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {

            final android.widget.Toast toast = android.widget.Toast.makeText(
              cordova.getActivity().getWindow().getContext(),
              messageReceived,
              android.widget.Toast.LENGTH_LONG 
                );
                toast.setGravity(GRAVITY_CENTER, 0, 0);
                toast.show();
            }
            });
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 为了说清楚,我正在推出我的决赛 plugin.xml

<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova.plugin.Inject" 
    version="1" 
    xmlns="http://apache.org/cordova/ns/plugins/1.0" 
    xmlns:android="http://schemas.android.com/apk/res/android">
<name>Inject</name>
<js-module name="Inject" src="www/Inject.js">
    <clobbers target="window.plugins.Inject"/>
</js-module>
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="Inject">
<param name="android-package" 
        value="cordova.plugin.Inject.Inject" />
        </feature>
</config-file>
<config-file parent="/*" target="AndroidManifest.xml">
</config-file>
<source-file src="src/android/Inject.java" 
target-dir="src/cordova.plugin.Inject/Inject" />
</platform>
</plugin>
Run Code Online (Sandbox Code Playgroud)
  1. 现在创建一个示例Ionic2项目并添加Android/IOS平台
  2. 使用cordova plugin add命令添加创建的插件
  3. 在Nodejs命令提示符中导航到ionic项目并给出此命令(请参阅插件文件夹库后add)cordova plugin add D:\PluginTrial\Inject
  4. 添加的插件应填充在Ionic2Project\plugins文件夹下
  5. 使用windowobject 调用此函数.以下是我的home.ts

import { Component } from '@angular/core';

import { NavController, Platform } from 'ionic-angular';

declare var window: any;
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController, private platform: Platform) {

  }
    showToast(message, position) {
        this.platform.ready().then(() => {
            window.plugins.Inject.coolMethod(message, "short", position);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 现在在home.html文件中引用此showToast方法

<button ion-button (click)="showToast('Yo Man! Its working ', 'center')">Default</button>
Run Code Online (Sandbox Code Playgroud)
  1. 而已.您应该能够成功测试插件!快乐的编码

参考: 参考文献1,参考文献2,参考文献3