Qt for Android中调用百度地图

2019-03-21  本文已影响0人  Qt工坊

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

四个重要的类

WebSocketTransport类的实现

继承QWebChannelAbstractTransport,实现WebSocketTransport类
websockettransport.h

#ifndef WEBSOCKETTRANSPORT_H
#define WEBSOCKETTRANSPORT_H

#include <QWebChannelAbstractTransport>

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 <QWebSocketServer>
#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 <QWebChannel>

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 <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QWebChannelAbstractTransport>
#include <QWebSocket>

/*!
    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 <QObject>

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。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/qwebchannel.js" ></script>
<style type="text/css">
body,html,#allmap {width: 100%;height: 100%;overflow: hidden;}
.userInfo {    
position: fixed;
z-index: 100;
top: 10pt;
left: 10pt;}
.notes {
position: fixed;
z-index: 100;
top: 10pt;
right: 10pt;}
</style>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=请在这里填入读者自己的百度地图开发者key"></script>
<title>百度地图</title>
</head>
</body>

<body>
<div id="allmap"></div>

</html>
<script type="text/javascript">

// 百度地图API功能
var map = new BMap.Map("allmap");
var m_city = "北京";
map.centerAndZoom(m_city, 13);                              // 初始化地图,设置中心点坐标和地图级别
map.addControl(new BMap.OverviewMapControl());              //添加缩略地图控件
map.enableScrollWheelZoom();                               //启用滚轮放大缩小

window.onload = function() {
                var baseUrl = "ws://localhost:12345";

                console.log("Connecting to WebSocket server at " + baseUrl + ".");
                var socket = new WebSocket(baseUrl);

                socket.onclose = function() {
                    console.error("web channel closed");
                };
                socket.onerror = function(error) {
                    console.error("web channel error: " + error);
                };
                socket.onopen = function() {
                    console.log("WebSocket connected, setting up QWebChannel.");
                    new QWebChannel(socket, function(channel) {
                        // make bridge object accessible globally
                        window.bridge = channel.objects.bridge;
                        
                        window.bridge.sendDataToJs.connect(function(key,dataString){
                        //在这里处理从C++发送到js的信号
                        //在这里也可以调用C++的槽函数,如下:
                        window.bridge.setDataToCPP("Key_Data1","Some data string");

                });

                    });
                }
            }


</script>



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

上一篇下一篇

猜你喜欢

热点阅读