Qt for android : libusb在android中使用

news2024/12/26 11:00:39

简介

如何在Qt for Android中使用libusb, 其实libusb的文档里面都写的很清楚, 这里只是稍微做下整理。

libusb

libusb github源码
libusb release的版本, 有编译好的静态

步骤

1. 下载libusb

libusb v1.0.027 源码包

2. 整理提取libusb android使用源码

从编译文件 libusb-1.0.27\android\jni\libusb.mk 直到 android所需要的源文件和头文件, 做整理,编译时再看缺少哪些,补齐。
如下是我整理的, config.h 来自libusb-1.0.27\android目录
在这里插入图片描述
下面是libusb目录包含的文件
在这里插入图片描述
os目录包含的文件
在这里插入图片描述

libusb.pri

CCFLAG += -fvisibility=hidden -pthread

INCLUDEPATH += $$PWD

SOURCES += \
    $$PWD/libusb/core.c \
    $$PWD/libusb/descriptor.c \
    $$PWD/libusb/hotplug.c \
    $$PWD/libusb/io.c \
    $$PWD/libusb/strerror.c \
    $$PWD/libusb/sync.c \
    $$PWD/os/events_posix.c \
    $$PWD/os/linux_netlink.c \
    $$PWD/os/linux_usbfs.c \
    $$PWD/os/threads_posix.c

HEADERS += \
    $$PWD/config.h \
    $$PWD/libusb/libusb.h \
    $$PWD/libusb/libusbi.h \
    $$PWD/libusb/version.h \
    $$PWD/libusb/version_nano.h \
    $$PWD/os/events_posix.h \
    $$PWD/os/linux_usbfs.h \
    $$PWD/os/threads_posix.h

3. 创建Qt for Android 并 加入libusb

参考 Qt for android 获取USB设备列表(二)JNI方式 获取,

  1. 工程文件.pro 添加libusb支持
    include ($$PWD/libusb/libusb.pri)
  2. java代码支持, 用于获取usb权限
package usb;

import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.io.IOException;

import android.content.pm.PackageManager;
import android.Manifest;
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 StorageManager storageManager = 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);
        // storageManager = (UsbManager)getSystemService(Context.STORAGE_SERVICE);

        Log.i(tag, "checkPermission: " + checkPermission());
        // getDeviceList();
    }

    private boolean checkPermission() {
        int readPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
        int writePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
    }



    public static boolean requestUSBPermission(String portName)
    {
        if (portName.isEmpty())
        {
            Log.i(tag, "port empty");
            return false;
        }
        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;
        // }


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

  1. 将libusb示例加入到Qt for android工程
    将 libusb-1.0.27\android\examples 目录下的 unrooted_android.c和unrooted_android.h拷贝到Qt 项目中, 添加

  2. Qt for Android通过JNI调用获取文件描述符并使用libusb打印usb设备信息

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "unrooted_android.h"
#include <QJniObject>
#include <QJniEnvironment>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(ui->btnRefreshPortNames, &QPushButton::clicked,
            this, [=]()
    {
        ui->cbPortNames->clear();
        ui->cbPortNames->addItems(getSerialPorts());
    });
    connect(ui->btnTest, &QPushButton::clicked,
            this, &MainWindow::test);

    emit ui->btnRefreshPortNames->clicked(); // 借势初始化
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::logger(const QString &text)
{
    ui->textEdit->append(text);
}

QList<QString> MainWindow::getSerialPorts()
{
    QList<QString> names;
#ifdef Q_OS_ANDROID
    QJniObject usbService = QJniObject::getStaticObjectField("android/content/Context",
                                                            "USB_SERVICE",
                                                            "Ljava/lang/String;");
    if (!usbService.isValid())
    {
        logger("fail to get usb service");
        return names;
    }


    QJniObject activity = QJniObject(QNativeInterface::QAndroidApplication::context());

    QJniObject usbManager = activity.callObjectMethod("getSystemService",
                                                      "(Ljava/lang/String;)Ljava/lang/Object;",
                                                      usbService.object<jstring>());
    if (!usbManager.isValid())
    {
        logger("fail to get usb manager");
        return names;
    }

    QJniObject usbDeviceListHashMap = usbManager.callObjectMethod("getDeviceList",
                                                           "()Ljava/util/HashMap;");
    QJniObject devListKeySet = usbDeviceListHashMap.callObjectMethod("keySet",
                                                       "()Ljava/util/Set;");
    QJniObject devListIter = devListKeySet.callObjectMethod("iterator",
                                                       "()Ljava/util/Iterator;");
    jint devListSize = usbDeviceListHashMap.callMethod<jint>("size", "()I");

    QJniObject usbDevObj;
    QJniObject usbDevObjIter;
    int vid = 0, pid = 0;
    QString devName;
    for (int i = 0; i < devListSize; ++i)
    {
        usbDevObjIter = devListIter.callObjectMethod("next",
                                            "()Ljava/lang/Object;");
        usbDevObj = usbDeviceListHashMap.callObjectMethod("get",
                                                   "(Ljava/lang/Object;)Ljava/lang/Object;",
                                                   usbDevObjIter.object());
        vid = usbDevObj.callMethod<jint>("getVendorId", "()I");
        pid = usbDevObj.callMethod<jint>("getProductId", "()I");
        devName = usbDevObj.callMethod<jstring>("getDeviceName", "()Ljava/lang/String;").toString();

        logger(QString("Name: %1, VID: %2, PID: %3").arg(devName).arg(vid).arg(pid));
        names.append(devName);
    }
#else
    for (QSerialPortInfo &info : QSerialPortInfo::availablePorts())
    {
        names.append(info.portName());
    }
#endif
    return names;
}


