2011-03-15 36 views
3

我想將我的外部JS文件(包含在資產目錄中)注入到WebView中並在之後調用它。在Android WebView中注入外部JS文件並將其命名爲

這是我用它注入代碼:

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()"); 
    } 
}); 

當我打印我的Web視圖的全部內容,我可以看到的src ='文件的腳本標籤:// android_asset/js_demo。 js'確實被插入,但調用函數jsDemo什麼都不做。

注意:函數jsDemo包含在js_demo.js中,並且沒有做任何聰明的事情,只是改變了某些跨度的顏色。它可以正常工作,因爲我在瀏覽器中測試它。

我確信我犯了錯誤給js文件的路徑,但我不知道如何改變它,以使其工作。任何幫助將不勝感激。

回答

2

爲什麼不直接在文件中讀取並通過loadUrl("javascript:...)直接執行?

+1

是的,這是可以做到這樣,我同意,但我一直在尋找一些更「優雅」 , 有點。 我只是想從單獨的文件加載所有的JS,就像我在網頁上做的一樣。 – ezamur 2011-03-15 19:13:24

+0

@ezamur:如果我必須猜測,假設您的內容是從Web加載的,那麼您將遇到跨域問題。 – CommonsWare 2011-03-15 19:18:48

+0

我也想過這個問題,但這不是這種情況,因爲我試圖加載資產目錄中包含的JS文件。 – ezamur 2011-03-16 07:31:35

0

這是我最終做到的。我使用的內容://協議,併成立了ContentProvider的處理返回一個文件描述符到系統

這裏是我的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"); 
    } 
} 
在清單

我定義了供應商:

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

這裏是JavaScriptø注入到網頁視圖:

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); " 
      + "})();"); 

和這裏是myjavascriptfile.js(爲例):

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

}

+0

,你發現這比使用loadUrl注入js更「優雅」? – 2013-11-08 07:41:40

+0

是在企業級你會有很多的JS。這將它保存在一個單獨的文件中。 – j2emanue 2013-11-14 16:55:14

+0

您可以在注入之前從資產文件中讀取js - 如果需要遍歷整個文件夾,請僅選擇.js文件 – 2013-11-15 10:27:28

1

感謝您的反饋傢伙。我嘗試了大部分的建議,這裏是我如何爲webkit加載的每個網頁注入一個.js文件。

  1. 讀取本地js文件爲字符串。
  2. 字符串追加到script.text一個重寫網頁視圖onPageFinished內創建具有類型text/javascript
  3. 呼叫javascript: (function() { <programmatically formatted string dynamically creating webpage script element >})()"一個文檔元素之後。

驗證在Android 4.0.3-4.0.4 Ice Cream Sandwich的(API級別15)個工作

相關問題