首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >uni-app 自定义 Android 插件详解

uni-app 自定义 Android 插件详解

作者头像
木易士心
发布2025-11-30 09:26:38
发布2025-11-30 09:26:38
2040
举报

uni-app 自定义 Android 插件详解

在 uni-app 开发中,当内置 API 无法满足需求时(如调用特定硬件、集成第三方 SDK),就需要开发 自定义 Android 原生插件。这允许你使用 Java/Kotlin 编写原生代码,并通过 JavaScript 接口在 uni-app 中调用。


一、准备工作

  1. 开发环境:
    • HBuilderX (推荐使用最新版)
    • Android Studio
    • JDK
    • Android SDK
  2. 项目结构:
    • uni-app 项目根目录
    • nativeplugins/ 目录 (手动创建):存放所有自定义原生插件。

二、创建插件目录结构

nativeplugins/ 下创建插件文件夹,结构如下:

代码语言:javascript
复制
nativeplugins/
└── my-awesome-plugin/          # 插件根目录 (命名规范: 小写字母、数字、下划线)
├── android/               # Android 原生代码
│   ├── src/
│   │   └── main/
│   │       ├── java/      # Java/Kotlin 源码
│   │       │   └── com/
│   │       │       └── dcloud/
│   │       │           └── plugin/
│   │       │               └── MyAwesomePlugin.java  # 核心插件类
│   │       ├── AndroidManifest.xml  # 插件清单文件
│   │       └── assets/    # 资源文件 (可选)
│   └── build.gradle       # 插件构建脚本
├── package.json           # 插件描述文件 (必须)
└── index.js               # JS 调用接口 (可选,推荐)

三、编写 package.json

这是插件的核心描述文件,uni-app 通过它识别插件。

代码语言:javascript
复制
{
  "id": "my-awesome-plugin",          // 插件唯一标识 (与目录名一致)
  "displayName": "我的插件",      		// 插件名称 (HBuilderX 中显示)
  "version": "1.0.0",                 // 版本号
  "description": "一个演示自定义插件的示例", // 描述
  "platforms": {
    "Android": ">=3.0.0"             // 支持的平台和最低 uni-app 版本
  },
  "engines": {
    "HBuilderX": ">=3.0.0"           // 最低 HBuilderX 版本
  },
  "permissions": [
    "Camera",                        // 需要的权限 (会自动合并到主应用)
    "Storage"
  ],
  "hooks": [],                        // 钩子 (较少用)
  "nativePlugins": [
    {
      "type": "module",               // 类型: module (功能模块)
      "name": "MyAwesomePlugin",      // 模块名 (JS 中调用的名称)
      "android": {
        "plugins": [
          {
            "type": "service",        // 插件类型: service (服务类)
            "name": "MyAwesomePlugin", // Java 类名 (不含包名)
            "class": "com.dcloud.plugin.MyAwesomePlugin" // 完整类名
          }
        ]
      }
    }
  ]
}

四、编写 Android 原生代码 (Java)

1. 创建插件类 MyAwesomePlugin.java

该类必须继承 io.dcloud.feature.uniapp.common.UniModule

代码语言:javascript
复制
package com.dcloud.plugin;

import android.util.Log;
import android.widget.Toast;
import io.dcloud.feature.uniapp.annotation.UniJSMethod; // 注解: 标记 JS 可调用方法
import io.dcloud.feature.uniapp.common.UniModule;
import io.dcloud.feature.uniapp.ui.view.WebView;

public class MyAwesomePlugin extends UniModule {

    private static final String TAG = "MyAwesomePlugin";

    // JS 调用的方法必须用 @UniJSMethod 注解
    // mode = UniJSMethod.THREAD_UI: 在 UI 线程执行 (用于更新 UI)
    // mode = UniJSMethod.THREAD_MAIN: 在主线程执行 (默认)
    @UniJSMethod(uiThread = true)
    public void showToast(String message, int duration, UniCallback callback) {
        Log.d(TAG, "收到 JS 消息: " + message);

        // 在 UI 线程执行 Toast
        Toast.makeText(mWXSDKInstance.getContext(), 
                      message, 
                      duration == 1 ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG)
              .show();

        // 调用 callback 通知 JS 任务完成 (可选)
        if (callback != null) {
            // 返回给 JS 的数据
            UniMPJSResponse response = new UniMPJSResponse();
            response.setData("Toast 显示成功: " + message);
            response.setSuccess(true);
            callback.invoke(response);
        }
    }

    @UniJSMethod
    public void getDeviceInfo(UniCallback callback) {
        try {
            JSONObject deviceInfo = new JSONObject();
            deviceInfo.put("model", Build.MODEL);
            deviceInfo.put("brand", Build.BRAND);
            deviceInfo.put("version", Build.VERSION.RELEASE);
            
            UniMPJSResponse response = new UniMPJSResponse();
            response.setData(deviceInfo);
            response.setSuccess(true);
            callback.invoke(response);
        } catch (Exception e) {
            UniMPJSResponse response = new UniMPJSResponse();
            response.setSuccess(false);
            response.setMsg(e.getMessage());
            callback.invoke(response);
        }
    }

