使用Qt for android 获取android PDA设备扫码数据并连接https服务器

安装Qt Android 模块、Qt Creator、JDK8

在这里插入图片描述
Qt Creator版本太高不行,亲测最新版的会导致无法使用jdk 8(2024-05-04
我的Qt版本是5.15.2,所以我选择了Qt Creator5.0.3进行开发
5.0.3

下载JDK8

在这里插入图片描述
JDK8

安装Qt Creator、JDK8

安装Qt Creator没什么好说的,都是默认选择就行
安装JDK8也是全部默认的就行

Qt Creator安卓环境配置

  1. 确认是否开启了Android 开发插件Android 帮助-》关于插进在这里插入图片描述
  2. 配置Android开发环境 工具-》选项在这里插入图片描述
    JDK location:JDK安装路径,此处是默认的安装路径
    Android SDk的路径:此处请新建一个非中文路径的名为《android-sdk-windows》的文件夹,这一步在我测试,好像必须是这个名字,不然set up sdk不行

然后请将sdk_definitions.json文件中的“cmdline-tools;latest” 修改为 “cmdline-tools;6.0”。在这里插入图片描述
在这里插入图片描述
修改完成后点击[Android SDk的路径]后面的set up sdk
如果不出意外的,会自动下载相关依赖,最终正常效果如下
在这里插入图片描述
配置openssl,先选择保存路径,然后再download openssl即可
在这里插入图片描述
下载对应Android 版本sdk,我的机器是Android 9 ,下载了下面勾选的三个东西,然后点击update installed.
在这里插入图片描述
然后点击Kits-》Qt Versions,将Android qmake.exe添加进来,然后就会会自动的检测并配置Android 编译套件 ,如果没有就重新启动下Qt Creator,或者手动设置下
在这里插入图片描述

在这里插入图片描述
至此,环境搭配完成

PDA连接https服务器、并获取PDA扫码数据

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重点来了
在这里插入图片描述
这里默认值就行
在这里插入图片描述
点击完成,此时,会在源码路径生成一个android文件夹,在里面建立一个src文件夹(这里一定要建立)。
在这里插入图片描述
在这里插入图片描述
双击AndroidManifest.xml
在这里插入图片描述
org.qtproject.example:这里表示的是java代码的包名,根据官方示例的做法,是在刚建立的src文件夹中依次建立org》qtproject》example,(其实不这样直接放入src也是没问题的,但是既然官方都这样写,我还是这样做)。当然你也可以写成org.qtproject.example.test,然后在example下面再建立一个test文件夹即可,把java源文件放入最后一个目录中。

然后在设置如下两样参数

在这里插入图片描述
将手机进入开发者模式,然后勾选:USB调试
连接电脑在这里插入图片描述

PDA设备扫码数据获取

我这使用的方法是以Android广播的形式,获取设备扫码数据的,但是Qt没有办法直接获取广播数据,只有借助java代码。
这里借鉴的是如来说法同志的QT for android 获取PDA扫码的广播数据博客中的代码,
代码如下

ActivityUtils.java

package org.qtproject.example;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;

public class ActivityUtils {
    private static native void sendToQt(String message);
    private static final String TAG = "ActivityUtils";
    public static final String BROADCAST_NAME_ACTION = "com.android.server.scannerservice.broadcast";//这里填广播名称

    public void registerServiceBroadcastReceiver(Context context) {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BROADCAST_NAME_ACTION);
        context.registerReceiver(serviceMessageReceiver, intentFilter);
        Log.i(TAG, "Registered broadcast receiver");
    }
    private BroadcastReceiver serviceMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "In OnReceive broadcast receiver");
            if (BROADCAST_NAME_ACTION.equals(intent.getAction())) {
                String name = intent.getStringExtra("scannerdata");
                Log.i(TAG, "Service received name: " + name);
                String message = "Hello " + name;
                sendToQt(message);
                Log.i(TAG, "Service sent back message: " + message);
            }
        }
    };
}

然后将此源文件放入上面说的android文件夹里面的码包文件夹中

然后在cpp中代码调用

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSslKey>
#include <QNetworkAccessManager>
#include <QFile>
#include <QNetworkReply>

#include <QAndroidJniEnvironment>
#include <QAndroidIntent>
#include <QtAndroid>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

signals:
    void sendCodeMessage(QString mess);

public slots:
    void setCodeMessage(QString mess);

private:
	bool requestPermission();\\动态申请权限
    void registerNatives();\\将c++函数注册进入java,等待被java调用
    void registerBroadcastReceiver();\\这里应该是调用java中的注册函数,将接收数据函数注册到广播中

    static void receivedFromAndroidService(JNIEnv *env, jobject /*thiz*/, jstring value);\\当有扫码的广播时被调用

 private:
    void readQSslConfiguration();\\读取密钥
    void networkRequest();\\发送请求

