您的位置:首页 > 移动开发 > Android开发

Cordova插件开发(2)-Android插件安装包制作详解

2018-01-27 21:34 495 查看
本篇文章讲述的是如何制作自己的Cordova插件安装包(Android),具体内容包括以下三个方面:

1,安装和使用plugman;

2,开发自己的Cordova插件安装包;

3,插件安装包的安装与卸载;

本篇文章以自定义加密压缩文件插件的实践过程为例,本人不会IOS,倒是撸过两年Android,所以这里只讲述Android平台的实现过程。

一,准备工作

需已搭建好Codova环境;

二,具体实现

1,安装plugman

plugman是Cordova官方推荐使用的创建插件工具,执行以下命令即可安装:

npm install -g plugman

2,使用plugman创建插件模板

2.1 创建插件

plugman创建插件方式如下:

plugman create --name 插件名 --plugin_id 插件id --plugin_version 插件版本号

执行以下命令,即可创建一个插件名为fileUtil,插件id为fxp-plugin-fileUtil,版本号为1.0.0的插件:

plugman create --name fileUtil --plugin_id fxp-plugin-fileUtil --plugin_version 1.0.0


2.2 给插件添加Android平台

cd fileUtil
plugman platform add --platform_name android

到了这一步,插件模板就创建完成了,新创建的插件模板目录结构如下:



以上目录中,一共有plugin.xml、fileUtil.java、fileUtil.js三个文件。接下来我们就可以在此插件模板基础上开发自己的插件安装包了。当然,也可以不安装使用plugman,直接手动创建以上文件目录。

3,开发自己的Cordova插件安装包

其实插件安装包文件目录结构完全不用拘泥于以上,只要在plugin.xml文件中配置得当,目录结构可以随意。但出于规范,我们还是参照以上结构比较好。下面是我写的加密压缩文件插件目录结构:



以上目录中,plugin.xml是核心配置文件,src->android->code目录下是安卓代码,src->android->libs目录下是安卓用到的jar包,www 目录下的是js接口文件。下面开始讲解具体实现。

3.0  编辑package.json文件

package.json文件用于安装和发布,在以前的cordova版本中,没有此文件也可以正常本地安装自己的插件,但最近不行了,必须得有。直接上代码:

{
  "name": "fxp-plugin-fileUtil",
  "version": "1.0.0",
  "description": "create and zip file, used to export data to zip",
  "cordova": {
    "id": "fxp-plugin-fileUtil",
    "platforms": [
      "android"
    ]
  },
  "repository": {
    "type": "",
    "url": ""
  },
  "keywords": [
    "cordova",
    "zip",
    "file",
    "phonegap",
    "ecosystem:cordova",
    "cordova-android"
  ],
  "author": "",
  "license": "Apache 2.0",
  "bugs": {
    "url": ""
  },
  "homepage": ""
}


3.1  编辑plugin.xml文件

plugin.xml是核心配置文件,不废话,直接上代码,代码已详细注释配置说明及需要注意的问题:

<?xml version='1.0' encoding='utf-8'?>
<plugin xmlns:android="http://schemas.android.com/apk/res/android" id="fxp-plugin-fileUtil"
version="1.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0">
<name>fileUtil</name>
<!-- 一个plugin可以有多个module,类似于Android Studio中project和module的概念-->
<!-- js-module name可随意命名,src值为此module对应js文件的相对路径 -->
<!-- 【插件id.js-module的name值】对应安装后zipUtil.js中cordova.define方法第一个参数,以及其在cordova_plugin.js中的id值 -->
<js-module name="zipUtil" src="www/fileUtil.js">
<!-- target值即为js调用插件方法时所用的对象名,可随意命名;对应安装后cordova_plugin.js中clobbers值 -->
<clobbers target="fxp.plugins.zipUtil" />
</js-module>
<!-- 可添加多个平台,name值为平台名-->
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<!-- 注册插件module,feature的name值为需要注册的js-module的name值 -->
<feature name="zipUtil">
<!-- name值随意,value值为【将插件id中"-"替换为"."后的字符串】.【feature的name值】-->
<param name="android-package" value="fxp.plugin.fileUtil.zipUtil" />
</feature>
</config-file>
<config-file parent="/*" target="AndroidManifest.xml">
<!-- 此处添加所需权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</config-file>
<!-- 将插件文件放到指定目录:src为在插件安装包中的相对路径,target-dir为在插件安装后的相对路径 -->
<!-- 将java类文件放到【src/包名】目录,注意:此处所写包名须与java类中包名一致 -->
<source-file src="src/android/code/zipUtil.java" target-dir="src/fxp.plugin.fileUtil" />
<source-file src="src/android/code/CompressUtil.java" target-dir="src/fxp.plugin.fileUtil" />
<source-file src="src/android/code/DateUtils.java" target-dir="src/fxp.plugin.fileUtil" />
<source-file src="src/android/code/FileService.java" target-dir="src/fxp.plugin.fileUtil" />
<source-file src="src/android/code/FileUtils.java" target-dir="src/fxp.plugin.fileUtil" />
<source-file src="src/android/code/StringUtil.java" target-dir="src/fxp.plugin.fileUtil" />

