从零创建cordova插件(包括四大组件、架包、生命周期)

1 介绍

本文将细致讲解cordova插件的创建、编写、plugin.xml配置、aar+jar+so架包配置、静态资源配置、四大组件配置

2 开始整活一个简单cordova插件

2.1 初始化Cordova插件开发目录

初始化之前确保安装Cordova

cordova create cordovaProject ths.com.cn cordovaApp
cordovaProject               创建应用程序的目录名称。
ths.com.cn                   反向域值
cordovaApp                   应用的标题。

创建项目目录 cordovaProject

$ cordova create cordovaProject ths.com.cn ThsToast

此时根目录下会生成如下结构


在添加platforms和plugins之后,可以在此目录下打包

cordovaProject$ cordova build android

2.2 安装plugman

plugman是用于安装和卸载用于Apache Cordova项目的插件的命令行工具。
进入cordovaApp项目根目录,安装plugman

$ npm install -g plugman

2.3 创建插件

2.3.1创建一个最简单的Toast插件

2.3.1.1 plugman create 在plugins下创建插件

cordovaProject$ plugman create --name [插件名] --plugin_id [插件id] --plugin_version [插件版本]

为了方便管理,将插件创建在 cordovaApp 项目目录下的 plugins 文件夹下

plugins$ plugman create --name ThsToast --plugin_id cordova-plugin-ths-toast --plugin_version 1.0.0

2.3.1.2 plugman platform add 创建插件的平台基础代码

进入具体的插件目录下,创建插件安卓和iOS平台基础代码

cordova-plugin-ths-toast$ plugman platform add --platform_name android
cordova-plugin-ths-toast$ plugman platform add --platform_name ios

添加之后将在cordova-plugin-ths-toast目录下产生android和ios两个目录,
生成的java文件内容如图所示

2.3.1.3 重命名插件目录名称(可选)

接着手动将ThsToast目录重命名为和上述plugin_id一样的值:cordova-plugin-ths-toast,命名方式和cordova插件命名规范保持一致,ths是公司的统一标识,通常是英文字符串

2.3.1.4 重命名java代码中的package包名和api方法名

需要将默认的包名改为[反向域值].cordova.[插件name],要注意的是,plugin.xml中配置的java文件target-dir输出目录需要和这里包名目录匹配,如
plugin.xml

注意:起名不要和安卓原生方法冲突了,比如这里ThsToast如果改成Toast,就会和android.widget.Toast中的Toast类重名,导致构建报错

2.3.2 插件配置

2.3.2.1 plugin.xml配置js调用方法名和资源文件输出路径

添加完平台后,cordova-plugin-ths-toast 目录下的 plugin.xml 文件将添加如下内容

修改 plugin.xml 文件内容如下



    Toast
    
        
        
    

    
        
            
            
                
            
        
        
        
        
    

    
        
            
                
            
        
        
    

2.3.2.2 www/xxx.js 修改js api对象和调用函数

2.3.2.2.1 修改exports处理逻辑,增强可读性(可选)

2.3.2.2.2 暴露给js的api方法名通过plugin.xml配置

www/xxx.js中export的ThsToast在plugin.xml中是通过clobbers的target值暴露给js调用的,如果target值改为toast,通过target.show即可调用插件api


    
    
2.3.2.2.3 exec函数干了什么

www/xxx.js中的exec函数可以理解为java中暴露给js的回调方法,用于触发java的excute方法,该js函数传的'show'和[arg0],success,error参数将会以action和args,callbackContext.success,callbackContext.error参数的形式传入java中的excute方法

@Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        ……
    }

2.3.3 写README的好处,是不怕记用户不住

cordova-plugin-ths-toast$ touch README.md

一个简单模版

---
title: ThsToast
description: 弹出提示框.
---

# cordova-plugin-ths-toast

