Qt for Android中调用百度地图

首先感谢参考链接中的博主wkcagd,在他文章里面,基于websocket介绍了利用Qt官方js脚本qwebchannel.js文件,实现C++同js的互相通信方法。
关于在Qt中调用百度地图,网上能找到在桌面版中的实现方法,也是通过qwebchannel.js实现的;但在Android手机上实现Qt同百度地图的交互,完全套用桌面开发的方法行不通,还需要实现一些附加的工作,比如:需要自己手动创建websocket来实现C++代码同js之间的通信。

四个重要的类

  • QWebSocketServer
  • WebSocketTransport
    继承于QWebChannelAbstractTransport
  • WebSocketChannel
    继承于QWebChannel
  • WebChannelBridge
    继承于QObject,作用如下:
    1. 从C++发送信号并传递参数到js;
    2. 从js调用C++的槽函数。

WebSocketTransport类的实现

继承QWebChannelAbstractTransport,实现WebSocketTransport类
websockettransport.h

#ifndef WEBSOCKETTRANSPORT_H
#define WEBSOCKETTRANSPORT_H

#include 

QT_BEGIN_NAMESPACE
class QWebSocket;
QT_END_NAMESPACE

class WebSocketTransport : public QWebChannelAbstractTransport
{
    Q_OBJECT
public:
    explicit WebSocketTransport(QWebSocket *socket);
    virtual ~WebSocketTransport();

    void sendMessage(const QJsonObject &message) override;

private slots:
    void textMessageReceived(const QString &message);

private:
    QWebSocket *m_socket;
};


#endif // WEBSOCKETTRANSPORT_H

websocketchannel.cpp

#include "websocketchannel.h"
#include 
#include "websockettransport.h"

WebSocketChannel::WebSocketChannel(QWebSocketServer *server)
    :_server(server)
{
    connect(server, &QWebSocketServer::newConnection,
            this, &WebSocketChannel::handleNewConnection);

    connect(this, &WebSocketChannel::clientConnected,
            this, &WebSocketChannel::connectTo);
}

void WebSocketChannel::handleNewConnection()
{
    emit clientConnected(new WebSocketTransport(_server->nextPendingConnection()));
}

WebSocketChannel类的实现

继承QWebChannel,实现WebSocketChannel类
websocketchannel.h

#ifndef WEBSOCKETCHANNEL_H
#define WEBSOCKETCHANNEL_H

#include 

class QWebSocketServer;
class WebSocketTransport;

class WebSocketChannel : public QWebChannel
{
    Q_OBJECT
public:
    WebSocketChannel(QWebSocketServer *server);

signals:
    void clientConnected(WebSocketTransport *client);

private slots:
    void handleNewConnection();

private:
    QWebSocketServer *_server;
};

#endif // WEBSOCKETCHANNEL_H

websocketchannel.cpp

#include "websockettransport.h"

#include 
#include 
#include 
#include 
#include 

/*!
    Construct the transport object and wrap the given socket.

    The socket is also set as the parent of the transport object.
*/
WebSocketTransport::WebSocketTransport(QWebSocket *socket)
: QWebChannelAbstractTransport(socket)
, m_socket(socket)
{
    connect(socket, &QWebSocket::textMessageReceived,
            this, &WebSocketTransport::textMessageReceived);
    connect(socket, &QWebSocket::disconnected,
            this, &WebSocketTransport::deleteLater);
}

/*!
    Destroys the WebSocketTransport.
*/
WebSocketTransport::~WebSocketTransport()
{
    m_socket->deleteLater();
}

/*!
    Serialize the JSON message and send it as a text message via the WebSocket to the client.
*/
void WebSocketTransport::sendMessage(const QJsonObject &message)
{
    QJsonDocument doc(message);
    m_socket->sendTextMessage(QString::fromUtf8(doc.toJson(QJsonDocument::Compact)));
}

/*!
    Deserialize the stringified JSON messageData and emit messageReceived.
*/
void WebSocketTransport::textMessageReceived(const QString &messageData)
{
    QJsonParseError error;
    QJsonDocument message = QJsonDocument::fromJson(messageData.toUtf8(), &error);
    if (error.error) {
        qWarning() << "Failed to parse text message as JSON object:" << messageData
                   << "Error is:" << error.errorString();
        return;
    } else if (!message.isObject()) {
        qWarning() << "Received JSON message that is not an object: " << messageData;
        return;
    }
    emit messageReceived(message.object(), this);
}

WebChannelBridge类的实现

webchannelbridge.h

#ifndef WEBCHANNELBRIDGE_H
#define WEBCHANNELBRIDGE_H

#include 

class WebChannelBridge : public QObject
{
    Q_OBJECT
public:
    explicit WebChannelBridge(QObject *parent = nullptr);
signals:
//发送信号传递参数到js
  void sendDataToJs(const QString& key, const QString& dataString);
public slots:
//从js调用槽函数设置数据到C++
  void setDataToCPP(const QString& key, const QString& dataString);
};
#endif // WEBCHANNELBRIDGE_H

Qt for Android工程main.cpp主要代码

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    //启动web socket server监听端口12345,以实现C++同html的数据传输
    QWebSocketServer server(QStringLiteral("QWebChannel Standalone Example Server"),   
    QWebSocketServer::NonSecureMode);
    if (!server.listen(QHostAddress::LocalHost, 12345))
    {
        exit(-1);
    }

    QQmlApplicationEngine engine;
    Engine *appEngine = Engine::getInstance();//这是笔者自己写的C++类,用于在QML中实现同C++的通信之用,和本文主要内容无关
    appEngine->uiInit();
    appEngine->basicInit();

    //建立websocketchannl,该channel就可以用来同html通信了
    WebSocketChannel channel(&server);

    WebChannelBridge *bridge = new WebChannelBridge;
    //注册C++对象,该类要继承自QObject
    //将bridge对象注册到channel中,以便在html/js中调用
    channel.registerObject(QStringLiteral("bridge"), (QObject*)bridge);

    appEngine->setHttpBridge(bridge);
    engine.rootContext()->setContextProperty("bridgeHtml",bridge);//注册对象bridge,在qml中调用
    engine.rootContext()->setContextProperty("appEngine",appEngine);//注册对象appEngine,在qml中调用

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        exit(-1);

    return app.exec();
}

html文件中主要代码实现

qwebchannel.js文件可以通过下方链接进行下载;请读者自行从其它地方下载jquery.min.js文件,放到该html文件同级的js目录中。请读者在该html文件中填入自己的百度开发者key。










百度地图



QML文件中百度地图的调用

将百度地图html文件和相关js文件放到Qt for Android工程目录的android/assets目录中,文件将被打包至apk安装包中。

   WebView{//百度地图
        id:webView
        x:0
        width: parent.width
        height: parent.height
        url:"file:///android_asset/baiduMap_online/index.html"
        onLoadProgressChanged: {
            if(webView.loadProgress == 100){
               
            }
        }
    }

qwebchannel.js文件下载地址

链接:https://pan.baidu.com/s/1QMRuVwn-88IZX2N3QAggaw
提取码:j6y6

参考链接

https://www.cnblogs.com/wkcagd/p/7732330.html

你可能感兴趣的:(Qt for Android中调用百度地图)