Android webview, chargement du fichier javascript dans le dossier des actifs

j'ai vu cette question a été posée beaucoup de fois, mais ne peut toujours pas réussir à faire fonctionner mon code.

je veux que mon webview charge une URL (dire www.google.com) et ensuite appliquer un certain javascript stocké dans assets/jstest.js , qui contient ce qui suit:

function test(){
document.bgColor="#00FF00"; //turns to green the background color
}

et voici où j'essaie de charger le JS:

@Override  
public void onPageFinished(WebView view, String url){
    view.loadUrl("javascript:(function() { "
                + " document.bgColor='#FF0000';" //turns to red the background color
                + " var script=document.createElement('script'); "
                + " script.setAttribute('type','text/javascript'); "
                + " script.setAttribute('src', 'file:///android_asset/jstest.js'); "
                + " script.onload = function(){ "
                + "     test(); "
                + " }; "
                + " document.getElementsByTagName('head')[0].appendChild(script); "
                + "})()"); 
} 

je sais que le javascript fonctionne ici parce que la couleur de fond en fait, il tourne en rouge, mais pour une raison quelconque, il ne chargera pas jstest.js . Je pense que le problème pourrait être dans le chemin du fichier (je suis certain que toutes les autres lignes du code javascript sont correctes), mais il me semble correct. Et le fichier est dans le bon dossier.

Qu'est-ce que je rate?

MODIFIER :

depuis la classe WebResourceResponse est disponible uniquement avec le niveau D'API 11, Voici ce que j'ai compris à la fin.

public void onPageFinished(WebView view, String url){
        String jscontent = "";
        try{
            InputStream is = am.open("jstest.js"); //am = Activity.getAssets()
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);

            String line;
            while (( line = br.readLine()) != null) {
                jscontent += line;
            }
            is.close(); 
        }
        catch(Exception e){}
        view.loadUrl("javascript:(" + jscontent + ")()"); 
    } 

avec le jstest.js contenant simplement:

function() {
    document.bgColor="#00FF00";
}
15
demandé sur Brock Adams 2011-04-13 16:21:10

4 réponses

j'ai essayé la même chose, en chargeant un bookmarklet (le code javascript dans votre appel loadUrl ()) dans une page tierce. Mon bookmarklet dépend aussi d'autres ressources (javascript et fichiers css) qui ne se chargeraient pas avec une URL fichier:///android_asset.

c'est parce que le contexte de sécurité de la page est toujours celui de, par exemple, http://www.google.com , et qui n'est pas autorisé l'accès au fichier: URLs. Vous devriez être capable de voir les erreurs, si vous fournir / annuler un WebChromeClient.onConsoleMessage ().

j'ai fini avec un kludge où j'ai changé les références d'actifs de bookmarklet à un schéma D'URL bidon, comme:

asset:foo/bar/baz.js

et a ajouté un WebViewClient.shouldInterceptRequest () outrepasse qui les Recherche et les charge à partir des actifs en utilisant AssetManager.ouvrir.)(

une chose que je n'aime pas à propos de ce kludge est que l'asset: scheme est ouvert à tout tiers HTML / Javascript sur n'importe quelle page Ma vue se charge, leur donnant accès aux biens de mon application.

une alternative, que je n'ai pas essayé, serait d'intégrer les sous-actifs dans le bookmarklet en utilisant des données: URLs, mais cela peut devenir difficile.

je préférerais qu'il y ait un moyen de manipuler le contexte de sécurité de juste le bookmarklet JS que je charge dans loadUrl(), mais je ne trouve rien de tel.

voici un extrait:

import android.webkit.WebResourceResponse;
...
    private final class FooViewClient extends WebViewClient
    {
    private final String bookmarklet;
    private final String scheme;

    private FooViewClient(String bookmarklet, String scheme)
        {
        this.bookmarklet = bookmarklet;
        this.scheme = scheme;
        }

    @Override
    public void onPageFinished(WebView view, String url)
        {
        view.loadUrl(bookmarklet);
        }

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url)
        {
        if (url.startsWith(scheme))
            try
                {
                return new WebResourceResponse(url.endsWith("js") ? "text/javascript" : "text/css", "utf-8",
                        Foo.this.getAssets().open(url.substring(scheme.length())));
                }
            catch (IOException e)
                {
                Log.e(getClass().getSimpleName(), e.getMessage(), e);
                }

        return null;
        }
    }
