当前位置: 首页 > 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
  • 【node学习】协程
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • iOS 系统授权开发
  • Javascripit类型转换比较那点事儿,双等号(==)
  • Java新版本的开发已正式进入轨道,版本号18.3
  • JS实现简单的MVC模式开发小游戏
  • overflow: hidden IE7无效
  • PHP那些事儿
  • Sass 快速入门教程
  • SOFAMosn配置模型
  • Yii源码解读-服务定位器(Service Locator)
  • 百度小程序遇到的问题
  • 初识MongoDB分片
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 理清楚Vue的结构
  • 前端工程化(Gulp、Webpack)-webpack
  • 前言-如何学习区块链
  • 微信小程序设置上一页数据
  • 正则学习笔记
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • ​flutter 代码混淆
  • %check_box% in rails :coditions={:has_many , :through}
  • (2)(2.10) LTM telemetry
  • (C++17) optional的使用
  • (第一天)包装对象、作用域、创建对象
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .Net Core和.Net Standard直观理解
  • .net操作Excel出错解决