void MainWindow::test()
{
    QJniObject str = QJniObject::fromString(ui->cbPortNames->currentText());
    jboolean res = QJniObject::callStaticMethod<jboolean>(
                                       "usb/USBListActivity",
                                       "requestUSBPermission",
                                       "(Ljava/lang/String;)Z",
                                       str.object<jstring>());
    if (!res)
    {
        logger("permission denied");
        return;
    }
    QJniObject usbService = QJniObject::getStaticObjectField("android/content/Context",
                                                            "USB_SERVICE",
                                                            "Ljava/lang/String;");
    if (!usbService.isValid())
    {
        logger("fail to get usb service");
        return;
    }


    QJniObject activity = QJniObject(QNativeInterface::QAndroidApplication::context());

    QJniObject usbManager = activity.callObjectMethod("getSystemService",
                                                      "(Ljava/lang/String;)Ljava/lang/Object;",
                                                      usbService.object<jstring>());
    if (!usbManager.isValid())
    {
        logger("fail to get usb manager");
        return;
    }

    QJniObject usbDeviceListHashMap = usbManager.callObjectMethod("getDeviceList",
                                                           "()Ljava/util/HashMap;");
    QJniObject devListKeySet = usbDeviceListHashMap.callObjectMethod("keySet",
                                                       "()Ljava/util/Set;");
    QJniObject devListIter = devListKeySet.callObjectMethod("iterator",
                                                       "()Ljava/util/Iterator;");
    jint devListSize = usbDeviceListHashMap.callMethod<jint>("size", "()I");

    QJniObject usbDevObj;
    QJniObject usbDevObjIter;
    QString devName;
    QJniObject selectedUsbDevice;
    for (int i = 0; i < devListSize; ++i)
    {
        usbDevObjIter = devListIter.callObjectMethod("next",
                                            "()Ljava/lang/Object;");
        usbDevObj = usbDeviceListHashMap.callObjectMethod("get",
                                                   "(Ljava/lang/Object;)Ljava/lang/Object;",
                                                   usbDevObjIter.object());
        devName = usbDevObj.callMethod<jstring>("getDeviceName", "()Ljava/lang/String;").toString();


        if (devName != ui->cbPortNames->currentText())
        {
            continue;
        }
        selectedUsbDevice = usbDevObj;
        break;
    }
    if (!selectedUsbDevice.isValid())
    {
        logger("device not found");
        return;
    }

    QJniObject usbConnection = usbManager.callObjectMethod("openDevice",
                                                                   "(Landroid/hardware/usb/UsbDevice;)Landroid/hardware/usb/UsbDeviceConnection;",
                                                                    selectedUsbDevice.object());
    if (!usbConnection.isValid())
    {
        logger("fail to get usb connection");
        return;
    }
    jint fd = usbConnection.callMethod<jint>("getFileDescriptor", "()I");


    unrooted_usb_description(fd);

    logger("libusb test finished7");
}

4. 手机接入OTG和USB设备

我这里接的是USB转TTL线

5. 测试

打印信息是

