Cordova 插件开发手札(一)- 腾云互动直播云

参考文献:

如何在 MainActivity 添加组件 http://blog.csdn.net/offbye/article/details/49683369 在插件内引入 aar 库http://aarphonegapplugin.blogspot.hk/2015/09/aar-file-with-phonegapcordova-plugin.html

题记

由于项目需要开发一个直播平台 APP,我们团队已经是深度 Cordova+Vue 患者,但是直播这一块的话已经多方考证是无法用纯 WEB 方案解决的了,于是只能硬着头皮写原生的 Cordova 插件。

作者本人学艺不精,缺胳膊少腿,在几乎不会 iOS 和 Android 原生开发的前提下揽了一个大活,这要求我带团队在一个月时间内要攻克这个用插件接入直播的技术难点并且完成 150+ 功能用例的 Hybrid App。

开发的目标是在 Android 和 iOS 平台下支持腾讯互动直播云 ILVB:

产品地址:https://www.qcloud.com/product/ilvb 官方文档:https://cloud.tencent.com/document/product/268

首先声明一下我的开发环境,是使用 Ubuntu 17.04 的操作系统,配合 Cordova 7.0 进行开发。

创建项目

创建 Cordova 主项目 ilvb-demo

我们先从 Android 端入手,我们目标开发的插件命名为 cordova-plugin-tencent-ilvb,我在 GitHub 上面独立设置了仓库,这里仅存放插件的文件。然后本地存放的路径为 ~/app/cordova-plugin-tencent-ilvb,后面的解说会维持这样的配置。

另外,我们需要创建一个 Cordova 项目:

cordova create ilvb-demo

创建插件项目 cordova-plugin-tencent-ilvb

然后我们进入 cordova-plugin-tencent-ilvb 创建一些基础的文件:

插件配置文件 config.xml

首先是 config.xml

下面只是一个基础的骨架,后面我们会加进去更多的东西:

<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-tencent-ilvb"
        version="0.1.0"
        xmlns="http://apache.org/cordova/ns/plugins/1.0"
        xmlns:android="http://schemas.android.com/apk/res/android">

    <name>TencentILVB</name>
    <description>Tencent ILVB Plugin</description>
    <license>Apache 2.0</license>
    <keywords>cordova,live,video,tencent,qq,ilvb,lvb</keywords>
    <repo>https://github.com/EaseCloud/cordova-plugin-tencent-ilvb.git</repo>
    <issue>https://github.com/EaseCloud/cordova-plugin-tencent-ilvb/issues</issue>

    <engines>
        <engine name="cordova" version=">=3.5.0"/>
    </engines>

    <!-- 这里指定了 js 接口层文件的路径 -->
    <js-module name="TencentILVB" src="www/ilvb.js">
        <!-- 这里指定 window.TencentILVB 可以访问到插件的 js 接口层 -->
        <clobbers target="TencentILVB" />
    </js-module>

    <!-- 目前暂时先做 Android,iOS 会有独立的另一个 platform 节点 -->
    <platform name="android">
        <!-- 下面马上需要对 android 平台填写配置 -->
        <config-file target="res/xml/config.xml" parent="/*">
            <feature name="TencentILVB" >
                <param name="android-package" value="cn.easecloud.cordova.tencent.ilvb"/>
            </feature>
        </config-file>
    </platform>

</plugin>

OK,我们现在就需要填充 Android 平台的配置。

需要额外说明一下 <config-filg> 这一段的配置,这一段配置是必须的,它会将 <feature> 这个标签的内容加入到 ~/app/ilvb-demo/platforms/android/res/xml/config.xml 里面,它指定了我们正在开发的插件的 java 包名。

Android 平台依赖库 JAR 包引入

官方给出了一个随心播的示例 APP 仓库,我们需要从里面抽取所有的插件:

git clone https://github.com/zhaoyang21cn/ILiveSDK_Android_Suixinbo
cp -r ~/app/ILiveSDK_Android_Suixinbo/app/libs ~/app/cordova-plugin-tencent-ilvb/src/android/libs

里面大概是这么一堆冬冬。

