最近由于要开发个需要用到低功耗蓝牙(BLE)的安卓app,因此需要搭建qt的安卓开发环境。
遇到的不少问题搜不到啥资料,只有自己去摸索尝试,但仍然有问题不知道怎么解决。被这环境搭建折腾得不轻、时间也折腾得不短,记录一下,给自己当个备忘,对有同样需求的人也希望能有所帮助。
先说一番折腾后最终使用的版本:Qt6.5 + openjdk17 + cmdline-tools 12。
之前也没搭建过着环境,于是在网上开始搜教程,一开始选的是最后的可以本地安装的版本Qt 5.14.2,参照这教程 Qt | Qt For Android、Qt5.14.2安卓开发环境搭建详细步骤 配好的环境。蓝牙相关的程序写好后,开始是在win10电脑上调试,发现搜不到低功耗蓝牙设备,开始以为是USB蓝牙设备的问题,于是又在网上买了个,发现照样搜不到,网上一番查找才知道,mingw编译器搜不到ble设备、要用msvc编译器,而安装qt的时候只选了mingw,网上一番搜索,折腾了一阵没搞明白怎么添加组件的,于是想着干脆卸载掉装个Qt6了。
想着装个Qt6.5吧,由于之前没在线安装过,所以才觉得本地安装更方便、才抗拒在线安装,尝试了在线安装后才发现挺方便的,尤其是添加、卸载组件、换Qt版本,MaintenanceTool.exe中通通搞定了(虽然Qt5.14也有这维护工具,但是没弄明白怎么添加msvc编译器)。在线安装时,若直接双击qt-online-installer-windows-x64-online.exe安装比较慢的话,就可以使用镜像,cmd中cd到其所在的目录:
.\qt-online-installer-windows-x64-online.exe --mirror https://mirrors.ustc.edu.cn/qtproject
这是中科大的镜像速度不错,由于后来安装卸载过好些次,开始也用过阿里云(https://mirrors.aliyun.com/qt/)的镜像,觉得还是中科大的快一些。同样,维护的时候也可以使用镜像,换成MaintenanceTool.exe就行。关于镜像源可参考Qt 镜像源安装,文章中还有Qt官方推荐的镜像源的网址。
第一次安装Qt6.5的时候选了这些组件,后来觉得Qt Design Studio用不上,后面再装时就把其去掉了。
配置安卓开发环境比Qt5.14方便不少,只要安装下JDK,其他的SDK、NDK点几下鼠标就行。工具 - 外部 - 配置 - SDKs - Android,先点击JDK位置最右边的圆形打开Open JDK的下载网页,下载JDK11或17都行,然后点击浏览选择JDK的安装位置就可以了。Android SDK的路径,选择一个空的文件夹就行,然后点击设置SDK,正常情况下是会自动下载SDK、NDK这些的。下图是后面偶然发现的方法配置好安卓开发环境后的截图。
但是第一次安装好Qt6.5配置安卓开发环境时,意外发生了。正常情况是先1后2再3,但是出现1和2之后就没有然后了,试过好几次,就是不出现3,当时也不知道怎么解决,于是就只好试试安装Qt 6.8。
通过MaintenanceTool.exe很方便的就卸载了Qt 6.5、安装了Qt6.8,组件上和6.5时还是有不少区别的。
安装好后,配置安卓环境挺顺利,点击设置SDK后,一次出现了上面的1、2和3,没多久就安装好了。
于是就开始在Qt 6.8下开始写程序了,很快就发现个问题,之前Qt 5.14编译的程序在安卓上运行时,扫描蓝牙时是会自动弹出获取定位权限的对话框的,但是6.8编译的程序不弹框,导致根本没法扫描蓝牙,打印是没有定位权限导致的。试了下在手机的系统设置里手动授权app的定位权限,就可以正常扫描蓝牙了,但是不能自动获取肯定是个问题。
然后又是一番搜索,发现可以在C++中通过QLocationPermission手动添加权限(参考Application Permissions),添加好后,在安卓9上跑可以自动获取定位权限了,但是在安卓13上还是不能自动获取定位权限,所以不出意外也是不能扫描蓝牙,在Qt论坛上提问(lack of permission)也没找到办法。问题的回答中有提到:
Android 12 (API 31) and Later
Required permissions:
BLUETOOTH (normal permission - granted at install time)
BLUETOOTH_CONNECT (runtime permission - must be requested)
BLUETOOTH_SCAN (runtime permission - if scanning for devices)Android 6.0 (API 23) to Android 11 (API 30)
Required permissions:
BLUETOOTH (normal permission)
BLUETOOTH_ADMIN (normal permission - if you need to scan/pair)
ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION (runtime permission - required for scanning)
按这说法,安卓13(对应的是API 33 Android 系统与SDK和JDK版本对照表)是可以不需要定位权限了的,但是不知道为啥就是不能扫描蓝牙。
然后又是一番搜索,发现可以在左侧的项目中选中安卓的构建套件,点开“构建安卓APK”,点击“创建模板”,在AndroidManifest.xml中添加权限,可是由于创建工程时选的是Qt Quick Application,只能使用cmake,在创建模板时又出意外了:
在Qt论坛上也提问了(Unable to create the template),还是没有找到解决办法。
后来才发现创建工程时选Qt Quick Application(compat)可以创建qmake的工程,此时虽然能正常创建模板,添加了ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION、BLUETOOTH、BLUETOOTH_ADMIN权限,但是还是不能自动获取定位权限。各权限的含义见Android Manifest.xml配置访问权限设置。
没办法,只能又是换版本了。于是又装上了Qt 5.14.2,但是总觉得心有不甘,想用新点的版本。
之前的搜索过程中就有看到过配置安卓环境时出问题,有的是cmdline-tools版本过新导致的,替换旧版本后就解决了。偶然在这篇文章 开发经验C++、QML、安卓常见问题合集 中看到了关于cmdline-tools的相关内容:
感觉Qt 6.5配置安卓开发环境又看到希望了。于是又重新安装了6.5,一开始装的OpenJDK11,然后用Everything搜sdk_definitions.json,把所有搜出来的文件里面的latest都改成了9.0,cmdline-tools 版本 和JDK版本的对于关系参考cmdline-tools 版本与其最小JDK关系。这次点击设置SDK后,总算是顺利安装好了,长舒了一口气,原来之前6.5配置不成功是cmdline-tools 版本太新的问题。
然后赶紧编译安卓试试看能不能自动弹出获取定位的对话框,Qt6.5 + openjdk11 + cmdline-tools 9,新建qmake项目(最低版本选5.15或6.2)或cmake项目在安卓9和13的手机上都能自动弹框获取定位、能正常扫描蓝牙。然后又试了Qt6.5 + openjdk17 + cmdline-tools 16也可以,只是明明cmdline-tools指定的版本明明是16,但是安卓配置环境页面显示的SDK版本却是12,在SDK管理器里显示的版本是16的。还试过指定cmdline-tools 17,SDK管理中已安装的如下所示,对比了16和17,除了cmdline-tools的版本不一样外,其它的都是一样的。
若同时安装了OpenJDK11和17,切换版本也很简单。先后安装OpenJDK11和17,安装时会自动设置环境变量,后安装的会覆盖前面安装的。要切换时,此电脑 - 右键属性 - 高级系统设置 - 环境变量 - 系统变量 - Path,将要使用的版本的安装路径放第一行,如当前是C:\Program Files\Eclipse Adoptium\jdk-17.0.14.7-hotspot\bin,要换成11时,将这一行内容换成11的安装路径即可,切换后应该是要注销一下系统才会生效,cmd中java -version查看当前生效的版本。
Qt6.8 + openjdk17 + cmdline-tools 16,可以看到NDK、Build-Tools和SDK平台的版本都比6.5的高一些。
想着试试看6.8下添加一下6.5的那些版本,是不是也能编译出的apk能自动弹框获取定位。
添加好后,构建安卓APK那能看到有两个版本的可选了,只有35.0.0 + android-35编译出来的apk是正常运行的,33.0.0 + android-35能成功编译,但是运行时闪退,其它组合编译直接报错了,也不知道是啥原因。所以这尝试是以失败告终了。
于是最终决定使用Qt6.5 + openjdk17 + cmdline-tools 16的组合。
由于电脑上装的是VS2022,而Qt6.5用的是MSVC 2019,因此需要在Visual Studio Installer中添加一下2019的相关组件,可参考 QT中MSVC2017无法使用的解决方法、qt5.14.2跟vs2022配置。
对比了6.5和6.8编译后生成的AndroidManifest.xml中关于权限的部分,差别还是挺大的,6.8的加上了版本的限制,感觉是6.8这样子的更合理,只是无奈实际上用不了啊。试过6.8创建qmake项目,然后创建模板添加相应的权限,手动添加的那些权限在AndroidManifest.xml中显示的和6.5的是一样的了,只是照样是不能自动弹框获取定位权限。
Qt6.5 + openjdk17 + cmdline-tools 16时,首次选安卓构建套件编译时,编译输出如下乱码信息,但是又能正常生成apk、安装后能正常运行;再次编译时又没有这些乱码了,搞不清这是为啥。Qt6.8时试过使用openjdk21,发现首次编译时也有乱码,只是乱码和这不同,换成openjdk17时又没有这乱码了。后来试了Qt6.5+openjdk11也还是有这乱码。
需要更换运行的手机时:
低功耗蓝牙(ble)编程可参考:QT编程: 编写低功耗BLE蓝牙调试助手(Android系统APP)。
连接同一个目标蓝牙设备,安卓上通过蓝牙收发数据是正常的,但是win10上就是有问题,Qt5.14、Qt6.5、Qt6.8都试了,都不行,现象是:writeCharacteristic()写数据后,characteristicWritten信号没有被触发,但是对方又能收到数据,对方也回了数据,但是onCharacteristicChanged信号照样没有被触发,因此也收不到数据,连接蓝牙的过程中看到有如下信息打印,也是搞不清为什么。Qt论坛上看到之前有人提过相同的问题,但是没人解答。
-------------- 2025.5.27更新一下 --------------------
今天发现之前明明指定的cmdline-tools的版本是16但是安卓环境配置界面显示的版本是12的原因了。原来除了latest要改,上面的链接和sha256也要改。Qt6.5默认的是12版本的,所以才出现界面显示的版本是12。将latest改为16,同时上面的链接和sha256也改为版本16的,配置好后,安卓配置界面显示的SDK版本也是16了。
上图是版本12的,若要修改为其他版本的,链接中只需要修改文件名即可,点击设置SDK后,会从这链接去下载cmdline-tools到C:\Users\(用户名)\AppData\Local\Temp文件夹下,下载好后会将下载好的文件的SHA-256 Hash 值与上图中的windows_sha256值去对比,一致才能验证通过,因此改了链接就要同步修改windows_sha256。windows_sha256可以在cmd中通过下面命令行得到:
CertUtil -hashfile 文件的绝对路径 SHA256
以下是其它几个版本的修改内容:
8.0
"windows": "https://dl.google.com/android/repository/commandlinetools-win-9123335_latest.zip",
"windows_sha256": "8a90e6a3deb2fa13229b2e335efd07687dcc8a55a3c544da9f40b41404993e7d",
10.0
"windows": "https://dl.google.com/android/repository/commandlinetools-win-9862592_latest.zip",
"windows_sha256": "8597200d2622a0c720d0cf9a2b62b33d20eabdf56ce4cbd5ed5830c723a5fce5",
16.0
"windows": "https://dl.google.com/android/repository/commandlinetools-win-12266719_latest.zip",
"windows_sha256": "f9088c04a44f1f37a8a3a228a7663e11ae9445fa07529c96cef38acb985a88f3",
发现JDK17 + cmdline-tools 16 安卓编译时有如下告警,JDK17 + 默认的cmdline-tools 12、JDK11 + cmdline-tools 10都没有这告警,因此还是决定改用JDK17 + cmdline-tools 12了。
Warning: SDK processing. This version only understands SDK XML versions up to 3 but an SDK XML file of version 4 was encountered. This can happen if you use versions of Android Studio and the command-line tools that were released at different times.
还有个困扰的问题是,配置好环境后,经常再打开时又是好几把×,得又点击设置SDK等下载验证完后才会变成全√,又是个搞不清为啥的问题。
-------------- 2025.5.28更新一下 --------------------
上图中的问题看了Qt安装安卓环境报错 后摸索出来了解决办法。
前面sdk_definitions.json中的latest是改为了12.0的,因此SDK路径下的cmdline-tools文件夹下的文件夹也是12.0。尝试把2个sdk_definitions.json中的12.0又改为latest、把12.0文件夹名也改为latest,然后再次打开配置安卓开发环境的对话框时,提示有更新,点开显示详情是说cmdline-tools要更新到latest,赶紧点了取消。于是又把sdk_definitions.json中的latest改为了12.0、只保留了把12.0文件夹名也改为latest,再次打开安卓配置界面时,耶,好了!全是 √ 了、也不弹要更新到latest的对话框了!
-------------- 2025.5.29更新一下 --------------------
昨天试过好几次重新打开Qt Creator(包括重启电脑)配置环境都是好的的,今天咋又是×了,只是比之前少了一把×,忧伤...
于是又把cmdline-tools文件夹下的latest文件夹名称改回了12.0。因为commandlinetools-win-11076708_latest.zip之前已经下载到了C:\Users\(用户名)\AppData\Local\Temp文件夹下,因此把2个sdk_definitions.json中的
"windows": "https://dl.google.com/android/repository/commandlinetools-win-11076708_latest.zip",
改为了
"windows": "file:///C:/Users/(用户名)/AppData/Local/Temp/commandlinetools-win-11076708_latest.zip",
这样至少在出现×的时候,点击设置SDK时不用下载了,直接验证,速度会快一些了。
PS
为啥现在越来越多的文章需要VIP才能看了呢...