Méthodes WebView sur la même erreur de thread

84

J'ai un programme Android (Java + html dans une vue Web). Je peux appeler du javascript au code Java. Mais l'inverse a cessé de fonctionner (après la mise à jour dans eclipse).

Alors c'est ce que j'essaye de faire

  • Faire une webview (travaillé)
  • appel en javascript vers AndroidFunction.test (); (travaillé)
  • la fonction java test () appelle webView.loadUrl ("javascript: helloBack ()"); (! ne fonctionne plus)

J'ai essayé de le laisser fonctionner avec WebView dans MainActivity, mais cela n'a pas fonctionné.

MainActivity.java

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        final WebView webView = (WebView)findViewById(R.id.webView);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebChromeClient(new WebChromeClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        javascr = new Javascript(this, webView);
        webView.addJavascriptInterface(javascr, "AndroidFunction");
        webView.loadUrl("file:///android_asset/www/index.html");

        ....
}

Javascript.java

public class Javascript {   
    Context cont;
    WebView webView;

    Javascript(Context c, WebView w) {
        cont = c;
        webView = w;
    }

    // function called in the javascript by AndroidFunction.test();
    public void test() {
          // Breaking point!!!
        webView.loadUrl("javascript:helloBack()");
    }

Erreur:

03-24 11:47:50.103: W/WebView(21026):   at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
03-24 11:47:50.103: W/WebView(21026):   java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper{41ab68f8} called on Looper{41bb70a8}, FYI main Looper is Looper{41ab68f8})

03-24 11:47:50.103: W/WebView(21026):   at android.webkit.WebView.checkThread(WebView.java:2063)
03-24 11:47:50.103: W/WebView(21026):   at android.webkit.WebView.loadUrl(WebView.java:794)
03-24 11:47:50.103: W/WebView(21026):   at com.example.hellobt.Javascript.test(Javascript.java:24)

03-24 11:47:50.103: W/WebView(21026):   at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
03-24 11:47:50.103: W/WebView(21026):   at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
03-24 11:47:50.103: W/WebView(21026):   at android.os.Handler.dispatchMessage(Handler.java:102)

03-24 11:47:50.103: W/WebView(21026):   at android.os.Looper.loop(Looper.java:137)
03-24 11:47:50.103: W/WebView(21026):   at android.os.HandlerThread.run(HandlerThread.java:61)

Merci d'avoir répondu. J'ai édité la fonction dans mon fichier Javascript comme ceci:

private void test(final String s) {
        webView.post(new Runnable() {
            public void run() {
                webView.loadUrl("javascript:" + s + ";");
            }
        });
        System.out.println("javscript done..");
    }
Johan Hoeksma
la source
Dans votre modification, vous mentionnez que vous avez modifié votre code en fonction de (l'une des) réponses, ce qui donne l'impression que cela n'a toujours pas résolu votre problème - mais il y a une réponse acceptée. Je vous suggère de préciser si cela a résolu le problème ou non (ou autrement, simplement annuler la modification).
Tom le

Réponses:

212

La méthode JavaScript est exécutée sur un thread d'arrière-plan (c'est-à-dire non-UI). Vous devez appeler toutes les méthodes associées à Android View sur le fil d'interface utilisateur. Vous pouvez réaliser ce dont vous avez besoin avec:

mWebView.post(new Runnable() {
    @Override
    public void run() {
        mWebView.loadUrl(...).
    }
});

Qui publiera la tâche à exécuter sur le fil de l'interface utilisateur.

ksasq
la source
où avez-vous ajouté l'extrait (mWebView) à votre code d'origine?
Bowie
Dans la fonction test (), voir ma question ci-dessus.
Johan Hoeksma
Et si vous devez renvoyer une valeur? par exemple, retourner webview.getUrl? stackoverflow.com/questions/29748782/… @JohanHoeksma
Suresh Subedi
Savez-vous comment et quand ce problème est survenu? Dans mon Nexus 5X (Android 7.1.1), ça va, mais certains appareils sont tombés en panne.
Ellie Zou
comment passer une variable? J'ai essayé d'ajouter une variable dans mWebView.loadUrl ("javascript: test ('" + MyData + "');"); mais la valeur n'est jamais passée à javascript!
user1788736
14

Dans mon cas, rien n'a été affiché dans une WebView, donc je préfère une autre manière:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        final WebView webView = (WebView) findViewById(R.id.map);
        webView.loadDataWithBaseURL(...);
    }
});
CoolMind
la source
3

Cela peut être résolu en utilisant la méthode de publication. Veuillez parcourir le code ci-dessous.

 m_targetView.post(new Runnable() {
                        @Override
                        public void run() {
                            m_targetView.loadUrl(".....");
                        }
                    });
Akhil Ghatiki
la source
2

Version Java : vous devez utiliser l' interface Runnable et Post to Handler .

webView.post(new Runnable() {
          @Override
          public void run() {
             webView.loadUrl("file:///android_asset/www/index.html");
          }
       });

Version Kotlin :

webView.post(new Runnable {
   webView.loadUrl("file:///android_asset/www/index.html")
})
romain
la source