drwxr-xr-x 2 alfred alfred   4096 6月  21 11:44 ./
drwxr-xr-x 4 alfred alfred   4096 6月  21 11:44 ../
-rw-r--r-- 1 alfred alfred 132637 6月  21 11:44 cos-sdk-android-1.4.3.jar
-rw-r--r-- 1 alfred alfred  68112 6月  21 11:44 MobCommons-2017.0216.1054.jar
-rw-r--r-- 1 alfred alfred 197138 6月  21 11:44 MobTools-2017.0216.1054.jar
-rw-r--r-- 1 alfred alfred   1058 6月  21 11:44 sha1utils.jar
-rw-r--r-- 1 alfred alfred 119034 6月  21 11:44 ShareSDK-Core-2.8.1.jar
-rw-r--r-- 1 alfred alfred   6277 6月  21 11:44 ShareSDK-Wechat-2.8.1.jar
-rw-r--r-- 1 alfred alfred  43061 6月  21 11:44 ShareSDK-Wechat-Core-2.8.1.jar
-rw-r--r-- 1 alfred alfred   6291 6月  21 11:44 ShareSDK-Wechat-Favorite-2.8.1.jar
-rw-r--r-- 1 alfred alfred   6496 6月  21 11:44 ShareSDK-Wechat-Moments-2.8.1.jar

然后,我们把这些库文件用得着用不着全部引用到我们的插件里面去。

    <platform name="android">
        <!-- ... 这是原来的内容,下面的内容加在后面 -->
        <source-file src="src/android/libs/cos-sdk-android-1.4.3.jar" target-dir="libs"/>
        <source-file src="src/android/libs/MobCommons-2017.0216.1054.jar" target-dir="libs"/>
        <source-file src="src/android/libs/MobTools-2017.0216.1054.jar" target-dir="libs"/>
        <source-file src="src/android/libs/sha1utils.jar" target-dir="libs"/>
        <source-file src="src/android/libs/ShareSDK-Core-2.8.1.jar" target-dir="libs"/>
        <source-file src="src/android/libs/ShareSDK-Wechat-2.8.1.jar" target-dir="libs"/>
        <source-file src="src/android/libs/ShareSDK-Wechat-Core-2.8.1.jar" target-dir="libs"/>
        <source-file src="src/android/libs/ShareSDK-Wechat-Favorite-2.8.1.jar" target-dir="libs"/>
        <source-file src="src/android/libs/ShareSDK-Wechat-Moments-2.8.1.jar" target-dir="libs"/>
    </platform>

这里补充一下 <source-file> 标签的作用,就是把插件内部 src 路径的文件安装到 cordova 项目(在我们的例子中就是 ilvb-demo 这个项目的 /platform/xxx/ 下面对应 target-dir 路径的目录中)。

Android 原生接口层类文件定义

好了,这里可以说开始进入正式的编码层面,虽然只是简单的先搭个框。

需要解释一下 Cordova 的插件运作机制,其实说白了就是一个 Adapter Pattern,我们要做的主要就是将一些原生的功能或者接口封装成 js 的接口,因此,除了原生的功能实现(这里一部分是实现原生的界面,一部分仅仅调用 SDK 即可),我们还需要做两个接口层的代码,一个是 js 层的接口代码,第二个是原生层的接口代码。

下面我们先关注 Android 原生的接口层代码,这是暴露给 js 接口的所有调用的入口:

首先我们在 plugin.xml 里面加入这个原生接口层的 java 类文件入口。

    <platform name="android">
        <!-- ... 这是原来的内容,下面的内容加在后面 -->
        <source-file src="src/android/TencentILVB.java" target-dir="src/cn/easecloud/cordova/tencent/ilvb" />
    </platform>

解析:<source-file> 标签的意思是将某个源文件(可以是代码或者资源文件)复制到 cordova 主项目对应 platform 中的某个目录,src 属性指定了在插件下的目录,target-dir 的话指定了在 cordova 主项目里面的目录,因此,上面这条配置在我们安装这个插件的时候,就等价于下面这句复制命令:

cp ~/app/cordova-plugin-tencent-ilvb/src/android/TencentILVB.java ~/app/ilvb-demo/platforms/android/src/cn/easecloud/cordova/tencent/ilvb/

注意 target 指定的路径与前面配置的插件的包名 cn.easecloud.cordova.tencent.ilvb 是对应的。

于是,我们现在编辑 ~/app/cordova-plugin-tencent-ilvb/src/android/TencentILVB.java 这个文件:

import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class TencentILVB extends CordovaPlugin {

    /**
     * Sets the context of the Command. This can then be used to do things like
     * get file paths associated with the Activity.
     *
     * @param cordova The context of the main Activity.
     * @param webView The CordovaWebView Cordova is running in.
     */
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
    }

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action          The action to execute.
     * @param args            JSONArry of arguments for the plugin.
     * @param callbackContext The callback id used when calling back into JavaScript.
     * @return True if the action was valid, false if not.
     */
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
        // 这段用来调试的,JS 接口调用 action 方法之后成功回调函数会获得 'Action [action] success!' 的字符串参数回调,
        // 并且获得字符串 'Done' 的这个返回值
        callbackContext.success("Action [" + action + "] success!");
        return "Done";
    }

}

其实关键的只有一个类,两个方法,下面说一下这两个方法:

initialize 方法 是插件加载的时候调用的,在这个方法内部可以获得 cordova 句柄(后面用到时候就知道有什么用了)以及主界面的 webView,其实我们可以在这里将其复制到 TencentILVB 类的成员字段里面去保存这几个变量以供后用(这样子就可以通过 this 指针的属性获取到 cordova 句柄和 webView 对象),也可以在这个方法里面做一些初始化的工作,例如创建一个 Activity,建立个连接啥的。这个方法的触发应该会在前端的 cordova ready 事件回调之前 关于启动的生命周期

execute 方法,这个方法是一个 JS 调用接口的统一入口方法,注意我们在 plugin.xml 里面指定了 window.TencentILVB 是 JS 入口对象,那么当我们在前端调用:

var result = window.TencentILVB.doSomething(params);

这样一句话的时候,流程就会交给这个 java 类的方法,变成调用 objTencentILVB.execute("doSomething", params, ...) 的这个样子,所以我们可以通过 action 的值以及 args 的参数值来路由到具体实现的功能,以实现多个不同的功能接口。

另外,这个 execute 的返回值也会直接返回到 js 调用方法的返回值中,而通过 callbackContext.success 方法传进去的参数则会回调到 JS 的回调函数中。

JS 接口层定义

好了,前面已经写好了 Android 接口层的代码,现在需要定义 JS 接口层,这个其实更为简单。

我们编辑 ~/app/cordova-plugin-tencent-ilvb/www/ilvb.js 这个文件:

var exec = require('cordova/exec');

module.exports = {
    test: function(params, success, error) {
        exec(success, error, 'TencentILVB', 'test', [params]);
    }
};

这样就比较明显了,简单来说,我们通过调用 window.TencentTLVB.test({ a: 1, b: 2 }, success => {}, error => {}) 就可以调用进去那段 java 代码了,这个代码文件是一个很简明的接口定义代码,只需要将相应的方法适配过去即可,不涉及具体的方法实验。

目录结构

最后,插件目录需要一个 pakage.json

{
  "name": "cordova-plugin-tencent-ilvb",
  "version": "0.0.1",
  "description": "Cordova Tencent ILVB Plugin",
  "cordova": {
    "id": "cordova-plugin-tencent-ilvb",
    "platforms": [
      "android",
      "ios"
    ]
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/Easecloud/cordova-plugin-tencent-ilvb"
  },
  "keywords": [
    "cordova",
    "live",
    "video",
    "tencent",
    "qq",
    "ilvb",
    "lvb",
    "cordova-android",
    "cordova-ios"
  ],
  "author": "Foshan EaseCloud Computer Technology Co., Ltd.",
  "license": "Apache-2.0",
  "engines": {
    "cordovaDependencies": {
      "2.0.0": {
        "cordova": ">100"
      }
    }
  },
  "devDependencies": {
  }
}

完成上面的所有操作后,目录路径大概是这个样子:

~/app
├── cordova-plugin-tencent-ilvb
│   ├── package.json
│   ├── plugin.xml
│   ├── README.md
│   ├── src
│   │   └── android
│   │       ├── libs
│   │       │   ├── cos-sdk-android-1.4.3.jar
│   │       │   ├── MobCommons-2017.0216.1054.jar
│   │       │   ├── MobTools-2017.0216.1054.jar
│   │       │   ├── sha1utils.jar
│   │       │   ├── ShareSDK-Core-2.8.1.jar
│   │       │   ├── ShareSDK-Wechat-2.8.1.jar
│   │       │   ├── ShareSDK-Wechat-Core-2.8.1.jar
│   │       │   ├── ShareSDK-Wechat-Favorite-2.8.1.jar
│   │       │   └── ShareSDK-Wechat-Moments-2.8.1.jar
│   │       └── TencentILVB.java
│   └── www
│       └── ilvb.js
└── ilvb-demo
    ├── config.xml
    ├── hooks
    ├── package.json
    ├── platforms
    ├── plugins
    ├── res
    ├── run.sh
    └── www

ilvb-demo 主项目中进行测试

现在我们用 IDE 打开 ilvb-demo 这个目录。

我们编辑一下 run.sh 这个脚本,可以快速将 cordova-plugin-tencent-ilvb 文件刷新并且运行这个 APP。

#!/usr/bin/env bash

cordova plugin remove -save cordova-plugin-tencent-ilvb
cordova plugin add -save ../cordova-plugin-tencent-ilvb

cordova run android

然后运行一下看看:

cordova platform add android
./run.sh

【转载请附】愿以此功德,回向 >>

原文链接:http://www.huangwenchao.com.cn/2017/06/cordova-plugin-1.html【Cordova 插件开发手札(一)- 腾云互动直播云】

发表评论

电子邮件地址不会被公开。 必填项已用*标注