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

相关推荐
宇卿.3 分钟前
Java中的while和do...while循环
java·开发语言
等什么君!5 分钟前
JavaScript数据类型
开发语言·前端·javascript
爱敲代码的小杨.12 分钟前
【Python】2. 变量和数据类型
开发语言·python
kuai-23 分钟前
MacOS配置python环境
开发语言·python·macos
lly20240625 分钟前
CSS 尺寸 (Dimension)
开发语言
procoder33826 分钟前
[C/C++开发]链接动态库在不同操作系统上的行为
c语言·开发语言·c++
大道归简32 分钟前
2.点位管理开发(续)及设计思路——帝可得后台管理系统
java·开发语言·spring boot·spring·前端框架
L-李俊漩35 分钟前
python配置环境变量
开发语言·python·pip
_.Switch43 分钟前
Python深度学习:从神经网络到循环神经网络
开发语言·人工智能·python·rnn·深度学习·神经网络·机器学习
晓丶寒1 小时前
The legacy JS API is deprecated and will be removed in Dart Sass 2.0
开发语言·javascript·sass