web-dev-qa-db-fra.com

Android Web-View: Injecter un fichier Javascript local dans une page Web distante

Cela a été demandé à plusieurs reprises auparavant, j'ai parcouru tout, pas encore de réponses claires.

Question simplifiée: Est-il possible d’injecter un fichier Javascript local (depuis un actif ou un stockage) vers une page Web distante chargée dans une vue Web Android? Je sais qu’il est possible d’injecter de tels fichiers dans des pages Web locales (Assets HTML) chargées dans une vue Web.

Pourquoi ai-je besoin de ça pour fonctionner? : Pour rendre la navigation plus rapide, en évitant le téléchargement de fichiers plus volumineux tels que les fichiers Js et CSS. Je souhaite éviter la mise en cache Web-View.

33
sumit

Il existe un moyen de "forcer" l'injection de vos fichiers Javascript locaux à partir d'actifs locaux (par exemple, assets/js/script.js), et de contourner le "Non autorisé à charger la ressource locale: file: /// Android_assets/js /script.js ... 'numéro.

Il est similaire à ce qui est décrit dans un autre fil de discussion ( Webview Android, chargement du fichier javascript dans le dossier assets ), avec encodage/décodage BASE64 supplémentaire pour représenter votre fichier Javascript sous forme de chaîne imprimable.

J'utilise un périphérique virtuel Android 4.4.2, API de niveau 19.

Voici quelques extraits de code:

[assets/js/script.js]:

    'use strict';

    function test() {
       // ... do something
    }

    // more Javascript

[MainActivity.Java]:

    ...

    WebView myWebView = (WebView) findViewById(R.id.webView);
    WebSettings webSettings = myWebView.getSettings();

    webSettings.setJavaScriptEnabled(true);
    webSettings.setAllowUniversalAccessFromFileURLs(true);
    myWebView.setWebViewClient(new WebViewClient() {
       @Override
       public boolean shouldOverrideUrlLoading(WebView view, String url) {
          return false;
       }

       @Override
       public void onPageFinished(WebView view, String url) {
          super.onPageFinished(view, url);

          injectScriptFile(view, "js/script.js"); // see below ...

          // test if the script was loaded
          view.loadUrl("javascript:setTimeout(test(), 500)");
       }

       private void injectScriptFile(WebView view, String scriptFile) {
          InputStream input;
          try {
             input = getAssets().open(scriptFile);
             byte[] buffer = new byte[input.available()];
             input.read(buffer);
             input.close();

             // String-ify the script byte-array using BASE64 encoding !!!
             String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
             view.loadUrl("javascript:(function() {" +
                          "var parent = document.getElementsByTagName('head').item(0);" +
                          "var script = document.createElement('script');" +
                          "script.type = 'text/javascript';" +
             // Tell the browser to BASE64-decode the string into your script !!!
                          "script.innerHTML = window.atob('" + encoded + "');" +
                          "parent.appendChild(script)" +
                          "})()");
          } catch (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
          }
       }
    });

    myWebView.loadUrl("http://www.example.com");

    ...
49
Raffaele N.

loadUrl ne fonctionnera que dans l'ancienne version, utilisez assessmentJavascript

webview.evaluateJavascript("(function() { document.getElementsByName('username')[0].value='USERNAME';document.getElementsByName('password')[0].value='PASSWORD'; "+
"return { var1: \"variable1\", var2: \"variable2\" }; })();", new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String s) {
                    Log.d("LogName", s); // Prints: {"var1":"variable1","var2":"variable2"}
                }
            });
5
rinkesh

Oui, vous pouvez utiliser shouldInterceptRequest () pour intercepter le chargement d’URL à distance et renvoyer le contenu stocké local.

WebView webview = (WebView) findViewById(R.id.webview);

webview.setWebViewClient(new WebViewClient() {
    @Override
    public WebResourceResponse shouldInterceptRequest (final WebView view, String url) {
       if (url.equals("script_url_to_load_local")) {
           return new WebResourceResponse("text/javascript", "UTF-8", new FileInputStream("local_url")));
       } else {
           return super.shouldInterceptRequest(view, url);
       }
    }
});
5
cyberflohr

Faites attention en utilisant evaluateJavascript: s'il y a une erreur de syntaxe ou une exception renvoyée dans votre javascript, il appellera votre onReceiveValue avec une valeur null. Le moyen le plus courant de prendre en charge à la fois le SDK 19 et le bas semble être le suivant: Remplir le formulaire dans WebView avec Javascript

De plus, si vous êtes terriblement désespéré par une sorte de fonctionnalité de navigateur (dans mon cas, vous ne pourrez jamais trouver comment faire fonctionner le DRM), vous pouvez utiliser un bookmarklet en chrome normal, qui ne fonctionne que si vous tapez le nom du signet dans la boîte aux lettres. mais fonctionne et injecte du javascript.

Sachez également qu'avec la variable WebView par défaut, vous ne pouvez pas utiliser les alertes javascript pour tester quoi que ce soit, elles ne s'affichent pas. Sachez également que "vidéo" par défaut (comme les balises html <vidéo>) ne "fonctionne pas vraiment" par défaut et que la vidéo DRM ne fonctionne pas par défaut, elles sont toutes des options de configuration: \

0
rogerdpack