前言:
在集成某些特定 原生SDK的时候,它本身是带UI控件的。当我们使用 uniapp 开发app的时候实是 可以使使用 nvue 页面,以 weex 的方式嵌入原生的UI控件。
我这边的场景是 接入连连app的支付,它有个自己的密码键盘 控件是原生的页面。这里就需要用到 nvue 以 weex 的方式接入:
图中
蓝色部分为 sdk 密码控件输入框,下面弹出的软键盘为 SDK 自带密码键盘; 函数为密码键盘SDK提供的函数
官方文档解析:
查看官方文档:
开发者须知 | uni小程序SDK
public class TestText extends UniComponent<TextView>
只要继承 UniComponent 的控件 就可以了,但是这里有个插曲。 代码自动生成的 构造函数多了一个参数。造成框架初始化 weex 组件(原始组件)不成功 “ com.taobao.weex.common.xRuntimeException: can't find constructor of component”
///错误的 四个参数 public InputLianLian(UniSDKInstance instance, AbsVContainer parent, int type, AbsComponentData componentData) { super(instance, parent, type, componentData); } ///正确的 三个参数 public InputLianLian(UniSDKInstance instance, AbsVContainer parent, AbsComponentData componentData) { super(instance, parent, componentData); AbsAttr attr = componentData.getAttrs(); aesKey = (String) attr.get("aesKey"); rasKey = (String) attr.get("rsaPublic"); }
在 initComponentHostView 中返回你的控件就可以了
@Override protected PassGuardEdit initComponentHostView(@NonNull Context context) { inputEditText = new PassGuardEdit(context, null); inputEditText.setButtonPress(true); if ((aesKey != null && aesKey.length() > 0) && (rasKey != null && rasKey.length() > 0)) { inputEditText.setCipherKey(aesKey); inputEditText.setPublicKey(rasKey); } inputEditText.needScrollView(false); inputEditText.setButtonPressAnim(true); //6-12位的字母、数字,不可以是连续或者重复的数字和字母 inputEditText.setInputRegex("[a-zA-Z0-9]{1,12}"); //inputEditText.setInputRegex("[0-9]{1,6}"); inputEditText.setClip(false); inputEditText.setMaxLength(12);//12位 //inputEditText.useNumberPad(true);//纯数字 inputEditText.setWatchOutside(true); inputEditText.initPassGuardKeyBoard(); return inputEditText; }
上手实操:
如果你是云打包,那么就需要把插件写成 模块库 的方式开发。方便导出 .aar库 给其他程序使用 。如果你是本地打包 那么直接写就好了。我这边是云打包,开发的时候 是本地跑的方式。
脚本依赖:
因为我们 是以 库的方式开发的,本身工程文件最好不好防止三方依赖库。我们都依赖 主应用的三方库;
. InputLianLian.java 完整控件脚本
package com.john.bridge.component; import android.content.Context; import androidx.annotation.NonNull; import cn.passguard.PassGuardEdit; import io.dcloud.feature.uniapp.UniSDKInstance; import io.dcloud.feature.uniapp.annotation.UniJSMethod; import io.dcloud.feature.uniapp.bridge.UniJSCallback; import io.dcloud.feature.uniapp.dom.AbsAttr; import io.dcloud.feature.uniapp.ui.action.AbsComponentData; import io.dcloud.feature.uniapp.ui.component.AbsVContainer; import io.dcloud.feature.uniapp.ui.component.UniComponent; public class InputLianLian extends UniComponent<PassGuardEdit> { private PassGuardEdit inputEditText; private String aesKey; private String rasKey; public InputLianLian(UniSDKInstance instance, AbsVContainer parent, AbsComponentData componentData) { super(instance, parent, componentData); AbsAttr attr = componentData.getAttrs(); aesKey = (String) attr.get("aesKey"); rasKey = (String) attr.get("rsaPublic"); } @Override protected PassGuardEdit initComponentHostView(@NonNull Context context) { inputEditText = new PassGuardEdit(context, null); inputEditText.setButtonPress(true); if ((aesKey != null && aesKey.length() > 0) && (rasKey != null && rasKey.length() > 0)) { inputEditText.setCipherKey(aesKey); inputEditText.setPublicKey(rasKey); } inputEditText.needScrollView(false); inputEditText.setButtonPressAnim(true); //6-12位的字母、数字,不可以是连续或者重复的数字和字母 inputEditText.setInputRegex("[a-zA-Z0-9]{1,12}"); //inputEditText.setInputRegex("[0-9]{1,6}"); inputEditText.setClip(false); inputEditText.setMaxLength(12);//12位 //inputEditText.useNumberPad(true);//纯数字 inputEditText.setWatchOutside(true); inputEditText.initPassGuardKeyBoard(); return inputEditText; } @UniJSMethod public void initEditText(String aesKey, String rasKey) { if ((aesKey != null && aesKey.length() > 0) && (rasKey != null && rasKey.length() > 0)) { inputEditText.setCipherKey(aesKey); inputEditText.setPublicKey(rasKey); inputEditText.initPassGuardKeyBoard(); } } @UniJSMethod(uiThread = true) public void getInputMD5(UniJSCallback callback) { if (callback != null && inputEditText != null) { callback.invoke(inputEditText.getMD5()); } } @UniJSMethod(uiThread = true) public void getInputLength(UniJSCallback callback) { if (callback != null && inputEditText != null) { callback.invoke(inputEditText.getLength()); } } @UniJSMethod(uiThread = true) public void getInputRSAAES(UniJSCallback callback) { if (callback != null && inputEditText != null) { callback.invoke(inputEditText.getRSAAESCiphertext ()); } } }
配置 weex 控件 dcloud_uniplugins.json
因为 uniapp 是通过我们这个配置表 来加载 weex 控件的;要么通过代码的方式也是可以的,这里两张都介绍下。应为你要告诉你的 主APP 你都有哪些 自定义的 weex 控件:
配置文件:
代码的方式:
基本上差不多了,已经跑起来了
我们再来看 .nvue 的页面
组件 inputLianLian 直接使用,方法调用,以及参数传值。
<template> <div class="mian"> <div> <!-- 直接传入 aesKey rasKey 初始化控件 --> <inputLianLian ref='inputLianLian' :aesKey="aesKey" :rasKey="rasKey" style="width:690rpx;height:120rpx;background-color: aqua;"> </inputLianLian> <div @click="getMD5()" style="width: 200;height: 80rpx; background-color: azure;">getMD5</div> <div @click="getLength()" style="width: 200;height: 80rpx;background-color:bisque;">getLength</div> <div @click="getLInputAESCode()" style="width: 200;height: 80rpx;background-color:coral;">getLInputAESCode </div> <div @click="initLianLian()" style="width: 200;height: 80rpx;background-color:darkgray;">initLianLian</div> </div> </div> </template> <script> import md5 from 'uview-ui/libs/function/md5'; export default { data() { return { aesKey: '26999721009008604284404453805522', rasKey: '3081890281810092D9D8D04FB5F8EF9B8374F21690FD46FDBF49B40EECCDF416B4E2AC2044B0CFE3BD67EB4416B26FD18C9D3833770A526FD1AB66A83ED969AF74238D6C900403FC498154EC74EAF420E7338675CAD7F19332B4A56BE4FF946B662A3C2D217EFBE4DC646FB742B8C62BFE8E25FD5DC59E7540695FA8B9CD5BFD9F92DFAD009D230203010001' } }, methods: { ///二次初始化,刚进来拿不到初始化参数 参数情况下 , ///如果输入框不能二次初始化,等待拿到数据再展示 initLianLian() { this.$refs.inputLianLian.initEditText('aesKey', 'rasKey'); }, async getMD5() { this.$refs.inputLianLian.getInputMD5((md5) => { uni.showToast({ title: `md5:${md5}`, duration: 3000 }); }); const md5 = await getInputMD5(); uni.showModal({ content: `md5:${md5}`, }) }, getLength() { this.$refs.inputLianLian.getInputLength((length) => { uni.showToast({ title: `length:${length}`, duration: 3000 }); }); }, getLInputAESCode() { this.$refs.inputLianLian.getInputRSAAES((code) => { uni.showToast({ title: `code:${code}`, duration: 3000 }); }); }, getInputMD5() { return new Promise((resolve, reject) => { try { this.$refs.inputLianLian.getInputMD5((md5) => { console.log('onMD5:', md5) resolve(md5); }) } catch (ex) { console.log('onMD5 error:', ex) //reject('') resolve(''); } }); } } } </script> <style> .mian { display: flex; flex-direction: column; align-items: center; } </style>
设置weex脚本 不混淆
因为 weex 加载是通过,反射的方式加载的。如果脚本混淆了,脚本的配置文件就对应不上了
导出 .aar 给云打包使用:
这里我们需要工程 导出为 .aar
在uniapp中设置 原生插件: 主要两个目录:
---android 放置 .aar
--- libs 放置 .jar 和 对应的 .so ; .so 文件按照 CPU 目录放置
插件描述文件 : 和 上面的 dcloud_uniplugins.json 有点像
配置没有错误:这里就能展示出来了