<!-- Cordova官方提供了以下两种库依赖方式 -->
<!-- 1,首选framework标签。此方法引入的库可被多个插件使用而不产生冲突;但此方法引入非官方jar包会失败,故此demo不用此方式 -->
<!--<framework src="com.android.support:support-v4:24.1.1+" />-->

<!-- 2,其次lib-file标签。但如果有其他插件也添加了此依赖,则可能产生冲突;此demo依赖的是非官方库,只有用此标签了 -->
<lib-file src="src/android/libs/zip4j_1.3.1.jar" />
<lib-file src="src/android/libs/commons-lang3-3.1.jar" />
<lib-file src="src/android/libs/commons-codec-1.7.jar" />

<!-- 经验证,使用source-file标签将依赖包放到libs目录,然后添加依赖关系也是可行的。如下: -->
<!-- 将依赖包文件放到【libs】目录 -->
<!-- 插件安装后执行cordova run 命令或在Android Studio中Sync操作即可自动添加依赖关系;如果没有自动添加,可以手动添加 -->
<!--<source-file src="src/android/libs/commons-codec-1.7.jar" target-dir="libs" />-->
<!--<source-file src="src/android/libs/commons-lang3-3.1.jar" target-dir="libs" />-->
<!--<source-file src="src/android/libs/zip4j_1.3.1.jar" target-dir="libs" />-->

</platform>
</plugin>

plugin.xml中配置项其实是很多的,由于此demo中只需要以上配置,所以就没有体现其他配置项了。想要了解更多的话,可以留言讨论,我会尽快回复。当然,也可以直接看官方文档(纯英文):http://cordova.apache.org/docs/en/latest/plugin_ref/spec.html

3.2  编辑fileUtil.js(js接口实现)

依旧直接上代码,代码已详细注释:

/**
* cordova.define 的第一个参数为【插件id.js-module的name值】,对应安装后cordova_plugins.js里面定义的id
* exec方法,参数说明:
* 参数1:成功回调function
* 参数2:失败回调function
* 参数3:feature name,与config.xml中注册的一致
* 参数4:调用java类时的action
* 参数5:要传递的参数,json数组格式
* 下面提供三种实现方式
*/
//cordova.define("fxp-plugin-fileUtil.zipUtil", function(require, exports, module) {
var exec = require('cordova/exec');

exports.exportDatasToEncryptedZip=function(content, successCallback, errorCallback){
exec(successCallback,errorCallback,"zipUtil","exportDatasToEncryptedZip",[content]);
};
exports.writeFileToDir=function (content, successCallback, errorCallback) {
cordova.exec(successCallback, errorCallback, "zipUtil", "writeFileToDir", [content]);
};
exports.zipEncryptedFolders= function (content, successCallback, errorCallback) {
cordova.exec(successCallback, errorCallback, "zipUtil", "zipEncryptedFolders", [content]);
}

/*        module.exports = {
exportDatasToEncryptedZip: function(content, successCallback, errorCallback){
cordova.exec(successCallback,errorCallback,"zipUtil","exportDatasToEncryptedZip",[content]);
}
,
writeFileToDir: function (content, successCallback, errorCallback) {
cordova.exec(successCallback, errorCallback, "zipUtil", "writeFileToDir", [content]);
},
zipEncryptedFolders: function (content, successCallback, errorCallback) {
cordova.exec(successCallback, errorCallback, "zipUtil", "zipEncryptedFolders", [content]);
}
}*/

