从零开始:使用UniApp构建Android原生插件的完整指南
1. 环境准备搭建UniApp原生插件开发环境第一次接触UniApp原生插件开发时我花了两天时间才把环境搭好。现在回想起来其实只要抓住几个关键点就能少走弯路。首先需要明确的是开发Android原生插件本质上是在用Android Studio写原生代码再通过UniApp的桥接机制让前端调用。必备工具清单Android Studio 最新稳定版建议4.2JDK 11注意不是最新版实测11兼容性最好UniApp官方提供的Android离线SDKHBuilderX用于调试UniApp项目下载Android离线SDK时有个坑要注意一定要选择与HBuilderX版本匹配的SDK。我遇到过因为版本不一致导致插件无法加载的情况。官方下载地址在DCloud文档中心可以找到解压后你会看到这些关键目录UniPlugin-Hello-AS/ ├── app/ # 示例主工程 ├── UniPlugin-Module/ # 插件模板 └── build.gradle # 工程配置配置Android Studio时建议先修改gradle-wrapper.properties中的distributionUrl换成你本地已有的gradle版本。我第一次运行时因为网络问题gradle下载失败后来改用本地缓存的7.0.2版本就顺利通过了。2. 创建你的第一个插件模块2.1 初始化插件工程用Android Studio打开UniPlugin-Hello-AS工程后我建议先clean再rebuild一次确保基础环境正常。接下来关键步骤是新建module右键工程 → New → Module选择Android Library命名建议用插件功能Plugin格式如MapPlugin新建的module会缺少关键配置需要从UniPlugin-Module复制这些内容build.gradle中的依赖项proguard-rules.pro混淆规则assets/目录下的原生插件声明文件特别注意要在module的build.gradle中添加这些关键依赖compileOnly fileTree(dir: ../app/libs, include: [uniapp-v8-release.aar]) implementation com.alibaba:fastjson:1.2.83 // UniApp使用的JSON库2.2 编写核心插件类所有UniApp原生插件都必须继承UniModule类。这里分享一个调试技巧先在构造函数里加Log输出方便排查插件是否加载成功public class MyFirstPlugin extends UniModule { private static final String TAG MyFirstPlugin; public MyFirstPlugin() { Log.d(TAG, 插件初始化成功); } UniJSMethod(uiThread true) public void showNativeDialog(String message) { // 注意要判断mUniSDKInstance是否有效 if(mUniSDKInstance ! null) { new AlertDialog.Builder(mUniSDKInstance.getContext()) .setMessage(message) .show(); } } }3. 插件打包与配置3.1 生成AAR文件在Terminal执行打包命令时建议先用gradlew tasks查看所有可用任务。常见问题及解决方案报错Could not determine java version → 检查JDK版本报错Failed to find target with hash string → 安装对应Android SDK版本正确的打包命令应该是./gradlew :mylibrary:assembleRelease生成的aar文件路径在mylibrary/build/outputs/aar/mylibrary-release.aar3.2 配置package.json这个配置文件是插件能被UniApp识别的关键。我整理了几个易错点name字段必须与插件类名一致class要写完整包名路径minSdkVersion不能低于21完整示例{ name: MyFirstPlugin, id: com.yourcompany.uniplugin, version: 1.0.0, _dp_type: nativeplugin, _dp_nativeplugin: { android: { plugins: [{ type: module, name: MyFirstPlugin, class: com.yourcompany.mylibrary.MyFirstPlugin }], integrateType: aar, minSdkVersion: 21 } } }4. UniApp集成与调试4.1 项目目录结构正确的插件存放位置很重要我推荐这样的结构nativeplugins/ └── MyFirstPlugin/ ├── android/ │ ├── mylibrary-release.aar │ └── package.json └── ios/ # 如果有iOS版本4.2 manifest.json配置在uni-app项目的manifest.json中添加app-plus: { plugins: { MyFirstPlugin: { version: 1.0.0, provider: com.yourcompany.uniplugin } } }4.3 调试技巧必须使用自定义调试基座标准流程HBuilderX → 运行 → 制作自定义调试基座选择你的打包模式建议选release运行到Android设备测试代码示例const plugin uni.requireNativePlugin(MyFirstPlugin) plugin.showNativeDialog(Hello from JS!)如果遇到插件未加载的问题可以按这个顺序排查检查控制台是否有插件初始化日志确认aar文件MD5值与打包时一致查看设备logcat中的UniApp相关日志5. 进阶开发技巧5.1 双向通信实现原生插件不仅可以被JS调用还能主动通知JS。比如实现一个计时器功能UniJSMethod(uiThread false) public void startTimer(int interval) { new Timer().schedule(new TimerTask() { Override public void run() { MapString, Object params new HashMap(); params.put(time, System.currentTimeMillis()); // 向JS发送事件 mUniSDKInstance.fireGlobalEventCallback(onTimerTick, params); } }, 0, interval); }JS端监听uni.onNativeEventReceive(onTimerTick, (res) { console.log(收到原生事件:, res.time) })5.2 性能优化建议线程管理耗时操作要加UniJSMethod(uiThread false)注解内存优化避免在插件中持有Activity引用异步回调复杂操作建议用Callback方式回调示例UniJSMethod(uiThread false) public void asyncTask(final UniJSCallback callback) { new Thread(() - { // 模拟耗时任务 try { Thread.sleep(1000); callback.invoke(任务完成); } catch (Exception e) { callback.invoke(e.getMessage()); } }).start(); }6. 常见问题解决方案问题1插件方法调用无效检查方法是否添加UniJSMethod注解确认方法签名是public查看是否有ProGuard混淆了方法名问题2资源文件加载失败把资源放在assets/目录下使用mUniSDKInstance.getContext().getResources()获取资源问题3插件打包后功能异常检查是否开启了minifyEnabled确认proguard-rules.pro包含UniApp相关keep规则测试时先用debug包排查记得每次修改原生插件后都需要重新打包aar更新到uni-app项目的nativeplugins目录重新制作自定义调试基座