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,导入或者自定义相关使用字段(我目前使用的)
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";
}

或(我暂时使用的方法)

java 复制代码
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

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

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;
    }

    @Override
    public 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 乱码问题

相关推荐
吾疾唯君医13 小时前
记录GoLang创建文件并写入文件的中文乱码错误!
开发语言·后端·golang
小年糕是糕手14 小时前
【数据结构】算法复杂度
c语言·开发语言·数据结构·学习·算法·leetcode·排序算法
JAVA学习通14 小时前
微服务项目->在线oj系统(Java-Spring)--C端用户(超详细)
java·开发语言·spring
数据知道14 小时前
Go基础:Go语言ORM框架GORM详解
开发语言·jvm·后端·golang·go语言
计算机毕业设计小帅14 小时前
【2026计算机毕业设计】基于jsp的毕业论文管理系统
java·开发语言·毕业设计·课程设计
明天会有多晴朗14 小时前
深度剖析 C++ 之内存管理篇
c语言·开发语言·c++
BD_Marathon14 小时前
【MySQL】函数
android·数据库·mysql
potato_may14 小时前
C语言第3讲:分支和循环(上)—— 程序的“决策”与“重复”之旅
c语言·开发语言
kalvin_y_liu14 小时前
【MES架构师与C#高级工程师(设备控制方向)两大职业路径的技术】
开发语言·职场和发展·c#·mes
xxxxxxllllllshi14 小时前
Java 代理模式深度解析:从静态到动态,从原理到实战
java·开发语言·笔记·算法·代理模式