/*                var exec = require('cordova/exec');
var FXP = function(){};
FXP.prototype.exportDatasToEncryptedZip=function(content,success, error) {
cordova.exec(success,error,"zipUtil","exportDatasToEncryptedZip",[content]);
};
FXP.prototype.writeFileToDir=function(content,success, error) {
cordova.exec(success, error, "zipUtil", "writeFileToDir", [content]);
};
FXP.prototype.zipEncryptedFolders=function(content,success, error) {
cordova.exec(success, error, "zipUtil", "zipEncryptedFolders", [content]);
};
var fxp = new FXP();
module.exports = fxp;*/

//});


3.3  编辑zipUtil.java(安卓原生接口实现)
package fxp.plugin.fileUtil;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import android.widget.Toast;

/**
* This class echoes a string called from JavaScript.
*/
public class zipUtil extends CordovaPlugin {

/**
* @param action          The action to execute.
* @param args            The exec() arguments, wrapped with some Cordova helpers.
* @param callbackContext The callback context used when calling back into JavaScript.
* @return
* @throws JSONException
*/
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("exportDatasToEncryptedZip")) {
exportDatas(args,callbackContext);
return true;
} else if (action.equals("writeFileToDir")) {
String message = args.getString(0);
//TODO

return true;
} else if (action.equals("zipEncryptedFolders")) {
String message = args.getString(0);
//TODO

return true;
}else {
//TODO
}
return super.execute(action, args, callbackContext);
}

private void exportDatas(JSONArray args,CallbackContext callbackContext) throws JSONException{
JSONObject jsonArgs = new JSONObject(args.getString(0));
String fileContent = (String) jsonArgs.get("fileContent");
String fileName = (String) jsonArgs.get("fileName");
String zipPath = (String) jsonArgs.get("zipPath");
String zipName = (String) jsonArgs.get("zipName");
Boolean isCreateDir = (Boolean) jsonArgs.get("isCreateDir");
String zipPwd = (String) jsonArgs.get("zipPwd");
String exportPath = FileService.getInstance(cordova.getActivity()).exportDatasToEncryptedZip(fileContent, fileName, zipPath, zipName, isCreateDir, zipPwd);
if (exportPath != null && exportPath != "") {
Log.e("本地导出成功-exportPath", exportPath);
callbackContext.success(exportPath);
} else {
Log.e("本地导出失败-exportPath", exportPath);
callbackContext.error(exportPath);
}
}

}

关于此类中execute方法线程和args取值问题,我在另一篇博文中有详细讲述,请参看:Cordova插件开发(1)-Android插件开发详解

主要就是以上三个文件了,业务代码可根据实际需求添加。文件加密压缩插件调用方式如下:

var args = {
fileContent:"鹏超帅才不是单身狗鹏超帅才不是单身狗鹏超帅才不是单身狗",
fileName:"fxp_export.json",
zipPath:"/storage/emulated/0/FXP/export/",
zipName:"EncryptedZip.zip",
isCreateDir:true,
zipPwd:"123456"
}
fxp.plugins.zipUtil.exportDatasToEncryptedZip(args,function(success){
alert("本地导出成功-exportPath:" + success);
},function (error){
alert("本地导出失败-exportPath:" + error);
});

下面也贴一点功能实现代码吧。这种业务需求,一般习惯写个服务类统一代理,然后单例模式调用。如下:

package fxp.plugin.fileUtil;

import android.content.Context;

import java.util.ArrayList;
import java.util.List;

