2011-03-15 5 views
3

J'essaie d'injecter mon fichier JS externe (contenu dans le répertoire des assets) dans WebView et de l'appeler par la suite.Injecter un fichier JS externe dans Android WebView et l'appeler

C'est le code que j'utilise pour l'injecter:

webView.setWebViewClient(new WebViewClient() { 
    @Override 
    public void onPageFinished(WebView view, String url) { 
     super.onPageFinished(view, url); 
     webView.loadUrl("javascript: (function() { " 
      + "var script=document.createElement('script');" 
      + "script.type='text/javascript';script.src='file://android_asset/js_demo.js';" 
      + "document.getElementsByTagName('head').item(0).appendChild(script);" 
      + "})()"); 
     webView.loadUrl("javascript: jsDemo()"); 
    } 
}); 

Lorsque j'imprime tout le contenu de mon point de vue web, je peux voir que balise de script avec src = 'file: // android_asset/js_demo. js 'est en effet inséré, mais l'appel de la fonction jsDemo ne fait rien.

REMARQUE: La fonction jsDemo est contenue dans js_demo.js et ne fait rien d'intelligent, il suffit de changer la couleur de l'intervalle. Ca marche bien puisque je l'ai testé dans le navigateur.

Je suis convaincu que j'ai fait une erreur en donnant le chemin vers le fichier js, mais je ne suis pas sûr de savoir comment le changer pour le faire fonctionner. Toute aide serait appréciée.

Répondre

2

Pourquoi ne pas simplement lire dans le fichier et l'exécuter directement via loadUrl("javascript:...)?

+1

Oui, cela peut être fait de cette façon, je suis d'accord, mais je cherchais quelque chose de plus « élégant » , sorte de. Je voulais juste charger tous les JS à partir de fichiers séparés, tout comme je le ferais dans une page Web. – ezamur

+0

@ezamur: Si je devais deviner, vous êtes confronté à des problèmes inter-domaines, en supposant que votre contenu est chargé depuis le Web. – CommonsWare

+0

J'ai aussi pensé à ce problème, mais ce n'est pas le cas ici puisque j'essaye de charger le fichier JS contenu dans le répertoire des assets. – ezamur

0

Voici comment j'ai fini par le faire. J'ai utilisé le contenu: // protocole 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 i défini le fournisseur:

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

est ici le javascript o injectent 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 les myjavascriptfile.js (à titre d'exemple):

function changeBackground(color) { 
    document.body.style.backgroundColor = color; 

}

+0

et vous trouvez cela plus "élégant" que juste injecter le js en utilisant loadUrl? –

+0

Oui au niveau de l'entreprise, vous allez avoir beaucoup de JS. Cela le garde dans un fichier séparé. – j2emanue

+0

Vous pouvez lire les fichiers js à partir des fichiers d'actifs avant d'injecter - parcourez un dossier entier si vous le souhaitez, choisissez uniquement les fichiers .js –

0

Vous avez besoin de trois barres obliques après "file:"

1

Merci pour les gars de retour. J'ai essayé la plupart des suggestions et voici comment j'ai pu injecter un fichier .js pour chaque chargement de webkit sur une page web.

  1. Lire un fichier js local dans une chaîne.
  2. Append cette chaîne à script.text après avoir créé un élément de document avec le type text/javascript
  3. Appel javascript: (function() { <programmatically formatted string dynamically creating webpage script element >})()" l'intérieur d'un WebView surchargée onPageFinished.

travaillant sur Android Vérifié 4.0.3-4.0.4 Sandwich Ice Cream (niveau de l'API 15)

Questions connexes