何度も尋ねられましたが、すべてを閲覧しましたが、まだ明確な答えはありませんでした。
質問の簡素化:Android Web-ViewにロードされたリモートWebページにローカルJavascriptファイル(アセットまたはストレージから)を挿入できますか?このようなファイルをローカルWebページに挿入できることはわかっています。 (アセットHTML)Webビューにロードされます。
なぜこれが機能する必要があるのですか? :JsやCSSファイルなどの大きなファイルを毎回ダウンロードすることを避けて、ブラウジングエクスペリエンスを高速化します。 Web-Viewキャッシングを避けたい。
ローカルアセット(例えば、assets/js/script.js)からローカルJavascriptファイルのインジェクションを「強制」し、「ローカルリソースのロードを許可しない:file:/// Android_assets/js」を回避する方法があります/script.js ...」の問題。
Javascriptファイルを印刷可能な文字列として表現するための追加のBASE64エンコード/デコードを使用した、別のスレッド( Android webview、javascriptファイルをアセットフォルダーに読み込む )で説明したものに似ています。
Android 4.4.2、APIレベル19の仮想デバイスを使用しています。
コードスニペットは次のとおりです。
[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");
...
はい、shouldInterceptRequest()を使用して、リモートURLロードをインターセプトし、ローカルに保存されたコンテンツを返すことができます。
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);
}
}
});
loadUrlは、古いバージョンでのみ動作します evaluateJavascript
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"}
}
});
evaluateJavascript
の使用には注意してください。Javascriptで構文エラーまたは例外がスローされると、onReceiveValue
がnullで呼び出されます。 SDK 19と下位の両方をサポートする最も一般的な方法は次のように思われます: JavaView
また、何らかのブラウザ機能にひどく必死になった場合(私の場合、DRMをうまく機能させる方法がわからない)、通常のクロム内でブックマークレットを使用できます。これは、アドレスバーにブックマーク名を入力した場合にのみ機能しますしかし動作し、javascriptを注入します。
また、デフォルトのWebView
では、JavaScriptアラートを使用して何かをテストすることはできず、表示されないことに注意してください。また、デフォルトでは「ビデオ」(html <video>タグなど)はデフォルトでは「本当に機能」せず、DRMビデオもデフォルトでは機能しないことに注意してください。これらはすべて設定オプションです:\