现在制作APP都流行混合开发,Ionic是个不错的选择,但是很多原生的功能,混合开发是无法实现的,这时候就要根据功能来制作Cordova插件来实现,下面就记录第一次制作Cordova插件的步骤和遇到的问题及解决方法。
首先cmd命令行创建自定义插件TestPlugin,格式:
plugman create --name <pluginName> --plugin_id <pluginID> --plugin_version
plugman create --name TestPlugin --plugin_id com.plugin.testPlugin --plugin_version 1.0.0
创建好的文件结构如下:
src文件夹下存放各平台原生文件,首先要添加想要的平台,这里添加android平台,先cd到插件根目录:
cd TestPlugin
cordova platform add android
执行完上面的命令之后,src文件下多了android/TestPlugin.java文件,我们就可以在这个文件中编写想要实现的功能。
ok,现在一个Cordova插件建好了,就差往里面添加先要实现的功能,刚好现在公司要集成讯飞语音的功能,索性将android原生开发集成的讯飞语音移植到插件中试试。
由于没有针对cordova插件的编辑器,直接用其他编辑器修改cordova插件的文件内容比较麻烦,而且容易有纰漏,在向cordova插件中添加功能之前,最好先写一个android项目将功能实现,再将其移植到cordova即可,具体参见大神的文章:开发自己的cordova插件
开发之前本人已把讯飞语音封装好并且打包成aar文件,见:Android初学—-自己封装集成讯飞语音和人脸识别,可直接使用。接下来就是在TestPlugin.java中编写语音合成。
写好的TestPlugin.java文件内容如下:
package com.face.plugintest;
import android.app.Activity;
import com.face.speech.Speech;
import com.face.speech.XunfeiSpeech;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
/**
* Created by AA on 2018/1/18.
*/
public class TestPlugin extends CordovaPlugin {
private Activity activity;
private XunfeiSpeech speech;//封装的讯飞语音合成对象
private String appId = "********";//讯飞语音APPID,可到讯飞开发平台上获取
/**
*
* @param action 用来判断要执行的方法
* @param args 参数组
* @param callbackContext 回调
* @return
* @throws JSONException
*/
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equalsIgnoreCase("speak")){//执行语音合成方法
speaking("说话的内容是:"+args.get(0));
return true;
}
return false;
}
/**
* 该方法会在调用execute()方法之前调用,此时用来初始化activity和speech
* @param cordova
* @param webView
*/
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {//
super.initialize(cordova, webView);
this.activity = cordova.getActivity();
speech = new XunfeiSpeech(this.activity,appId);
}
/**
* 语音合成方法
* @param content 合成内容
*/
public void speaking (String content){
if (this.activity==null){
this.activity = cordova.getActivity();
}
if (speech==null){
speech = new XunfeiSpeech(this.activity,appId);
}
speech.startSpeaking(content, new Speech.SpeakResultCallback() {
@Override
public void onCompleted(String s) {
}
});
}
}
然后修改www文文件夹下的TestPlugin.js文件,将插件方法暴露给Ionic项目中使用:
var exec = require('cordova/exec');
var myAPI = {}
myAPI.speak = function(arg0,arg1, success, error) {
exec(success, error, "TestPlugin", "speak", [arg0,arg1]);
};
module.exports = myAPI;
ok,到这一步比较头疼的就是如何把aar弄到插件里边去,网上找了很多文章,改了很久才弄好,首先,将讯飞语音识别的speech.aar复制到android文件夹下(也可以自己建一个文件夹来存放,最好在android文件夹下),然后修改plugin.xml文件:
<plugin xmlns:android="http://schemas.android.com/apk/res/android" id="com.plugin.test" version="0.0.1"
xmlns="http://apache.org/cordova/ns/plugins/1.0">
<name>TestPluginname>
<js-module name="TestPlugin" src="www/TestPlugin.js">
<clobbers target="cordova.plugins.TestPlugin" />
js-module>
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="TestPlugin">
<param name="android-package" value="com.plugin.test.TestPlugin" />
feature>
config-file>
<config-file parent="/*" target="AndroidManifest.xml">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
config-file>
<source-file src="src/android/TestPlugin.java"
target-dir="src/com/plugin/test/TestPlugin" />
<framework src="src/android/build.gradle" custom="true" type="gradleReference"/>
<resource-file src="src/android/speech.aar" target="libs/speech.aar"/>
platform>
plugin>
下面就是添加plugin.xml文件中提到的build.gradle文件:
def DEFAULT_MIN_SDK_VERSION = 15
def minSdk = Math.max(DEFAULT_MIN_SDK_VERSION, cdvHelpers.getConfigPreference('android-minSdkVersion',0) as Integer);
if (cdvMinSdkVersion == null || Integer.parseInt('' + cdvMinSdkVersion) < minSdk ) {
ext.cdvMinSdkVersion = minSdk;
}
//指定资源库libs
repositories{
jcenter()
flatDir{
dirs 'libs'
}
}
dependencies {
compile 'com.android.support:support-v4:+'
//关键就是这句话,添加speech依赖,
compile(name:'speech', ext:'aar')
}
android {
packagingOptions {
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
}
}
到这里,cordova插件开发完成了???
并没有,我可是改了N多变啊,老铁,因为打包生成的aar文件总是和ionic项目中的android配置文件有冲突,就像这样:
这里的错误是ionic项目中,platforms->android平台下的AndroidManifest.xml文件和aar中的AndroidManifest.xml文件冲突:
两个文件中的icon重复,系统编译就不知道要选择哪一个ic_launcher,这里建议吧application中的属性都删掉即可,若aar文件中的value文件也存在错误,如下:
这里的错误是解析主题和颜色出错,无法找到“Theme.AppCompat.Light.DarkActionBar”,将其删除即可。或者根据错误内容增加没有的文件或是删除多余的文件。
最后在项目中使用插件。
先添加插件,命令行cd到Ionic项目根目录,执行:
ionic cordova plugin add 插件路径
添加完开始调用插件:
完成!