当前位置: 首页 > backend >正文

Uniapp 串口通信原生插件开发指南(零基础版)

开发前的准备工作

首先,你需要安装以下工具:

  1. HBuilderX - 这是开发 Uniapp 应用和原生插件的主要工具
  2. Android Studio - 用于编写和编译 Android 原生代码
  3. Java JDK - 确保安装 JDK 8 或以上版本
  4. Android SDK - 通过 Android Studio 安装

创建插件项目

1. 在 HBuilderX 中创建原生插件项目
  1. 打开 HBuilderX,选择菜单:文件 -> 新建 -> 原生插件
  2. 填写插件信息:
    • 插件名称:UniSerialPort
    • 插件ID:UniSerialPort
    • 选择"仅Android平台"
  3. 点击"创建",项目将被创建在 HBuilderX 的项目目录中
2. 导入项目到 Android Studio
  1. 打开 Android Studio
  2. 选择"Open an existing Android Studio project"
  3. 导航到 HBuilderX 创建的插件项目目录,选择 android 文件夹
  4. 等待 Android Studio 导入并构建项目

实现串口通信功能

1. 添加 Android 串口库

首先,我们需要添加 Android 串口通信库到项目中:

  1. 在 Android Studio 中,打开 android/build.gradle 文件
  2. dependencies 块中添加以下依赖:
dependencies {implementation 'com.github.licheedev:AndroidSerialPort:1.3.1'
}
2. 创建串口管理类

在 Android Studio 中,创建以下类文件:

  1. SerialPortManager.java - 负责串口的打开、关闭、读写操作
// SerialPortManager.java
package com.uniserialport;import com.licheedev.serialworker.core.SerialConfig;
import com.licheedev.serialworker.core.SerialWorker;
import com.licheedev.serialworker.worker.ByteDataListener;
import com.licheedev.serialworker.worker.Worker;
import java.util.HashMap;
import java.util.Map;public class SerialPortManager {private static Map<String, Worker> workers = new HashMap<>();// 打开串口public static Worker openSerialPort(String path, int baudrate, int dataBits, int stopBits, String parity, int flowControl, int delay) throws Exception {if (workers.containsKey(path)) {closeSerialPort(path);}// 配置串口参数SerialConfig config = new SerialConfig(path, baudrate);config.setDataBits(dataBits);config.setStopBits(stopBits);// 设置校验位switch (parity.toLowerCase()) {case "odd":config.setParity(android_serialport_api.SerialPort.PARITY_ODD);break;case "even":config.setParity(android_serialport_api.SerialPort.PARITY_EVEN);break;default:config.setParity(android_serialport_api.SerialPort.PARITY_NONE);}// 设置流控config.setFlowControl(flowControl);// 创建串口WorkerWorker worker = new SerialWorker(config);worker.setReceiveDelay(delay); // 设置粘包处理延迟workers.put(path, worker);return worker;}// 关闭串口public static void closeSerialPort(String path) {Worker worker = workers.get(path);if (worker != null) {worker.release();workers.remove(path);}}// 发送数据public static void sendData(String path, byte[] data) throws Exception {Worker worker = workers.get(path);if (worker != null) {worker.send(data);}}// 开始监听数据public static void startListening(String path, DataCallback callback) {Worker worker = workers.get(path);if (worker != null) {worker.setDataListener(new ByteDataListener() {@Overridepublic void onDataReceived(byte[] data) {if (callback != null) {callback.onDataReceived(data);}}});}}// 数据回调接口public interface DataCallback {void onDataReceived(byte[] data);}
}
3. 创建 JS 接口模块

创建 SerialPortModule.java 文件,这是插件与 JS 交互的桥梁:

// SerialPortModule.java
package com.uniserialport;import com.alibaba.fastjson.JSONObject;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;public class SerialPortModule extends UniModule {// 打开串口@UniJSMethod(uiThread = false)public void open(Map<String, Object> options, UniJSCallback callback) {try {String path = (String) options.get("path");int baudrate = (Integer) options.get("baudrate");int dataBits = (Integer) options.getOrDefault("dataBits", 8);int stopBits = (Integer) options.getOrDefault("stopBits", 1);String parity = (String) options.getOrDefault("parity", "none");int flowControl = (Integer) options.getOrDefault("flowControl", 0);int delay = (Integer) options.getOrDefault("delay", 20);SerialPortManager.openSerialPort(path, baudrate, dataBits, stopBits, parity, flowControl, delay);callback.invokeSuccess();} catch (Exception e) {callback.invokeError(e.getMessage());}}// 关闭串口@UniJSMethod(uiThread = false)public void close(String path, UniJSCallback callback) {try {SerialPortManager.closeSerialPort(path);callback.invokeSuccess();} catch (Exception e) {callback.invokeError(e.getMessage());}}// 发送数据@UniJSMethod(uiThread = false)public void send(Map<String, Object> options, UniJSCallback callback) {try {String path = (String) options.get("path");String data = (String) options.get("data");byte[] bytes = data.getBytes("UTF-8");SerialPortManager.sendData(path, bytes);callback.invokeSuccess();} catch (Exception e) {callback.invokeError(e.getMessage());}}// 开始监听数据@UniJSMethod(uiThread = false)public void startListening(String path, final UniJSCallback callback) {try {SerialPortManager.startListening(path, new SerialPortManager.DataCallback() {@Overridepublic void onDataReceived(byte[] data) {try {String hexData = bytesToHexString(data);JSONObject result = new JSONObject();result.put("data", hexData);callback.invoke(result);} catch (Exception e) {e.printStackTrace();}}});callback.invokeSuccess();} catch (Exception e) {callback.invokeError(e.getMessage());}}// 工具方法:字节数组转16进制字符串private String bytesToHexString(byte[] bytes) {StringBuilder sb = new StringBuilder();for (byte b : bytes) {String hex = String.format("%02X", b);sb.append(hex);}return sb.toString();}
}
4. 配置插件信息