private:
    static MainWindow* mainWindow;

    //服务器地址
    QString domainName;
    static QNetworkAccessManager* manager;
    QSslConfiguration sslConfigurationnfig;
    quint16 port;
    QString hostName;

private:
    Ui::MainWindow *ui;


};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow* MainWindow::mainWindow = nullptr;
QNetworkAccessManager* MainWindow::manager= nullptr;


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    mainWindow = this,
    domainName = "https://dmmd:1111";
    hostName = "dmmd";
    port = 1111;
    manager = new QNetworkAccessManager(this);

    ui->setupUi(this);


    registerNatives();
    registerBroadcastReceiver();

    readQSslConfiguration();
    networkRequest();

    connect(this, &MainWindow::sendCodeMessage, this, &MainWindow::setCodeMessage);
}

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

bool MainWindow::requestPermission() {
    QtAndroid::PermissionResult r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
        if(r == QtAndroid::PermissionResult::Denied) {
            QtAndroid::requestPermissionsSync( QStringList() << "android.permission.WRITE_EXTERNAL_STORAGE" );
            r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
            if(r == QtAndroid::PermissionResult::Denied) {
                 return false;
            }
       }
       return true;
}

void MainWindow::registerNatives()
{
    JNINativeMethod methods[] {
        {"sendToQt", "(Ljava/lang/String;)V", reinterpret_cast<void *>(MainWindow::receivedFromAndroidService)}};
    QAndroidJniObject javaClass("org/qtproject/example/ActivityUtils");

    QAndroidJniEnvironment env;
    jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
    env->RegisterNatives(objectClass,
                         methods,
                         sizeof(methods) / sizeof(methods[0]));
    env->DeleteLocalRef(objectClass);
}

void MainWindow::registerBroadcastReceiver()
{
    QAndroidJniEnvironment env;
    jclass javaClass = env.findClass("org/qtproject/example/ActivityUtils");
    QAndroidJniObject classObject(javaClass);

    classObject.callMethod<void>("registerServiceBroadcastReceiver",
                                 "(Landroid/content/Context;)V",
                                 QtAndroid::androidContext().object());
}

void MainWindow::receivedFromAndroidService(JNIEnv *env, jobject /*thiz*/, jstring value){
    qDebug()<<env->GetStringUTFChars(value, nullptr);
    emit mainWindow->sendCodeMessage(env->GetStringUTFChars(value, nullptr));
}

void MainWindow::setCodeMessage(QString mess){
    ui->textBrowser_2->append(mess);
}

void MainWindow::readQSslConfiguration(){

    QString p12Path = R"(/storage/emulated/0/ssl/client.p12)";
    QFile file1(p12Path);
    if (!file1.open(QIODevice::ReadOnly)) {
        qWarning() << u8"p12文件读取失败";
        return;
    }

    QSslKey priKey;
    QSslCertificate cert;
    QList<QSslCertificate> certList;
   bool state = QSslCertificate::importPkcs12(&file1, &priKey, &cert, &certList, "dddddd122317");
   if(!state){
       qDebug()<<u8"解密失败";
   }

    sslConfigurationnfig.setPeerVerifyMode(QSslSocket::VerifyPeer);
    sslConfigurationnfig.setProtocol(QSsl::TlsV1_1);
    sslConfigurationnfig.setPrivateKey(priKey);
    sslConfigurationnfig.setLocalCertificate(cert);
    sslConfigurationnfig.setCaCertificates(certList);
    sslConfigurationnfig.setAllowedNextProtocols({QSslConfiguration::NextProtocolHttp1_1});
    file1.close();
}

void MainWindow::networkRequest(){
    QUrl url(domainName);
    url.setPath("/app/customer/query");
    QEventLoop eventLoop;
    QNetworkRequest request;
    request.setUrl(url);
    //设置请求头
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    manager->connectToHostEncrypted(hostName, port, sslConfigurationnfig);
    QNetworkReply* reply = manager->post(request, QByteArray{});
    connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
    connect(reply, &QNetworkReply::downloadProgress, this, [=](qint64 size, qint64 line) {
        //qDebug() << size << line;
        });
    connect(reply, &QNetworkReply::errorOccurred, this, [=](QNetworkReply::NetworkError code) {
        QString error = code + reply->errorString();
        qWarning() << error;
        });
    eventLoop.exec();
    QByteArray data = reply->readAll();
     ui->textBrowser->append(data);
    qDebug()<<data;
}

Virtual-Hosts

Virtual-Hosts
使用这个软件可以不用修改hosts文件也能使用自定义的主机名进行访问
首先在电脑上命名一个hosts文件(无后缀)
然后写入自定义的主机名
127.0.0.1 mddm
然后放入手机里面
然后点击:重新选择HOSTS文件
打开开关即可正常访问

大功告成!服务器可以正常连接返回数据、软件也可以正常接收到扫码数据

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值