/**
* File
* $desc:文件操作服务类
*
* @author fxp
*         Created at 2017/4/17.
*/
public class FileService {

private final String TAG = "FileService";

private static FileService instance;

private Context context;

public static FileService getInstance(Context context) {
if (null == instance) {
instance = new FileService(context);
}
return instance;
}

private FileService(Context context) {
this.context = context;
}

/**
* create by fxp 2017-4-18 将字符串导出到加密压缩包
*
* @param fileContent:文本内容
* @param fileName:文件名
* @param exportPath:压缩包存放的位置,为Null则存放在第一个带压缩文件/文件夹所在路径
* @param zipName:压缩包名称
* @param isCreateDir:是否需要建立子文件夹
* @param zipPwd:加密密码
* @return 压缩文件的路径,失败则为NULL。返回值示例: /storage/emulated/0/FXP/export/20170418115248_done.zip
*/
public String exportDatasToEncryptedZip(String fileContent, String fileName, String exportPath, String zipName, boolean isCreateDir, String zipPwd) {
String filePath = "";
//临时文件夹路径。tempPath示例: /storage/emulated/0/FXP/temp/
String tempPath = FileUtils.getTmpPath();
String exportTime = DateUtils.formatDate("yyyyMMddHHmmss", DateUtils.getNow());
//临时文件路径
String dirPath = tempPath + exportTime + "/data/";

//将数据写入文件
boolean isWriteSuccess = writeFileToDir(dirPath, fileName, fileContent);
if (isWriteSuccess) {
List<String> folders = new ArrayList<String>();
//将需要导出的文件夹路径添加到链表
folders.add(tempPath + exportTime);
//加密压缩文件夹
filePath = zipEncryptedFolders(folders, exportPath, zipName, isCreateDir, zipPwd);
}

//删除临时文件夹及文件
FileUtils.deleteDirOrFile(tempPath);

return filePath;
}

/**
* create by fxp 2017-4-17 将文本内容写入到指定目录下文件
*
* @param dirPath:文件目录
* @param fileName:文件名称
* @param fileContent:文本内容
* @return 文本写入操作是否成功
*/
public boolean writeFileToDir(String dirPath, String fileName, String fileContent) {
return FileUtils.writeFileToDir(dirPath, fileName, fileContent);
}

/**
* create by fxp 2017-4-17 将1~N个文件或文件夹加密压缩到特定目录下
*
* @param folders:1~N个文件或文件夹的链表
* @param exportPath:压缩包存放的位置,为Null则存放在第一个带压缩文件/文件夹所在路径
* @param zipName:压缩包名称
* @param isCreateDir:是否需要建立子文件夹
* @param pwd:加密密码
* @return 压缩文件的路径,失败则为NULL。返回值示例: /storage/emulated/0/FXP/export/20170418115248_done.zip
*/
public String zipEncryptedFolders(List<String> folders, String exportPath, String zipName, boolean isCreateDir, String pwd) {
return CompressUtil.zipEncryptedFolders(folders, exportPath, zipName, isCreateDir, pwd);
}
}

该下班了,其他的就懒得贴了。回归正题,插件安装包开发完成。

4,安装自己的插件

本篇文章的重点是讲述插件安装包制作过程,所以这里先只讲本地安装,后面我会专门整理出一篇文章讲述npm、git等安装方式。

进入cordova工程目录执行以下命令:

cordova plugin add 插件安装包相对路径

例如,
sudo cordova plugin add ../fileUtil

Installing "fxp-plugin-fileUtil" for android
ANDROID_HOME=/Users/fxp/Library/Android/sdk
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home
Subproject Path: CordovaLib
Incremental java compilation is an incubating feature.
:clean
:CordovaLib:clean
BUILD SUCCESSFUL
Total time: 7.386 secs
Installing "fxp-plugin-fileUtil" for ios
注意:本地安装是根据相对路径,不是插件id。我这里是把fileUtil文件夹(插件安装包)放在cordova工程同一目录。

5,卸载插件

卸载方式并无不同,在cordova工程目录下执行以下命令:

cordova plugin remove 插件id

例如,

sudo cordova plugin remove fxp-plugin-fileUtil

Password:

Uninstalling fxp-plugin-fileUtil from android

Uninstalling fxp-plugin-fileUtil from ios
Removing "fxp-plugin-fileUtil"

三,写在后面

1,本篇文章意在讲述插件安装包制作过程,欢迎交流讨论;

2,本篇文章只讲解了制作本地安装包以及本地安装,后面有空会再整理一篇文章讲述基于npm、git方式;

3,此demo为需求验证所写,并非实际项目最终所用,不存在侵权问题;

4,已手撸插件实现了文件加密、文件解密、文件压缩、文件解压、文件MD5值校验和其他常见文件操作,但只撸了Android,IOS不会,期待IOS大神实现IOS版,愿交换完整代码;

5,不足之处,欢迎批评指正;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: