Android的webview,在资产文件夹中加载javascript文件
我见过这个问题已经问了很多次,但仍然无法让我的代码工作。Android的webview,在资产文件夹中加载javascript文件
我想我的WebView加载某些URL(比如www.google.com),然后应用存储在assets/jstest.js
一些JavaScript,它包含以下内容:
function test(){
document.bgColor="#00FF00"; //turns to green the background color
}
这里的地方我尝试加载在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); "
+ "})()");
}
我知道这里的JavaScript的工作,因为背景颜色居然变成红色,但由于某些原因,它不会加载jstest.js
。我认为问题可能出现在文件路径中(我确定其他所有javascript代码都是正确的),但它对我来说看起来是正确的。该文件位于正确的文件夹中。
我错过了什么?
编辑:
由于WebResourceResponse
类是只与API级别11个可用,这里就是我最终想通了。
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 + ")()");
}
与jstest.js
只是包含:
function() {
document.bgColor="#00FF00";
}
我想同样的事情,加载书签(JavaScript代码在你使用loadURL()调用)到第三方网页。我的小书签还依赖于其他资源(javascript和css文件),它们不会使用file:/// android_asset URL进行加载。
这是因为该页面的安全上下文仍然是,例如,http://www.google.com,并且不允许访问file:URL。如果您提供/覆盖WebChromeClient.onConsoleMessage(),您应该能够看到错误。
我结束了一个杂牌组装电脑,我改变了书签的资产引用一个假的URL方案,如:
asset:foo/bar/baz.js
,并增加了WebViewClient.shouldInterceptRequest()重写它看起来从这些资产,并加载它们使用AssetManager.open()。
我不喜欢这个问题的一件事是资产:计划对我的视图加载的任何页面上的任何第三方HTML/Javascript都是开放的,让他们可以访问我的应用程序的资产。
我没有尝试的一种替代方法是使用data:URL将子资产嵌入到小书签中,但这可能会变得笨拙。
我更喜欢它,如果有一种方法来操纵安全上下文只是 JS书签我加载loadUrl(),但我找不到像这样的东西。
这里有一个片段:
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;
}
}
也许你可以有资产作为 'HTML/JavaScript的模板'。你可以结合不同的这些文本来源和字符串逻辑来组成你想要加载到WebViewer中的html。然后,您使用.loadData而不是.loadUrl
我正在使用它,它似乎工作得很好。
希望它有帮助!
我认为cordova的iceam cream webview客户端可以做你想做的事情。
如果这是记录在某个地方,那就太好了,但据我所知,它不是。
看看科尔多瓦的Android github上: https://github.com/apache/incubator-cordova-android/blob/master/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
这里是我终于实现了它。我使用的内容://协议,并成立了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;
}
首先,感谢您的回答! – Jacob 2011-04-14 14:37:10
好的,所以它看起来没有这个问题的“干净”解决方案..我想过编写所有javascript代码insieme loadUrl(),这将工作没有问题,但它肯定不会是最好的选择。 所以,我正在尝试你的kludge,但我似乎无法重写shouldInterceptRequest() - 我无法导入WebResourceResponse类 - 你能帮我张贴一些代码吗? – Jacob 2011-04-14 14:52:15
雅各布,看我的编辑,我添加了一个片段。 – dimitris 2011-04-14 17:20:58