    // UniModule 提供的上下文
    // mWXSDKInstance.getContext() 获取 Context
}
2. AndroidManifest.xml (可选)

如果插件需要声明 Activity、Service 或特殊权限,需在此文件中定义。

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 插件所需的权限 (如果 package.json 中已声明,可省略) -->
    <!-- <uses-permission android:name="android.permission.CAMERA"/> -->

    <!-- 如果需要启动 Activity -->
    <!-- <activity android:name=".MyPluginActivity" /> -->

</manifest>
3. build.gradle (可选)

如果插件依赖第三方库,则需要此文件。

代码语言:javascript
复制
dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.9.3'
    // 添加其他依赖...
}

五、编写 JS 接口 (index.js)

提供一个更友好的 JavaScript 接口给开发者。

代码语言:javascript
复制
// nativeplugins/my-awesome-plugin/index.js

// 导出方法
export function showToast(message, duration = 0) {
  // uni.requireNativePlugin 返回原生模块实例
  const MyAwesomePlugin = uni.requireNativePlugin('MyAwesomePlugin');
  
  return new Promise((resolve, reject) =&gt; {
    MyAwesomePlugin.showToast(message, duration, (result) =&gt; {
      if (result.success) {
        resolve(result.data);
      } else {
        reject(new Error(result.msg || '调用失败'));
      }
    });
  });
}

export function getDeviceInfo() {
  const MyAwesomePlugin = uni.requireNativePlugin('MyAwesomePlugin');
  
  return new Promise((resolve, reject) =&gt; {
    MyAwesomePlugin.getDeviceInfo((result) =&gt; {
      if (result.success) {
        resolve(result.data);
      } else {
        reject(new Error(result.msg));
      }
    });
  });
}

六、在 uni-app 项目中使用插件

  1. HBuilderX 识别: 重启 HBuilderX,插件会自动被识别。
  2. 引用 JS 接口:
代码语言:javascript
复制
<template>
  <view>
    <button @click="handleClick">调用原生插件</button>
  </view>
</template>

<script>
// 引入封装好的 JS 接口
import { showToast, getDeviceInfo } from '@/nativeplugins/my-awesome-plugin/index.js'

export default {
  methods: {
    async handleClick() {
      try {
        // 调用 showToast
        await showToast('Hello from Native!', 1);
        
        // 调用 getDeviceInfo
        const info = await getDeviceInfo();
        console.log('设备信息:', info);
      } catch (error) {
        console.error('插件调用失败:', error);
      }
    }
  }
}
</script>

七、关键概念与最佳实践

  1. @UniJSMethod 注解:
    • 标记 Java 方法可被 JS 调用。
    • uiThread = true: 方法在 UI 线程执行,用于更新 UI (如 Toast, Dialog)。
    • callback: JS 调用时传入的回调函数,在原生方法执行完毕后调用它返回结果。
  2. 线程安全:
    • 默认在主线程执行。
    • 耗时操作(网络、数据库)必须在子线程中进行,避免阻塞。
    • 更新 UI 必须回到 UI 线程 (uiThread = true 或使用 runOnUiThread)。
  3. 权限处理:
    • package.jsonpermissions 中声明。
    • Android 6.0+ 需要运行时动态申请权限。可在插件中使用 mWXSDKInstance.getActivity() 获取 Activity 实例来申请。
  4. 调试:
    • Java 代码: 使用 Android Studio 打开 unpackage 目录下的原生工程进行调试。
    • 日志: 使用 Log.d() 输出日志,在 Android Studio 的 Logcat 中查看。
    • JS 代码: 使用 console.log
  5. 打包:
    • 在 HBuilderX 中正常打包 App。
    • 插件代码会被自动集成到原生工程中。
  6. 错误处理:
    • 原生代码中捕获异常,通过 callback 返回错误信息给 JS。
    • JS 端使用 try-catch.catch() 处理 Promise 错误。

八、总结

开发 uni-app 自定义 Android 插件的核心流程:

  1. 创建结构: nativeplugins/your-plugin/ 目录。
  2. 编写 package.json: 描述插件元信息。
  3. 编写 Java 类: 继承 UniModule,用 @UniJSMethod 标记方法。
  4. (可选) 编写 index.js: 提供友好的 JS API。
  5. 在项目中使用: 通过 uni.requireNativePlugin 或导入 index.js 调用。

自定义插件是扩展 uni-app 能力的关键,掌握它能让你的跨平台应用实现几乎任何原生功能。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • uni-app 自定义 Android 插件详解
    • 一、准备工作
    • 二、创建插件目录结构
    • 三、编写 package.json
    • 四、编写 Android 原生代码 (Java)
      • 1. 创建插件类 MyAwesomePlugin.java
      • 2. AndroidManifest.xml (可选)
      • 3. build.gradle (可选)
    • 五、编写 JS 接口 (index.js)
    • 六、在 uni-app 项目中使用插件
    • 七、关键概念与最佳实践
    • 八、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档