Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
New Contributor
Posts: 7
Registered: ‎12-20-2011
My Device: all
My Carrier: a lot's of them

With a Webview element, how can you make a synchronous call to the C++ code from the javascript located in the html page ?

Hi !

 

Here is my current solution, which is very far from a truly synchronous call (and also quite complex):

In the main.qml file where I have my WebView implemented:

WebView {
    id: webView
    url: propertyMap.url
    onMessageReceived: {
        postMessage(JSHandler.handleMessage(message.origin, message.data));
    }
}

Where JSHandler is the C++ object in charge of making the interface between the Javascript call and the BlackBerry API.

Here is what the method handleMessage look like:

QString JSHandler::handleMessage(QString origin, QString data)
{
             if (data.startsWith("helloWorld", Qt::CaseSensitive))   return this->helloWorld(data);
    else if (data.startsWith("getValue1", Qt::CaseSensitive))      return this->getValue1(data);
    else if (data.startsWith("toast", Qt::CaseSensitive))               return this->toast(data);
    else ...
    return "";
}
QString JSHandler::getValue1(QString data)
{
    QString value1 = "2";
    return "getValue1 "+value1;
} 

 

And in each method I wish to implement, I need to further parse the QString data to retrieve the different arguments I wish to use.

In the Javascript code, to retrieve "value1", I use a global variable:

var BBStore = new Object();

navigator.cascades.onmessage = function onmessage(message) {
    var omr = message.split( " ", 2 );
    switch( omr[0] )
    {
    case "getValue1":
        BBStore.value1 = omr[1];
        break;
    case ...
    default:
        // nothing to do
        break;
    }
} 

 



So if I need to use value1 in method "foo", I need to make a first call to "foo" to fetch the value I need, and then call "foo" again when I have the value I want:

function foo( args ) {
    if ( ! BBStore.value1 ) {
        navigator.cascades.postMessage( "getValue1" );
        setTimeout( foo(args), 100 );
        throw( "fetching value1" );
    }
    var value1 = BBStore.value1;
    // clear the global variable to re-fetch value1 at next call.
    BBStore.value1 = null;
    
    // do something with args and value1.
} 

 



At the moment, my application remains simple enough to not run into problems. But should my application becomes more complex, I will have problems of course-condition if for example, another method "bar" also request "value1" and is called almost at the same time than "foo".


Is there any better way than this ?