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

Qt for android 串口库使用

简介

由于Qt for android并没有提供android的串口执行方案,基于需要又懒得自己去造轮子, 使用开源的
usb-serial-for-android 库进行串口访问读写。
如果有自己的需要和库不满足的点,可以查看库的底层调用的Android相关API + C/C++ 串口库 + 对应串口设备的开源驱动代码进行改造。

Note: 由于我没有系统的学习过Java、Android, 如果涉及到认知冲突, 请信自己[礼貌不失尴尬的微笑]。

步骤

1. 下载 usb-serial-for-android release版本

usb-serial-for-android_v3.7.2.zip

2. 解压缩

解压缩之后目录呈现如下图, 移植的代码在usbSerialForAndroid目录下

在这里插入图片描述

3. 加入Qt for Android项目

将usbSerialForAndroid/src/main/java/com目录整个拷入到Qt for
android生成的Android目录下

在这里插入图片描述

Qt for android 工程目录下的android源码目录

在这里插入图片描述

4. 设置Qt Creator显化java代码

DISTFILES +=
android/src/com/hoho/android/usbserial/driver/.java \
android/src/com/hoho/android/usbserial/util/
.java
在这里插入图片描述

5. 编译和解决报错

在这里插入图片描述

错误1 BuildConfig不存在

BuildConfig 是 gradle自动生成的,移植的时候并没有一起移植过来, 所以有几种方案:

1) 注释掉掉BuildConfig相关信息代码
2) Qt for android本身的项目也生成BuildConfig, 将 引用包由原先

import com.hoho.android.usbserial.BuildConfig; 改成
import org.qtproject.example.BuildConfig;

3) 创建BuildConfig.java,导入或者自定义相关使用字段(我目前使用的)
package com.hoho.android.usbserial;
public final class BuildConfig {public static final boolean DEBUG = false;public static final String APPLICATION_ID = "org.qtproject.example";public static final String BUILD_TYPE = "release";public static final int VERSION_CODE = 1;public static final String VERSION_NAME = "1.0";
}

或(我暂时使用的方法)

package com.hoho.android.usbserial;public final class BuildConfig {public static final boolean DEBUG = org.qtproject.example.BuildConfig.DEBUG;public static final String APPLICATION_ID = org.qtproject.example.BuildConfig.APPLICATION_ID;public static final String BUILD_TYPE = org.qtproject.example.BuildConfig.BUILD_TYPE;public static final int VERSION_CODE = org.qtproject.example.BuildConfig.VERSION_CODE;public static final String VERSION_NAME = org.qtproject.example.BuildConfig.VERSION_NAME;
}
4) 定义包自身的gradle, 这个我暂时没有去Study和尝试, 懂得朋友开始自己的表演。(推荐)

6. 代码

mainwindows.cpp

void MainWindow::test()
{QJniObject str = QJniObject::fromString(ui->cbPortNames->currentText());jboolean res = QJniObject::callStaticMethod<jboolean>("usb/USBListActivity","test","(Ljava/lang/String;)Z",str.object<jstring>());if (0 == res){logger("test failed");}else{logger("test succeed");}
}

usb.USBListActivity.java