7
répondu dimitris 2011-04-14 17:19:53

je pense que le client iceam cream webview de cordova fait exactement ce que vous voulez faire.

ce serait bien si cela était documenté quelque part mais, pour autant que je puisse voir, ce n'est pas le cas.

regardez l'androïde Github de cordova: https://github.com/apache/incubator-cordova-android/blob/master/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java

1
répondu nurieta 2013-04-17 16:26:07

, Voici comment j'ai fini par le faire. J'ai utilisé le contenu: / / protocol et mis en place un contentprovider pour gérer le retour d'un descripteur de fichier au système

Voici mon fileContentProvider:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;


import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;

public class FileContentProvider extends ContentProvider {
    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) {

        Log.d("FileContentProvider","fetching: " + uri);

        ParcelFileDescriptor parcel = null;

        String fileNameRequested = uri.getLastPathSegment();
        String[] name=fileNameRequested.split("\.");
        String prefix=name[0];
        String suffix=name[1];
       // String path = getContext().getFilesDir().getAbsolutePath() + "/" + uri.getPath();
        //String path=file:///android_asset/"+Consts.FILE_JAVASCRIPT+"

/*check if this is a javascript file*/

        if(suffix.equalsIgnoreCase("js")){
        InputStream is = null;
        try {
            is = getContext().getAssets().open("www/"+Consts.FILE_JAVASCRIPT);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }


        File file = stream2file(is,prefix,suffix);
        try {
            parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        } catch (FileNotFoundException e) {
            Log.e("FileContentProvider", "uri " + uri.toString(), e);
        }
        }
        return parcel;
    }

    /*converts an inputstream to a temp file*/

    public File stream2file (InputStream in,String prefix,String suffix) {
        File tempFile = null;
        try {
            tempFile = File.createTempFile(prefix, suffix);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        tempFile.deleteOnExit();

            FileOutputStream out = null;
            try {
                out = new FileOutputStream(tempFile);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 

            try {
                IOUtils.copy(in, out);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        return tempFile;
    }


    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public int delete(Uri uri, String s, String[] as) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }

    @Override
    public String getType(Uri uri) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }

    @Override
    public Uri insert(Uri uri, ContentValues contentvalues) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }

    @Override
    public Cursor query(Uri uri, String[] as, String s, String[] as1, String s1) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }

    @Override
    public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }
}

dans le manifeste j'ai défini le fournisseur:

<provider android:name="com.example.mypackage.FileContentProvider"
          android:authorities="com.example.fileprovider"
        />

voici le javascript o injecté dans le webview:

webView.loadUrl("javascript:(function() { "

           + "var script=document.createElement('script'); "
           + " script.setAttribute('type','text/javascript'); "
           + " script.setAttribute('src', 'content://com.example.fileprovider/myjavascriptfile.js'); "
      /*      + " script.onload = function(){ "
           + "     test(); "
           + " }; "
      */     + "document.body.appendChild(script); "
           + "})();");

et voici le myjavascriptfile.js (à titre d'exemple):

   function changeBackground(color) {
       document.body.style.backgroundColor = color;
   }
1
répondu j2emanue 2014-02-19 17:25:41

peut-être que vous pourriez avoir des actifs comme 'modèles html/javascript'. Vous pouvez combiner différentes de ces sources de texte et la logique de chaîne pour composer votre html désiré pour être chargé dans le WebViewer. Ensuite, vous utilisez .loadData au lieu de .loadUrl 151910920"

Je l'utilise seul et il semble fonctionner assez bien.

Espère que cela aide!

0
répondu Dani bISHOP 2011-10-31 07:38:14