Search code examples
javaqtqmlqt5qt5.15

In qt5.15 qml how to deal with Native Function Exposure and JavaScript-to-Native Communication(caling a native function) using qml Webview


So I am using qt5.15.3 with qml and trying to handle Native Function Exposure and JavaScript-to-Native Communication

First I need to clarify my question For example like in Java we have:

// In your WebView setup code
WebView webView = findViewById(R.id.webView);
NativeInterface nativeInterface = new NativeInterface();
webView.addJavascriptInterface(nativeInterface, "NativeInterface");

NativeInterface class:

public class NativeInterface {
    @JavascriptInterface
    public void CANBUS_Write(String id,String[] data) {
        // Call the native CANBUS_Write function here with the provided data
    }
}

In webpage side we got something like:

function CANBUS_Write(id, data) {
    window.NativeInterface.CANBUS_Write(id, data);
}

to handle Native Function Exposure and JavaScript-to-Native Communication

How to deal with the same question in qt5 qml using WebView?

import QtWebView 1.1

 WebView {
 id:webView
 anchors.fill: parent
 url: "http://192.168.120.56:8888/test"


}

What I have tried

ServerSideHandler.h

#ifndef SERVERSIDEHANDLER_H
#define SERVERSIDEHANDLER_H



#include <QObject>
#include <QStringList>

class ServerSideHandler : public QObject
{
    Q_OBJECT
public:
    explicit ServerSideHandler(QObject *parent = nullptr);

public slots:
    void CANBUS_Write(const QString &ID, const QStringList &data);
};

#endif // SERVERSIDEHANDLER_H

ServerSideHandler.cpp

#include "serversidehandler.h"
#include <QDebug>

ServerSideHandler::ServerSideHandler(QObject *parent) : QObject(parent)
{
        qDebug() <<"Init";
}

void ServerSideHandler::CANBUS_Write(const QString &ID, const QStringList &data)
{
    QStringList sBuffer;
    for (const QString &item : data) {
        sBuffer.append(item);
    }
    qDebug() << "CANBUS_Write ID" << ID << ", data =" << sBuffer.join(' ');
}

main.cpp

qmlRegisterType<ServerSideHandler>("ServerSideHandler", 1, 0, "ServerSideHandler");

main.qml

 ServerSideHandler{
        id :server

    }

    WebView {
        id:webView
        anchors.fill: parent
       
        url: "http://192.168.120.56:8888/test"
        
        Component.onCompleted: {
 
            channel.registerObject("NativeInterface",server);
        }
   
        WebChannel{
            id: channel

        }
   
    }

Solution

  • OK I think I solve the problem it is not that complicated actually just directly inject into the webpage

       webView.runJavaScript(`
                              // Define a global object to expose functions
                              var NativeInterface= {
                              CANBUS_Write: function(ID, data) {  
                              return { id: ID, dataArray: data };
                              }
                              };
                              `);
    

    and also write a callback to show result while reading the result

      webView.runJavaScript(`
           NativeInterface.CANBUS_Write('123', ['data1', 'data2', 'data3'])
                                      `, function(result) {
        console.log("JavaScript NativeInterfaceresult:", JSON.stringify(result));
    });