编辑 package.json 文件,配置插件信息:

{"name": "UniSerialPort","id": "UniSerialPort","description": "Uniapp 串口通信插件","version": "1.0.0","platforms": ["android"],"modules": {"SerialPort": {"class": "com.uniserialport.SerialPortModule","methods": ["open", "close", "send", "startListening"]}},"android": {"permissions": ["<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>","<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>","<uses-permission android:name=\"android.permission.INTERNET\"/>"]}
}

打包和使用插件

1. 打包插件
  1. 在 HBuilderX 中,右键点击插件项目
  2. 选择"原生插件" -> “制作本地插件”
  3. 选择 Android 平台
  4. 点击"制作"按钮,HBuilderX 将自动调用 Android Studio 编译插件
  5. 编译完成后,插件将被打包到 nativeplugins/UniSerialPort/dist 目录
2. 在 Uniapp 项目中使用插件
  1. 在你的 Uniapp 项目中,创建 nativeplugins/UniSerialPort 目录
  2. 将刚才打包好的插件文件复制到该目录
  3. manifest.json 中配置插件:
{"app-plus": {"nvueStyleCompiler": "uni-app","usingComponents": true,"nativePlugins": {"UniSerialPort": {"version": "1.0.0","provider": "local"}}}
}
3. 在 JS 代码中调用插件
// 引入插件
const serialPort = uni.requireNativePlugin('UniSerialPort');// 打开串口
serialPort.open({path: '/dev/ttyS1',  // 串口设备路径baudrate: 9600,      // 波特率dataBits: 8,         // 数据位stopBits: 1,         // 停止位parity: 'none',      // 校验位:none, odd, evenflowControl: 0,      // 流控delay: 50            // 粘包处理延迟时间(ms)
}, (res) => {if (res.code === 0) {console.log('串口打开成功');// 开始监听数据startListening();} else {console.error('串口打开失败:', res.message);}
});// 监听数据
function startListening() {serialPort.startListening('/dev/ttyS1', (res) => {console.log('收到数据:', res.data);// 处理接收到的16进制数据});
}// 发送数据
function sendData() {serialPort.send({path: '/dev/ttyS1',data: 'Hello, Serial Port!'}, (res) => {if (res.code === 0) {console.log('数据发送成功');} else {console.error('数据发送失败:', res.message);}});
}// 关闭串口
function closeSerialPort() {serialPort.close('/dev/ttyS1', (res) => {if (res.code === 0) {console.log('串口关闭成功');} else {console.error('串口关闭失败:', res.message);}});
}

常见问题和解决方案

  1. 找不到串口设备

    • 确认设备上串口的实际路径
    • 检查应用是否有访问串口的权限
  2. 无法打开串口

    • 检查串口是否被其他应用占用
    • 确认串口参数配置正确
  3. 接收数据不完整

    • 调整粘包处理的延迟时间
    • 检查数据解析逻辑
  4. 应用崩溃

    • 检查 AndroidManifest.xml 中是否添加了必要的权限
    • 确保所有的串口操作都在 try-catch 块中进行

通过以上步骤,你就可以完成一个功能完整的 Uniapp 串口通信原生插件。即使你没有安卓原生开发经验,按照这个指南一步步操作,也能够成功实现这个插件。

http://www.xdnf.cn/news/9040.html

相关文章:

  • LSTM+Transformer混合模型架构文档
  • SWOT分析:MCP(Model Context Protocol)与传统编程解决方案
  • 精益数据分析(85/126):营收阶段的核心指标与盈利模型优化——从数据到商业决策的落地
  • Prompt Tuning:优化提示调优全攻略
  • 前端内容黑白处理、轮播图、奇妙的头像特效
  • Android开发namespace奇葩bug
  • 鸿蒙OSUniApp 开发实时天气查询应用 —— 鸿蒙生态下的跨端实践#三方框架 #Uniapp
  • Git 初次推送远程仓库
  • NL2SQL代表,Vanna
  • 【笔记】解决启动Anaconda Toolbox报错ModuleNotFoundError: No module named ‘pysqlite2‘
  • 从万有引力到深度学习,认识模型思维
  • ADS学习笔记(五) 谐波平衡仿真
  • 身份认证: JWT和Session是什么?
  • 深入解析 BlockingQueue:并发编程面试中的高频考点!
  • SDL2常用函数:SDL_RendererSDL_CreateRendererSDL_RenderCopySDL_RenderPresent
  • 数据库工程师备考
  • 第三届京麒CTF Web
  • ClickHouse性能优化技术深度解析与实践指南
  • (4)-Fiddler抓包-会话面板和HTTP会话数据操作
  • 多模态大语言模型arxiv论文略读(九十三)
  • Odoo 自动化规则全面深度解析
  • 探秘谷歌Gemini:开启人工智能新纪元
  • 基于树莓派的贪吃蛇游戏机
  • 【科研绘图系列】R语言绘制气泡图(bubble plot)
  • 噪声建模在一小时:最小化准备工作的自监督低光RAW图像去噪
  • ArcGIS 与 HEC-RAS 协同:流域水文分析与洪水模拟全流程
  • 数字展厅建设需融合创意设计与实用功能,打造多维用户体验!
  • 动态规划(7):背包问题
  • 解决 docker pull镜像失败
  • DEC Global:技术赋能如何重塑投资者决策模式?