package usb;import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.io.IOException;import android.content.Intent;
import android.app.PendingIntent;
import android.util.Log;
import android.os.Bundle;
import android.content.Context;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;import com.hoho.android.usbserial.driver.Ch34xSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;public class USBListActivity extends org.qtproject.qt.android.bindings.QtActivity
{private static USBListActivity instance = null;private static UsbManager usbManager = null;private static String tag = "MainClass";private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";public USBListActivity(){instance = this;}@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);usbManager = (UsbManager)getSystemService(Context.USB_SERVICE);// getDeviceList();}public static boolean test(String portName){System.out.println("<-------------->test: " + portName);if (portName.isEmpty()){Log.i(tag, "port empty");return false;}System.out.println("<-------------->test1: " + portName);HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();UsbDevice device = null;for (Map.Entry<String, UsbDevice> entry : deviceList.entrySet()){if (portName.equals(entry.getKey())){device = entry.getValue();break;}}if (device == null){Log.i(tag, "device not exists");return false;}if (!usbManager.hasPermission(device)){Intent permissionIntent = new Intent(ACTION_USB_PERMISSION);PendingIntent pendingIntent = PendingIntent.getBroadcast(instance,0,permissionIntent,PendingIntent.FLAG_UPDATE_CURRENT);usbManager.requestPermission(device, pendingIntent);if (!usbManager.hasPermission(device)){Log.i(tag, "permission denied");return false;}}UsbDeviceConnection deviceConnection = usbManager.openDevice(device);if (null == deviceConnection){Log.i(tag, "fail to open device");return false;}Ch34xSerialDriver ch340Device = new Ch34xSerialDriver(device);UsbSerialPort serialport = ch340Device.getPorts().get(0);/* 打开串口 */try {serialport.open(deviceConnection);} catch (IOException ignored) {Log.i(tag, "fail to open serial port");return false;}/* 设置串口参数 */try {serialport.setParameters(115200, 8, 1, UsbSerialPort.PARITY_NONE);}catch (IOException ignored) {Log.i(tag, "fail to set parameters");}/* 向串口发送数据 */try {serialport.write("Hello, world!".getBytes(), 1000);} catch (IOException e) {System.out.println("catched write error expected");}/* 关闭串口 */try {serialport.close();} catch (IOException ignored) {}return true;}public void getDeviceList(){HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();System.out.println("------------------------->GetDeviceList<-------------------------");deviceList.forEach((key, value) -> {System.out.println("------------------------->" + key + "<-------------------------");System.out.println(value);System.out.println("<-------------------------" + key + "------------------------->");});System.out.println("<-------------------------GetDeviceList------------------------->");}
}

7. 连线

  1. PC 和 手机端各接一个USB转TTL线
    RX<->TX
    TX<->RX
    GND<->GND

8. 运行

第一次申请权限时同意了但还是判定失败, 后续解决,第二次执行test时成功…

手机端显示
在这里插入图片描述
PC端串口打印
在这里插入图片描述


帮助文档

Qt for Android

Qt for android 文档(thinkinginqt.com)
Qt for android 官方文档(Qt6.2LTS)
Qt Project to Manifest Configuration

Android

UsbManager(apiref.com)
UsbManager android-doc.com
UsbManager(matools.com)
Activity 生命周期概念

其他文章

Qt for android 获取USB设备列表(一)Java方式 获取
Qt for android 获取USB设备列表(二)JNI方式 获取
Qt for Android 乱码问题

相关文章:

  • 国产32位MCU的发展与机遇
  • 【数组】Leetcode 57. 插入区间【中等】
  • 【计算机视觉(2)】
  • 【LeetCode算法】第83题:删除排序链表中的重复元素
  • 一文搞透常见的Python编码陷阱(上)(分析+案例)
  • 如何判断一个对象是否已经被回收?
  • C++ 常用UI库
  • 如何消除*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS。如何消除函数未使用的警告
  • HTTPS能否避免流量劫持?如何实现HTTPS
  • 正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-24.1,2 SPI驱动实验-SPI协议介绍
  • 【软件测试】bug篇|软件测试的生命周期|描述bug的要素|bug的级别|bug的生命周期|高频面试题:与开发产⽣争执怎么处理
  • SSL VPN
  • C++系列-定位new表达式(placement-new)
  • 一个程序员的牢狱生涯(40)好事
  • 谈谈BlueStore的BitmapAllocator
  • Android框架之Volley
  • IndexedDB
  • JavaScript 奇技淫巧
  • javascript从右向左截取指定位数字符的3种方法
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • React 快速上手 - 07 前端路由 react-router
  • Vue ES6 Jade Scss Webpack Gulp
  • XForms - 更强大的Form
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 前端自动化解决方案
  • 译自由幺半群
  • ​比特币大跌的 2 个原因
  • # linux 中使用 visudo 命令,怎么保存退出?
  • #pragma预处理命令
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (33)STM32——485实验笔记
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (附源码)计算机毕业设计高校学生选课系统
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (算法)Game
  • .jks文件(JAVA KeyStore)
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .Net Core 微服务之Consul(三)-KV存储分布式锁
  • .NET Core 中插件式开发实现
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .net6+aspose.words导出word并转pdf
  • .NET中的Exception处理(C#)
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • @RequestBody与@ModelAttribute
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [1204 寻找子串位置] 解题报告
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [BZOJ 1040] 骑士
  • [C#] 如何调用Python脚本程序
  • [c#基础]DataTable的Select方法
  • [C++]类和对象(中)
  • [CF226E]Noble Knight's Path
  • [C进阶] 数据在内存中的存储——浮点型篇