这是一个简单的提示框插件
[插件github地址](https://github.com/qtpalmtop/cordova-plugin-ths-toast)

## 安装

通过 Cordova CLI 从npm安装:

\```
$ cordova plugin add cordova-plugin-ths-toast
$ cordova prepare
\```

## 支持平台

* Android 4.0.0
* iOS

## config.xml

延迟弹出时间
\```xml

\```
## 方法

- ThsToast.show
- ThsToast.hide

### ThsToast.show

弹出提示框

\```js
ThsToast.show(text, success, fail);
\```
- text String 显示文字
- success callback 成功回调 返回显示文字
- fail callback 失败回调 返回错误码

### ThsToast.hide

隐藏提示框

\```js
ThsToast.hide();
\```

2.3.4 初始化插件,给插件加上package.json

cordova-plugin-ths-toast$ npm init

或(推荐)

cordova-plugin-ths-toast$ plugman createpackagejson

上面的指令都将创建一个 package.json 文件,区别是npm init 不会生成"cordova"和"keywords"需要手动加上,"cordova"用于说明插件支持的平台,"keywords"
规定可以在cordova官网通过关键字搜索到该cordova插件,"engines"表示插件依赖的各平台版本号,详细内容请参考cordova创建插件

{
  "name": "cordova-plugin-ths-toast",
  "version": "1.0.0",
  "description": "",
  "cordova": {
    "id": "cordova-plugin-ths-toast",
    "platforms": [
      "android",
      "ios"
    ]
  },
  "keywords": [
    "ecosystem:cordova",
    "cordova-android",
    "cordova-ios",
    "toast",
    "cordova-plugin-ths-toast"
  ],
  engines: {
    cordovaDependencies: {
        "1.0.0":  { "cordova-android": ">4.0.0" },
        ">1.0.0": { "cordova-android": ">5.0.0" }
    }
  },
  "author": "",
  "license": "ISC"
}

这里可以搜索keywords中的插件
从零创建cordova插件(包括四大组件、架包、生命周期)_第1张图片

2.3.5 发布插件到npm

每次发布记得更新版本号

cordova-plugin-ths-toast$ npm login // 没有账号则需要到官网申请,登录过一次后就不用登了
cordova-plugin-ths-toast$ npm publish

2.3.6 安装插件

cordova plugin add cordova-plugin-ths-toast

2.3.6 使用插件

js环境

ThsToast.show()

ts环境

declare const ThsToast;
ThsToast.show()

3 cordova开发进阶

3.1 开发进阶之插件配置

3.1.1 广播


    
        
        
            
                
                
                
            
            
                
                
                
                
                
                
                
                
                
                
                
                
            
        
    

3.1.2 服务


    
        
        
                
                    
                    
                
            
    

3.1.3 内容提供者


    
    
      
      
    
    
    
    
        
    

3.1.4 架包

3.1.4.1 jar配置


    
        
    
    

3.1.4.2 so配置

3.1.4.2.1 so 路径

so是在NDK平台开发的,NDK是用来给安卓手机开发软件用的,但是和SDK不同的是它用的是C语言,而SDK用的是Java语言。NDK开发的软件在安卓的环境里是直接运行的,一般只能在特定的CPU指令集的机器上运行。

so配置通常配置在libs目录下

3.1.4.2.1 so plugin.xml配置,注意输出路径子目录也要改

    
    
    
    
        

3.1.4.3 aar配置

3.1.4.3.1 aar文件配置

aar和jar类似,但是他包含了所有资源,class以及res资源文件,aar和gradle通常放在libs下

3.1.4.3.2 gradle配置

gradle中要在repositories中配置flatDir,dependencies中配置compile的aar包

repositories{
    jcenter()
    flatDir{
        dirs 'libs'
    }
}

dependencies {
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile(name:'ijkplayer-java-debug', ext:'aar')
    compile(name:'giraffeplayer-debug', ext:'aar')
}
3.1.4.3.3 aar plugin.xml
 
    
    
    
    

3.1.5 静态资源和java文件

3.1.5.1 静态资源路径

静态资源规定放在src/android/res目录下

3.1.5.2 静态资源输出目录配置 通过resource-file和source-file配置当前路径和输出路径,静态资源默认路径是src/android/res/xxx, 输出路径是res/xxx


    
        
        

        
        

        
        
        

        
    

3.1.5.3 java文件路径

java文件通常放在src/android目录下
从零创建cordova插件(包括四大组件、架包、生命周期)_第2张图片

3.1.5.4 java文件输出目录配置 默认路径是src/android/Xxx.java 输出目录是src/包/名/字/,注意target-dir是目录路径,target才是文件路径。


    
        
        
    

3.1.5 meta-data

拿一个分享插件举例做示范

plugin.xml:配置preference,用于接收用户传参variable的值,config-file中配置meta-data, 保存参数键值信息用于给java类调用。

    
    
    

        
            
        
        
        
            
            
            
            
        

3.1.6 权限

当需要使用系统的某个功能时,一定要加上权限询问配置,所有的权限在这查看


    
    
    
    
    
    
    
    
    

3.2 开发进阶之插件实现

3.2.1 开启活动

简单来说,活动相当于angular的page,vue的vue,是一个可包含组件(fragment)的ui页面。

3.2.1.1 开启普通活动

// 应用上下文
Context context = cordova.getActivity().getApplicationContext();
String pkgName  = context.getPackageName();

// 打开app应用
Intent intent = context
        .getPackageManager()
        .getLaunchIntentForPackage(pkgName);

// 打开XxxActivity
// Intent intent=new Intent(cordova.getActivity(), XxxActivity.class);

// 打开应用必须要加 CATEGORY_LAUNCHER
intent.addCategory(Intent.CATEGORY_LAUNCHER);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

// 启动应用
context.startActivity(intent);

// 启动活动
// cordova.getActivity().startActivity(intent);

// 启动有返回值的活动
// cordova.startActivityForResult((CordovaPlugin) this, intent, 0);

3.2.1.2 打开第三方Android SDK活动 如:百度地图uri

// 如果有百度地图 uri详情:http://lbsyun.baidu.com/index.php?title=uri/api/android
Intent intent = Intent.parseUri("intent://map/direction?"
                        + "origin="+options.getOrigin4Baidu()
                        + "&destination="+options.getDestination4Baidu()
                        + "&mode="+options.getModel4Baidu()
                        + "&coord_type=wgs84&referer=Autohome|GasStation#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end",0);
                        
cordova.getActivity().startActivity(intent);

3.2.2 使用广播

广播其实就是一个在app范围内的事件推送和接受中心,类似于iframe的postMessage。

和原生广播没有区别,一般静态广播用在插件比较多

3.2.3 使用服务

服务可以同步或执行一些小任务、小进程,甚至对其他进程的ui页面做操作,可类比angular的service服务。

和原生Service一样的用法

3.2.4 使用内容提供者

内容提供者其实是一个手机系统范围的API调度中心,比如可以读取和修改通讯录和相册的内容。

3.2.5 使用架包

3.2.5.1 使用jar

jar包可以理解为api的集合,解压后全部是编译好的class,但是不包含资源文件,可以直接使用使用其中的类。

3.2.5.2 使用so

通常在jar中使用

3.2.5.3 使用aar

例如跳转activity

3.2.6 使用meta-data

保存用户添加插件时传入的参数键值对象

3.2.6.1 meta-data 在java中获取参数对象

Plugin.java:通过cordova.getActivity().getPackageManager().getApplicationInfo(cordova.getActivity().getPackageName(), PackageManager.GET_META_DATA)获取参数存储的对象appInfo,再通过appInfo.metaData.getType(key)取得参数value,getType有getString、getInt……
从零创建cordova插件(包括四大组件、架包、生命周期)_第3张图片

3.2.6.2 meta-data 如何传参

传入插件参数有两种办法,

1.用cordova 安装时利用--variable key=value 传入

cordova plugin add cordova-plugin-share --variable WEIXIN_APP_ID=xxx --variable WEIXIN_APP_SECRET=xxx 

2.添加插件完成后,在项目的config.xml中手动添加,cordova build后生效


    
    

3.2.7 使用权限

    import android.Manifest;

    public static final String WRITE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
    public static final String READ = Manifest.permission.READ_EXTERNAL_STORAGE;
    public static final int REQ_CODE = 0;

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("show")) {
            this.args = args;
            this.callbackContext = callbackContext;

            if (cordova.hasPermission(READ) && cordova.hasPermission(WRITE)) {
                // 有权限则跳转活动
                this.launchActivity();
            } else {
                // 若没有权限则请求
                this.getPermission();
            }
            return true;
        }
        return false;
    }
    
    /**
    * 请求权限
    **/
    protected void getPermission() {
        cordova.requestPermissions(this, REQ_CODE, new String[]{WRITE, READ});
    }
    
    @Override
    public void onRequestPermissionResult(int requestCode, String[] permissions,
                                          int[] grantResults) throws JSONException {
        for (int r : grantResults) {
            if (r == PackageManager.PERMISSION_DENIED) {
                this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
                return;
            }
        }

        switch (requestCode) {
            case REQ_CODE:
                launchActivity();
                break;
        }
    }

3.2.8 使用生命周期和常用回调方法

3.2.8.1 excute:执行插件方法

调用插件执行方法。第一个参数action是调用的方法名,第二个参数args是传入的参数数组,第三个参数CallbackContext是传入的回调函数上下文,可以通过callbackContext.success(message)和callbackContext.error(errorMessage)传入回调参数;

@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
}

3.2.8.2 initialize:初始化

在插件构造函数执行和字段初始化之后调用,此时尚未执行excute方法。

@Override
public void initialize (CordovaInterface cordova, CordovaWebView webView) {}

3.2.8.3 pluginInitialize:无参初始化

在插件构造函数执行和字段初始化之后调用,没有参数,此时尚未执行excute方法,pluginInitialize 不支持 cordova 3.0-3.5 。

@Override
protected void pluginInitialize() {}

3.2.8.4 onStart:活动开始周期

活动正在被启动,已经可见,但是还没位于前台。

@Override
public void onStart() {}

3.2.8.5 onResume:活动恢复周期

活动位于前台,并且可以与用户交互了。

/**
 * 当活动将开始与用户互动时调用。
 *
 * @param multitasking 表示是否为应用程序打开了多任务
 */
@Override
public void onResume(boolean multitasking) {
    super.onResume(multitasking);
    // deviceready();
}

3.2.8.6 onPause:活动暂停周期

活动处于正在停止的状态,通常当要离开这活动的时候会被调用。接下去onStop()马上会被调用,如果是弹出一个对话框,那么onStop不会被调用。

/**
 * 在系统即将开始恢复上一个活动时调用
 *
 * @param multitasking 表示是否为应用程序打开了多任务
 */
@Override
public void onPause(boolean multitasking) {
    super.onPause(multitasking);
}

3.2.8.7 onStop:活动停止周期

活动即将停止,活动完全不可见。

/**
 * 活动停止前调用
 */
@Override
public void onStop() {
    super.onStop();
}

3.2.8.8 onReset:活动重置周期

这个方法表示活动正在重新启动,活动由停止状态恢复为运行状态,通常由上一个活动返回到这个活动时,这个活动会调用此方法。

/**
 * 当视图导航时调用
 */
@Override
public void onReset() {}

3.2.8.9 onActivityResult:返回活动数据

当从另一个活动返回到当前活动时,当前活动中的onActivityResult可接收刚才活动的返回数据。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
}

3.2.8.10 onDestroy:活动销毁周期

活动完全销毁前调用,可以在这做一些资源释放的操作。

/**
 * 活动销毁前调用
 */
@Override
public void onDestroy() {
    // deviceready = false;
}

4 总结

本文从创建一个简单的cordova自定义插件,到四大组件的配置和使用,以及如何导入和使用jar、aar、so、静态资源方面做了详细讲解,最后归纳了常用的生命周期和回调方法。
看到这,我们应该已经具备独立创建和改写插件的基本能力,剩下的就只有自己多看多用cordova-plugin,实践出真知,若有总结不到位或者遗漏的地方,还请各位朋友多多指出,共同交流完善!如果这篇文章对前端或其他方向的你有所帮助或者启发,记得点个赞哦亲:)

你可能感兴趣的:(前端,cordova,cordova-android,android,插件)