D LibUsb : Dev (bus 1, device 4): 1A86 - 7523 speed: 12M
D LibUsb : Product: USB2.0-Serial
D LibUsb : Configuration:
D LibUsb : wTotalLength: 39
D LibUsb : bNumInterfaces: 1
D LibUsb : bConfigurationValue: 1
D LibUsb : iConfiguration: 0
D LibUsb : bmAttributes: 80h
D LibUsb : MaxPower: 48
D LibUsb : Interface:
D LibUsb : bInterfaceNumber: 0
D LibUsb : bAlternateSetting: 0
D LibUsb : bNumEndpoints: 3
D LibUsb : bInterfaceClass: 255
D LibUsb : bInterfaceSubClass: 1
D LibUsb : bInterfaceProtocol: 2
D LibUsb : iInterface: 0
D LibUsb : Endpoint:
D LibUsb : bEndpointAddress: 82h
D LibUsb : bmAttributes: 02h
D LibUsb : wMaxPacketSize: 32
D LibUsb : bInterval: 0
D LibUsb : bRefresh: 0
D LibUsb : bSynchAddress: 0
D LibUsb : Endpoint:
D LibUsb : bEndpointAddress: 02h
D LibUsb : bmAttributes: 02h
D LibUsb : wMaxPacketSize: 32
D LibUsb : bInterval: 0
D LibUsb : bRefresh: 0
D LibUsb : bSynchAddress: 0
D LibUsb : Endpoint:
D LibUsb : bEndpointAddress: 81h
D LibUsb : bmAttributes: 03h
D LibUsb : wMaxPacketSize: 8
D LibUsb : bInterval: 1
D LibUsb : bRefresh: 0
D LibUsb : bSynchAddress: 0

在这里插入图片描述

代码

基本代码都提供了, 没必要下载
libusb在Qt for android中的调用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1707131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么使用Stable diffusion中的models

Stable diffusion中的models Stable diffusion model也可以叫做checkpoint model&#xff0c;是预先训练好的Stable diffusion权重&#xff0c;用于生成特定风格的图像。模型生成的图像类型取决于训练图像。 如果训练数据中从未出现过猫的图像&#xff0c;模型就无法生成猫的…

【MySQL数据库】 MySQL主从复制

MySQL主从复制 MySQL主从复制主从复制与读写分离的意义主从数据库实现同步&#xff08;主从复制&#xff09;三台mysql服务器搭建主从复制&#xff0c;要求不可以用root帐号同步&#xff0c;要求第三台服务器在测试过1、2的主从复制之后进行主从复制配置 MySQL主从复制 主从复…

FastAPI - 组织模块2

FastAPI没有强制指定某种格式来组织项目结构&#xff0c;开发者可以根据自己喜好和项目需要来定制自己的项目结构。 https://fastapi.tiangolo.com/zh/tutorial/bigger-applications/ 在项目根目录创建python包routers&#xff0c;然后创建member.py文件 member.py文件内容 …

嘴尚绝卤味:健康美味新选择,开启味蕾新旅程!

在这个美食文化繁荣的时代&#xff0c;卤味作为传统小吃界的一颗璀璨明珠&#xff0c;一直深受大众的喜爱。而今天&#xff0c;我要向大家介绍一款不仅美味可口&#xff0c;更注重健康营养的卤味品牌——嘴尚绝卤味。它以其独特的制作工艺和丰富的口感&#xff0c;成为众多卤味…

滚珠花键在工业自动化领域中有什么优势?

滚珠花键是工业自动化设备中重要的传动系统之一&#xff0c;不仅在工业自动化系统中有着广泛的运用&#xff0c;还在机械制造领域、航空航天领域、工业汽车领域、工业机器人、高速铁路、新能源领域 等都得到广泛应用。由于具有高精度、高承载、耐磨损、传递扭矩大等特点&#x…

EE trade:如何理解做空黄金

理解做空黄金&#xff0c;其实就是理解卖空操作在黄金市场中的应用。卖空&#xff0c;或称为做空&#xff0c;是指投资者预测某资产(在这个例子中是黄金)的价格会下跌&#xff0c;因此采取的一种投资策略。 下面简要说明做空黄金的过程和相关概念&#xff1a; 借入黄金: 首先…

饲料粉碎混合机组:打造精细化养殖

饲料粉碎混合机组是畜牧业和养殖业中不可或缺的设备。它集饲料粉碎和混合于一体&#xff0c;可以高效地处理各种饲料原料&#xff0c;提高饲料的均匀度和营养价值。 具体来说&#xff0c;饲料粉碎混合机组的主要功能包括将饲料原料进行粉碎&#xff0c;增加其表面积和调质粒度…

计算机毕业设计python+spark天气预测 天气可视化 天气大数据 空气质量检测 空气质量分析 气象大数据 气象分析 大数据毕业设计 大数据毕设

摘 要 近些年大数据人工智能等技术发展迅速&#xff0c;我国工业正努力从“制造”迈向“智造”实现新跨越。神经网络(NeuronNetwork)是一种计算模型&#xff0c;通过大量数据的学习&#xff0c;来发现数据之间的模式和规律&#xff0c;模仿人脑神经元的工作方式。随着算力的提…

SEC突发:以太坊ETF大概率获批

美国证监会大概率批准以太坊现货ETF。 5月20日&#xff0c;据外媒CoinDesk报道&#xff0c;知情人士透露&#xff0c;美国SEC周一要求证券交易所更新以太坊现货ETF的19b-4备案文件。19b-4备案文件是一种表格&#xff0c;用于向SEC通报允许基金在交易所交易的规则变更。 三位消息…

SOLIDWORKS教育版代理商应该如何选择?

SOLIDWORKS作为目前流行的三维设计软件在工程设计&#xff0c;制造和建筑中有着广泛的应用前景。教育版SOLIDWORKS软件是学生及教育机构学习教学的理想平台。 下面介绍几个挑选SOLIDWORKS教育版代理的关键要素: 1、专业知识与经验&#xff1a;代理商应掌握SOLIDWORKS等软件的丰…

【前端笔记】记录一个能优化Echarts Geo JSON大小的网站

前端在使用Echarts等可视化图表库会不可避免遇到的问题&#xff0c;渲染地图的数据太大。 而有那么一个网站能给予这个问题一个解决方案&#xff1a;链接在此 使用方法很简单&#xff0c;首先先进入网站&#xff0c;如果进入了会是这个页面&#xff1a; 接着&#xff0c;选择一…

香橙派 AIPro开发板上手测评

前言 最近拿到了一个新玩具&#xff1a;香橙派 AIPro。一个只比银行卡大一点点的开发板能带给我们多少惊喜呢&#xff1f;接下来就跟我一起来体验下这块开发板的魅力。 一、硬件配置 CPU&#xff1a;配备了4核64位ARM处理器&#xff0c;其中默认预留1个给AI处理器使用 NPU&am…

Discourse 编辑没有办法显示更多的 JS 错误

Priority/Severity: High Platform: 3.3.0.beta3-dev UI bugs Description: 昨天升级的时到最新版本的时候就发现有这个错误&#xff0c;是 JS 的错误。 发了一个帖子到官方的网站上&#xff0c;官方说可能是插件的问题。 但是我们实在是没有安装什么插件呀&#xff1f; 官方…

大数据——Spark

1.Spark MLlib概述 MLlib是Spark的机器学习&#xff08;Machine Learning&#xff09;库&#xff0c;旨在简化机器学习的工程实践工作&#xff0c;并方便扩展到更大规模。 MLlib由一些通用的学习算法和工具组成&#xff0c;包括分类、回归、聚类、协同过滤、降维等&#xff0…

智能奶柜:重塑牛奶零售新篇章

智能奶柜&#xff1a;重塑牛奶零售新篇章 回忆往昔&#xff0c;孩童时代对送奶员每日拜访的期待&#xff0c;那熟悉的一幕——新鲜牛奶被细心放置于家门口的奶箱中&#xff0c;成为了许多人温馨的童年记忆。如今&#xff0c;尽管直接投递袋装牛奶的情景已不多见&#xff0c;但…

Android NDK系列(一)手动搭建Native Project

使用NDK编写的本地代码具有高性能等特性&#xff0c;在游戏、图形处理等领域有广泛应用&#xff0c;下面介绍如何手动搭建一个纯C版的Android项目&#xff0c;通过该项目可以理解Android的项目结构。 一、创建settings.gradle Android项目是基于Gradle构建的&#xff0c;首先得…

推荐系统学习笔记(四)--基于向量的召回

离散特征处理 离散特征&#xff1a;性别&#xff0c;国籍&#xff0c;英文单词&#xff0c;物品id&#xff0c;用户id 处理&#xff1a; 建立字典&#xff1a;eg&#xff1a;china 1 向量化&#xff1a;eg&#xff1a;one-hot /embedding&#xff08;低维稠密向量&#xf…

【Qt QML】Dialog组件

带有标准按钮和标题的弹出对话框&#xff0c;用于与用户进行短期交互。 这个描述指的是一个常见的用户界面元素&#xff0c;即一个临时弹出的窗口&#xff08;或对话框&#xff09;&#xff0c;它包含一个标题&#xff0c;显示对话框的用途或内容描述&#xff0c;以及一系列标…

用手机做客服的吐槽点客服亲们有同感吗

聊天宝手机版很好的解决了&#xff0c;客服手机快速回复客户的需求&#xff0c;不论微信&#xff0c;企业微信&#xff0c;千牛或其他手机APP回复客户&#xff0c;都可以用聊天宝APP实现图文一键发送&#xff0c;非常方便 前言 做客服工作&#xff0c;除了电脑上回复客户咨询&…

开源博客项目Blog .NET Core源码学习(23:App.Hosting项目结构分析-11)

本文学习并分析App.Hosting项目中后台管理页面的标签管理页面、轮播图维护页面。 标签管理页面 标签管理页面用于显示、检索、新建、编辑、删除标签数据&#xff0c;以便在前台页面的首页及文章专栏等页面显示标签数据。标签管理页面附带一新建及编辑页面&#xff0c;以支撑新…