Qt on Android 蓝牙开发
版权声明:本文为MULTIBEANS ORG研发跟随文章,未经MLT ORG允许不得转载。
最近做项目,需要开发安卓应用,实现串口的收发,目测CH340G在安卓手机上非常麻烦,而且驱动都是Java版本的, 就没选择,博主在大二的时候学习过Java SE基本的语法,写过一些小程序就放弃了Java的道路。最后选择了蓝牙无线透传模块,实现串口通信。现在Qt跨平台支持安卓,是在是令人欣喜。在网上找资料,用Qt on Android做蓝牙驱动的几乎没有,也没有相关例程,所以准备撰写此文,献给广大嵌入式程序员们
2018/6/27更新:
增加Java版本的蓝牙通信,文章地址:https://www.cnblogs.com/sigma0/p/9234478.html
一、软硬件平台
1.1 硬件平台
1. 蓝牙:HC-05,(淘宝上有卖),它的接口就是跟串口一样的,我们用到了TX,RX,GND,VCC四个引脚。跟下位机或者用CH340G TTL转USB模块接到PC机上。蓝牙工作在串口模式可以通过AT指令调节。具体参考蓝牙配套的说明文档,最主要的就是请将蓝牙设定为从机模式,否则安卓手机搜寻链接不上。
2.安卓手机:我这里测试用了2台安卓手机,一台是小米4移动版,安卓版本6.0.1;一台是MOTO MT887,安卓版本4.1.2。
1.2 软件平台
本项目Qt版本是5.7,系统是windows 8.1 x64
二、软件基本介绍
因为第一次做蓝牙,就做一个非常简单的雏形,实现蓝牙状态检测、蓝牙的开关、蓝牙的扫描和蓝牙配对链接,并且能像串口助手一样完成数据收发。如图,就是本一开始做的最简单的软件界面,本软件基于QWidget控件制作,当然你可以选择mainwinodw,更可以自己定义类。
软件界面
我不用介绍每个部位是什么了,都会明白吧?蓝牙打开后通过扫描,会将蓝牙的MAC地址还有名字显示在List中,我们双击List列表中的蓝牙,就会进入actived信号连接的槽函数,执行蓝牙的配对连接。建立连接之后,就类似串口一样可以进行数据通信了。另外,点击send按钮之后会发送一堆字符串。
三、 蓝牙开发
3.1 项目文件准备
需要用到蓝牙就需要在.pro文件中引入库,我没有用Qt quick,用的是纯C++写的代码,你需要在.pro文件中加入这句话:
- QT += bluetooth
- #include <QtBluetooth/qbluetoothglobal.h>
- #include <QtBluetooth/qbluetoothlocaldevice.h>
- #include <qbluetoothaddress.h>
- #include <qbluetoothdevicediscoveryagent.h>
- #include <qbluetoothlocaldevice.h>
- #include <qbluetoothsocket.h>
一会儿介绍每个都是做什么的。
- QBluetoothDeviceDiscoveryAgent *discoveryAgent;
- QBluetoothLocalDevice *localDevice;
- QBluetoothSocket *socket;
第一个discoveryAgent是用来对周围蓝牙进行搜寻,localDevice顾名思义,就是对本地设备进行操作,比如进行设备的打开,设备的关闭等等。socket就是用来进行蓝牙配对链接和数据传输的。这里要用到这三个。
3.2 蓝牙开关和可见性设定
- localDevice = new QBluetoothLocalDevice();
1) 蓝牙开关
- if( localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff ) {
- ui->pushButton_openBluetooth->setEnabled(true);
- ui->pushButton_closeDevice->setEnabled(false);
- }else {
- ui->pushButton_openBluetooth->setEnabled(false);
- ui->pushButton_closeDevice->setEnabled(true);
- }
在构造函数中
那么,我们如何来对蓝牙进行打开和关闭呢?我在open按钮和close按钮的槽函数中对蓝牙进行开关操作。
open按钮的槽函数:
- void Widget::on_pushButton_openBluetooth_clicked()
- {
- localDevice->powerOn();
- ui->pushButton_closeDevice->setEnabled(true);
- ui->pushButton_openBluetooth->setEnabled(false);
- ui->pushButton_scan->setEnabled(true);
- }
localDevice->powerOn();方法调用打开本地的蓝牙设备,然后你可以根据自己的喜好完成对按钮的使能和禁止操作。
- void Widget::on_pushButton_closeDevice_clicked()
- {
- localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
- ui->pushButton_closeDevice->setEnabled(false);
- ui->pushButton_openBluetooth->setEnabled(true);
- ui->pushButton_scan->setEnabled(false);
- }
close设备和我们的open设备的方法在形式上不一样,我还以为他们两个是对称的,但是事实上不是,只能用这样的方法对蓝牙进行关闭。
2) 蓝牙可见性
- if( localDevice->hostMode() == QBluetoothLocalDevice::HostDiscoverable ) {
- ui->checkBox_discoverable->setChecked(true);
- }else {
- ui->checkBox_discoverable->setChecked(false);
- }
我的设计中,蓝牙可见如界面图用的是checkBox空间完成的,通过setChecked()方法,一开机对是否可见进行。
- localDevice->setHostMode( QBluetoothLocalDevice::HostDiscoverable);
同理,不可见你也能想到对吧。
3.3 蓝牙设备的查找
- connect(discoveryAgent,
- SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
- this,
- SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo))
- );
在我们发现设备的时候,这个deviceDiscovered信号被触发,进入到addBlueToothDevicesToList的函数中。在上面的软件界面,我们的最上面蓝牙列表下的控件是ListIte控件,这里做一个槽函数,将发现的设备打印到这个列表中列出来。
- void Widget::addBlueToothDevicesToList( const QBluetoothDeviceInfo &info )
- {
- QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
- QList<QListWidgetItem *> items = ui->list->findItems(label, Qt::MatchExactly);
- if (items.empty()) {
- QListWidgetItem *item = new QListWidgetItem(label);
- QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
- if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired )
- item->setTextColor(QColor(Qt::green));
- else
- item->setTextColor(QColor(Qt::black));
- ui->list->addItem(item);
- }
- }
这里给出这个函数,每一句话十分的好理解,这里增加点选操作,当点击listItem中的项目的时候,背景颜色会翻转,双击这个项目就会和这个蓝牙设备建立连接,这里有个actived槽函数,在这个槽函数里面就会进行蓝牙的链接。下一章节写这个如何连接。
3.4 蓝牙设备的建立连接
在Linux下你用一个命令uuidgen -t可以生成一个UUID值;在Windows下则执行命令uuidgen 。UUID看起来就像如下的这个形式:2d266186-01fb-47c2-8d9f-10b8ec891363。当使用生成的UUID去创建一个UUID对象,你可以去掉连字符。
- static const QLatin1String serviceUuid("00001101-0000-1000-8000-00805F9B34FB");
- socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
- void Widget::itemActivated(QListWidgetItem *item)
- {
- QString text = item->text();
- int index = text.indexOf(' ');
- if (index == -)
- return;
- QBluetoothAddress address(text.left(index));
- QString name(text.mid(index + ));
- qDebug() << "You has choice the bluetooth address is " << address;
- qDebug() << "The device is connneting.... ";
- QMessageBox::information(this,tr("Info"),tr("The device is connecting..."));
- socket->connectToService(address, QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);
- }
我们通过对字符串的处理,将得到address信息。通过socket->connectToService(....),把地址,Uuid,和蓝牙模式传递进去,当执行完这句话的时候,安卓手机开始和你
选择的蓝牙设备进行链接。
同样在socket中也提供了丰富的槽函数,比如成功建立连接信号,成功断开信号,这里在槽函数中可以做一些例子,这里给出例子:
- connect(socket,
- SIGNAL(connected()),
- this,
- SLOT(bluetoothConnectedEvent())
- );
- connect(socket,
- SIGNAL(disconnected()),
- this,
- SLOT(bluetoothDisconnectedEvent())
- );
- void Widget::bluetoothConnectedEvent()
- {
// 2017/10/8 更新一下,请在这里插入关闭蓝牙查找服务,否则数据会断。
// 具体语句是什么我忘记了,反正使用discoveryAgent的一个什么close,或者stop的方法- qDebug() << "The android device has been connected successfully!";
- QMessageBox::information(this,tr("Info"),tr("successful connection!"));
- }
- void Widget::bluetoothDisconnectedEvent()
- {
- qDebug() << "The android device has been disconnected successfully!";
- QMessageBox::information(this,tr("Info"),tr("successful disconnection!"));
- }
最后,还有一个断开连接函数。通过断开连接按钮的槽函数实现。
- void Widget::on_pushButton_disconnect_clicked()
- {
- socket->disconnectFromService();
- }
3.5 发送和接收数据
- void Widget::on_pushButton_send_clicked()
- {
- QByteArray arrayData;
- QString s("Hello Windows!!!\nThis message is sended via bluetooth of android device!\n");
- arrayData = s.toUtf8();
- socket->write(arrayData);
- }
这里通过socket->write函数,完成发送。发送之后,上位机,我用的串口助手会显示该信息。
那么接收数据呢?
- connect(socket,
- SIGNAL(readyRead()),
- this,
- SLOT(readBluetoothDataEvent())
- );
readyRead()信号触发,跳进readBluetoothDataEvent中。
- void Widget::readBluetoothDataEvent()
- {
- QByteArray line = socket->readAll();
- QString strData = line.toHex();
- comStr.append(strData);
- qDebug() <<"rec data is: "<< comStr;
- qDebug() <<"The comStr length is: " << comStr.length();
- if(comStr.length() >= ) {
- ui->textBrowser_info->append(comStr + "\n");
- comStr.clear();
- }
- }
我这里是这样处理的,当然了,你有你自己的处理方法,意思就是那么个意思。
四、结束语
Qt on Android 蓝牙开发的更多相关文章
- Qt on android 蓝牙开发(控制小车)
因为要做一个用蓝牙控制小车的app,就用着QT搞了下,网上关于QT蓝牙开发的资料比较少,我在这里记录下过程希望对看到了人有所帮助 首先在项目文件里添加 QT += bluetooth 这样就可以用QT ...
- Android 蓝牙开发(整理大全)
Android蓝牙开发 鉴于国内Android蓝牙开发的例子很少,以及蓝牙开发也比较少用到,所以找的资料不是很全. (一): 由于Android蓝牙的通信都需要用到UUID,如果由手机发起搜索,当搜索 ...
- Android蓝牙开发
Android蓝牙开发 近期做蓝牙小车,须要Android端来控制小车的运动.以此文记录开发过程. 使用HC-06无线蓝牙串口透传模块.对于其它的蓝牙设备本文相同适用. 蓝牙开发的流程: 获取本地蓝牙 ...
- Android蓝牙开发教程(三)——蓝牙设备相互通讯
在上一篇中已经介绍如何连接我们搜索到的蓝牙设备,如果你还没阅读过,建议先看看上一篇文章Android蓝牙开发教程(二)——连接蓝牙设备 在上一篇文章中,无论是自动连接还是被动连接,连接成功后,都是将获 ...
- Android 蓝牙开发(3)——蓝牙的详细介绍
前面的两篇文章,主要是在 Android 官网关于蓝牙介绍的基础上加上自己的理解完成的.主要针对的是 Android 开发中的一些 API 的使用. 第一篇文章 Android 蓝牙开发(1) 主要是 ...
- Qt on Android 蓝牙通信开发
版权声明:本文为MULTIBEANS ORG研发跟随文章,未经MLT ORG允许不得转载. 最近做项目,需要开发安卓应用,实现串口的收发,目测CH340G在安卓手机上非常麻烦,而且驱动都是Java版本 ...
- 【转】android蓝牙开发---与蓝牙模块进行通信--不错
原文网址:http://www.cnblogs.com/wenjiang/p/3200138.html 近半个月来一直在搞android蓝牙这方面,主要是项目需要与蓝牙模块进行通信.开头的进展很顺利, ...
- Android 蓝牙开发
今天给大家带来蓝牙开发的基础,主要展示的是程序搜到蓝牙会通过list展示出来,并实时排序,远近与信号强弱 首先我们要有次jar包 watermark/2/text/aHR0cDovL2Jsb2cuY3 ...
- android蓝牙开发---与蓝牙模块进行通信
近半个月来一直在搞android蓝牙这方面,主要是项目需要与蓝牙模块进行通信.开头的进展很顺利,但因为蓝牙模块不在我这里,所以只能用手机测试.一开头就发现手机的蓝牙不能用,为了证明这点,我刷了四次不同 ...
随机推荐
- C++ 环形缓冲区的实现
参考文章:http://blog.csdn.net/linyt/article/details/53355355 本文参考linux系统中 kfifo缓冲区实现.由于没有涉及到锁,在多线程环境下,只适 ...
- [原创]快速指定SQLDeveloper所使用JDK的方法
就众多的免费SQL开发工具来讲,Oracle出品的SQLDeveloper 还是一个很不错的选择. 看到网上不少的帖子讨论SQL Developer 启动的时候报告找不到Java Home(或JDK) ...
- Python之路-(Django进阶二)
model: 双下划线: # 获取个数 # # models.Tb1.objects.filter(name='seven').count() # 大于,小于 # # models.Tb1.objec ...
- Python之路-jQuery
参考网址:http://jquery.cuishifeng.cn/ 1.安装环境 2.查找元素 3.操作元素 一.安装环境: 1.我们需要去官网下载jQuery,地址:http://jquery.co ...
- Python之路-python(css、JavaScript)
css JavaScript 一.CSS 分层: position: fixed;(固定到页面的具体位置) 例如:返回顶部 <!DOCTYPE html> <html lang=&q ...
- (转载)Spring的refresh()方法相关异常
如果是经常使用Spring,特别有自己新建ApplicationContext对象的经历的人,肯定见过这么几条异常消息:1.LifecycleProcessor not initialized - c ...
- ASP.NET Core – 2300% More Requests Served Per Second
http://www.ageofascent.com/asp-net-core-exeeds-1-15-million-requests-12-6-gbps/ ASP.NET Core – Excee ...
- Spark:Join相关优化文章
http://blog.csdn.net/lsshlsw/article/details/48975771 https://www.douban.com/note/499691663/ http:// ...
- 利用php比较精确的统计在线人数的办法
利用php比较精确的统计在线人数的办法,注意这里所说的精确是指个数,如果需要精确在时间上,则需要根据实际情况调整代码中的有效时间.(自己没有写,从别人那拿过来的,先放着然后再研究)<?php// ...
- Android中处理崩溃异常和记录日志
大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...