vendredi 16 décembre 2011

MoSync : Communication entre JavaScript et C++ dans MoSync


Ce document indique comment le pont entre JavaScript et C++ marche dans MoSync. C’est la suite du cours Création de projet HTML5 sur MoSync.

Comment invoquer du code C++ depuis JavaScript

Ce qui suit assume que voue avez créé un projet en utilisant la template HTML5/C++ Project. Le code utilise les classes WebAppMoblet et WebViewMessage dans la librairie Wormhole.
Ceci est la fonction JavaScript dans le fichier index.html qui invoque le code qui fait vibrer le mobile :
/**
 * Fait vibrer le mobile.
 */
function Vibrate()
{
      // C’est ainsi qu’un message est passé au C++ lorsqu’on utilise la librairie de pont (Bridge)
      bridge.messagehandler.send({messageName: "Vibrate"}, null);
}
Et ceci est le code C++ dans main.cpp qui gère le message:
/**
 * Cette fonction gère les messages envoyés depuis WebView
 * @param webView Le WebView qui a envoyé le message.
 * @param urlData L’objet de données qui contient le contenu du message.
 * Veuillez noter que l’objet de données sera valide uniquement lors de la durée de vie de l’appel de cette fonction, puis il sera libéré*/

void handleWebViewMessage(WebView* webView, MAHandle urlData)
{
      // Crée l’objet message. Ceci scanne le message.
      WebViewMessage message(webView, urlData);

      if (message.is("Vibrate"))
      {
            // Fait vibrer le message pendant une demi-seconde.
            // Dans iOS, la longueur de la vibration sera constante,
            // peut importe la valeur du paramètre time.
            maVibrate(500);
      }

      // Indique à WebView que le message a été traité
      // ainsi il peut envoyer le suivant.
      callJS("bridge.messagehandler.processedMessage()");
}
La dernière ligne, qui appelle la fonction JavaScript bridge.messagehandler.processedMessage(), est là pour indiquer au pont JavaScript qu’il peut envoyer le message suivant. Ceci aurait pu être appelé par code dans la superclasse WebAppMoblet, mais afin d’éviter de coupler WebAppMoblet à une librairie JavaScript particulière, ceci n’est pas fait automatiquement.
La fonction bridge.messagehandler.send() prend 2 paramètres :
bridge.messagehandler.send(message, callbackFunction)
Le paramètre ‘message’ est un dictionnaire, qui contient le nom du message et optionnellement d’autres paramètres du message. Le paramètre ‘callbackFunction’ est une fonction que vous pouvez appeler depuis C++ pour retourner une valeur à JavaScript. Le mécanisme de communication est asynchrone, c’est pourquoi une fonction de callback est utilisée pour faire passer le résultat à JavaScript.
Si vous voulez faire passer des paramètres à C++, vous ajouter le paramètre comme champs dans message, par exemple :
bridge.messagehandler.send(
          { messageName: "Vibrate",
            duration: "1000" },    null);
Dans le code C++, c’est ainsi que vous récupérez le paramètre du message:
void handleWebViewMessage(WebView* webView, MAHandle urlData)
{
      // Crée un objet message. Ceci scanne le message.
      WebViewMessage message(webView, urlData);

      if (message.is("Vibrate"))
      {
            // Récupère le paramètre "duration" comme une valeur int et vibre pendant ce nombre de millisecondes.
            int duration = message.getParamInt("duration");
            maVibrate(duration);
      }

      // Indique à WebView que nous avon traité le message, ainsi il peut envoyer le suivant.
      callJS("bridge.messagehandler.processedMessage()");
}
Si vous voulez récupérer la valeur String d’un paramètre, utilisez la fonction getParam  de l’objet message.

Comment invoquer le code JavaScript depuis C++

Pour invoquer du code JavaScript dans WebView depuis C++, vous pouvez utiliser la fonction WebAppMoblet::callJS(). Voici un exemple :
callJS("alert('Hello World')");
Ce qui suit illustre comment invoquer C++ depuis JavaScript et appeler une function de callback JavaScript. Voici la partie JavaScript :
bridge.messagehandler.send(
      { messageName: "GetScreenSize" },
      function(width, height) {
            alert("Screen size: " + width + " " + height);
      });
Voici la partie C++:
void handleWebViewMessage(WebView* webView, MAHandle urlData)
{
      WebViewMessage message(webView, urlData);
       
      if (message.is("GetScreenSize"))
      {
            // Appeler le handler de réponse JavaScript pour ce message.
            char script[512];
            sprintf(
                  script,
                  "bridge.messagehandler.reply(%s, %d, %d)",
                  message.getParam("callbackId").c_str(),
                  EXTENT_X(maGetScrSize()),
                  EXTENT_Y(maGetScrSize()));
            getWebView()->callJS(script);
      }
       
      callJS("bridge.messagehandler.processedMessage()");
}

Aucun commentaire: