Comprendre l'application Android de l'addjavascriptinterface

Je sais que pour interagir de Javascript vers Java, vous devez injecter un objet Java à l'aide de la méthode addjavascriptInterface dans le Webview.

Voici le problème auquel je suis confronté.

  • Comment résoudre cet avertissement "W / Atlas: Pointeur 0x0, pas dans getPreloadedDrawables? "
  • Comment obtenir des valeurs d'attributs de thème
  • Conversion d'une vue en Bitmap sans l'afficher dans Android?
  • Vérifiez l'action de l'utilisateur sur Intent.ACTION_VIEW
  • Comment créer AUTO_INCREMENT sur la base de données SQLite SQL?
  • Suppression du rembourrage supplémentaire dans un GridView dans Android
    1. Je enregistre un objet java à l'aide de la méthode addJavascriptInterface pour être disponible dans mon JS.

    2. J'invite quelques JS dans la vision du Web en utilisant webview.loadURL("javascript:XXX");

    3. J'envoie un événement JS lorsque j'ai fini d'injecter le JS.

    Le problème est que si immédiatement après l'étape 1, si j'exécute le Javascript suivant:

     mWebView.loadUrl("javascript:if(window.myobject) console.log('myobject found---------'); else {console.log('myobject not found----');}"); 

    Je reçois "myobject not found" dans le journal de ma console.

    Je veux savoir que s'il y a un certain temps avant que je puisse accéder à mon objet et si oui, comment puis-je savoir combien de temps j'attends pour appeler mon objet?

    3 Solutions collect form web for “Comprendre l'application Android de l'addjavascriptinterface”

    Je veux savoir que s'il y a un certain temps avant que je puisse accéder à mon objet

    Oui, je pense qu'il y a un délai, car WebView.addJavascriptInterface sera exécuté dans le thread de travail interne du WebView. Peut-être avez-vous réfléchi à cela, et vous avez réalisé que WebView devait maintenir au moins un thread de travail pour effectuer un IO de réseau asynchrone. Peut-être que vous avez également remarqué ces threads dans DDMS tout en utilisant un WebView.

    Il s'avère qu'il utilise également un fil pour faire du travail pour un certain nombre d'autres méthodes publiques. Je souhaite vraiment que les documents de Google rendent cela plus clair. Mais j'espère pouvoir vous aider et vous montrer comment j'ai essayé de confirmer cela pour moi-même.

    Suivez-moi alors que je regarde la source pour WebView. C'est raisonnablement lisible, même si vous ne pouvez pas suivre exactement ce qui se passe, il est possible de suivre certaines questions concernant les threads.

    Vous pouvez télécharger la source de la structure Android via l'outil du gestionnaire SDK, mais elle est également reflétée sur Github, c'est ce que j'ai lié ici. J'ai deviné et choisi une étiquette proche de certaines versions d'ICS. Il n'est pas difficile de trouver WebView.addJavascriptInterface . Je viens de visiter Google Sites WebView.java: github.com/android ".

    La méthode WebView.addJavascriptInterface envoie un message à une instance de WebViewCore :

     mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg); 

    Dans WebViewCore.java il existe un tas de méthodes surchargées appelées sendMessage , mais nous n'avons pas vraiment besoin de savoir qui s'appelle exactement, car elles font à peu près la même chose. Il y a même un bon commentaire pour nous donner un indice que nous sommes au bon endroit! Tous délèguent à une instance de EventHub qui est une classe intérieure. Cette méthode se révèle être synchronisée et envoie un message à une instance de Handler , ce qui est une bonne indication que cela s'exécute probablement dans un autre thread, mais pour l'intégralité, découvrez-le!

    That Handler est instancié dans EventHub.transferMessages appelé WebViewCore.initialize . Il y a quelques sauts supplémentaires ici, mais finalement, j'ai découvert que cela s'appelait à partir de WebCoreThread (sous-classe de Runnable ), qui est instancié avec un nouveau Thread ici .

    Quelle aventure! Alors, même si je ne peux vraiment pas dire avec certitude ce qui se passe avec toutes ces parties mobiles, je suis assez confiant pour dire que cette méthode n'est pas synchrone et envoie un message au thread de travail WebView. J'espère que cela à du sens!

    Si oui, comment puis-je savoir combien de temps devrais-je attendre pour appeler mon objet?

    Malheureusement, je ne connais pas la réponse à cela. Je cherchais cette question exacte et je trouvai cette question sur StackOverflow au cours de mes Googling. Je pense que vous avez les options suivantes, dont certaines sont plus agréables ou plus simples que d'autres:

    1) Just Thread.sleep pour 100 ms ou quelque chose entre addJavascriptInterface et loadUrl("javascript:...") . Blech, je n'aime pas ça, mais c'est potentiellement le plus simple.

    2) Une autre possibilité est que vous pouvez appeler WebView.loadUrl avec un extrait de JavaScript qui teste spécifiquement si l'interface est définie et capture le ReferenceError qui est lancé s'il n'est pas encore défini. Cependant, comme vous l'avez peut-être supposé, ce type consiste à ajouter une interface JavaScript à la WebView!

    3) Appelez WebView.setWebChromeClient place, et WebView.setWebChromeClient l' alert() JavaScript alert() ou console.log place. À partir de mes expériences, cette méthode est synchrone, donc il n'y a pas de retard. (J'ai confirmé cela dans la source, mais je laisserai les détails comme un exercice pour le lecteur). Vous devriez probablement trouver une chaîne spéciale pour appeler l' alert et vérifier s'il-vous-en à l' onJsAlert , donc vous n'êtes pas seulement en train d'attraper toutes les alert() A.

    Désolé pour la durée de cette réponse, j'espère que cela vous aidera. Bonne chance!

    Assurez-vous que vos objets Javascript déclarés dans votre HTML / Javascript que vous avez besoin d'accéder à partir de Java sont déclarés globaux sinon ils seront très probablement collectés. J'ai un code qui le fait (où Android est mon interface ajoutée avec addJavascriptInterface):

     <script> var cb = function(location) { alert('location is ' + location); } Android.getLocation('cb'); </script> 

    La méthode getLocation appelle Android MarketManager.requestSingleUpdate qui invoque alors le rappel lorsque le FlagListener déclenche.

    Sans la "var", je trouve que, au moment où la recherche d'emplacement invoque le rappel, la fonction de rappel a été collectée.

    (Copié de ma réponse sur une question similaire )

    J'ai pris la mise en œuvre de Jason Shah et de M. S comme élément de base pour ma correction et je l'ai amélioré considérablement.

    Il y a trop de code pour mettre dans ce commentaire, je vais simplement lier.

    Les points clés sont les suivants:

    • S'applique à toutes les versions de Gingerbread (2.3.x)
    • Les appels de JS vers Android sont maintenant synchrones
    • Il ne faut plus mapper manuellement les méthodes d'interface
    • Correction de la possibilité de séparer les séparateurs de cordes
    • Beaucoup plus facile à modifier les noms de signature et d'interface JS
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.