私はAndroid webview
内で実行されているjavascript
ページに座っているいくつかのhtml
関数を呼び出そうとしています。コードが次に試みることは非常に簡単です - Androidアプリから、テストメッセージでjavascript
関数を呼び出します。この関数はinturnを使ってトースト経由でテストメッセージを表示するAndroidアプリにJava関数を呼び出します。
javascript
関数は次のようになります。
function testEcho(message){
window.JSInterface.doEchoTest(message);
}
WebViewから、私はjavascript
を以下の方法でうまく動かないように呼び出そうとしました。
myWebView.loadUrl("javascript:testEcho(Hello World!)");
mWebView.loadUrl("javascript:(function () { " + "testEcho(Hello World!);" + "})()");
javascript
でWebView
を有効にしました
myWebView.getSettings().setJavaScriptEnabled(true);
// register class containing methods to be exposed to JavaScript
myWebView.addJavascriptInterface(myJSInterface, "JSInterface");
そしてJava
クラス
public class JSInterface{
private WebView mAppView;
public JSInterface (WebView appView) {
this.mAppView = appView;
}
public void doEchoTest(String echo){
Toast toast = Toast.makeText(mAppView.getContext(), echo, Toast.LENGTH_SHORT);
toast.show();
}
}
私は自分が間違っているかもしれないことを見るためにグーグルを回って多くの時間を費やしました。私が見つけたすべての例はこのアプローチを使います。誰かがここで何か悪いことを見ますか?
編集:javascript
で参照され使用されている他の外部html
ファイルがいくつかありますが、それらが問題になる可能性はありますか?
私は問題が何であるかを把握しました:testEcho()パラメータに引用符がありません。これは私が働くように電話をかけた方法です:
myWebView.loadUrl("javascript:testEcho('Hello World!')");
KitKat以降では、loadUrlではなくevaluateJavascriptメソッドを使用して、以下のようなJavaScript関数を呼び出します。
if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.KitKat) {
webView.evaluateJavascript("enable();", null);
} else {
webView.loadUrl("javascript:enable();");
}
public void run(final String scriptSrc) {
webView.post(new Runnable() {
@Override
public void run() {
webView.loadUrl("javascript:" + scriptSrc);
}
});
}
JavaScriptメソッドを呼び出すためのNiceラッパーを作成しました。また、ログにJavaScriptエラーが表示されます。
private void callJavaScript(String methodName, Object...params){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("javascript:try{");
stringBuilder.append(methodName);
stringBuilder.append("(");
for (int i = 0; i < params.length; i++) {
Object param = params[i];
if(param instanceof String){
stringBuilder.append("'");
stringBuilder.append(param.toString().replace("'", "\\'"));
stringBuilder.append("'");
}
if(i < params.length - 1){
stringBuilder.append(",");
}
}
stringBuilder.append(")}catch(error){Android.onError(error.message);}");
webView.loadUrl(stringBuilder.toString());
}
これも追加する必要があります。
private class WebViewInterface{
@JavascriptInterface
public void onError(String error){
throw new Error(error);
}
}
そしてこのインターフェースをあなたのWebビューに追加してください。
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new WebViewInterface(), "AndroidErrorReporter");
はい、構文エラーがあります。あなたのJavascriptエラーとあなたのlogcatの印刷ステートメントを取得したい場合は、あなたのWebChromeClientでonConsoleMessage(ConsoleMessage cm)
メソッドを実装する必要があります。 Webコンソール(Inspect要素)のような完全なスタックトレースを表示します。これがその方法です。
public boolean onConsoleMessage(ConsoleMessage cm)
{
Log.d("Message", cm.message() + " -- From line "
+ cm.lineNumber() + " of "
+ cm.sourceId() );
return true;
}
実装後、Javascriptエラーとprintステートメント(console.log
)がlogcatに表示されます。
@Ilya_Gazman回答の修正
private void callJavaScript(WebView view, String methodName, Object...params){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("javascript:try{");
stringBuilder.append(methodName);
stringBuilder.append("(");
String separator = "";
for (Object param : params) {
stringBuilder.append(separator);
separator = ",";
if(param instanceof String){
stringBuilder.append("'");
}
stringBuilder.append(param.toString().replace("'", "\\'"));
if(param instanceof String){
stringBuilder.append("'");
}
}
stringBuilder.append(")}catch(error){console.error(error.message);}");
final String call = stringBuilder.toString();
Log.i(TAG, "callJavaScript: call="+call);
view.loadUrl(call);
}
正しくJS呼び出しを作成します。
callJavaScript(mBrowser, "alert", "abc", "def");
//javascript:try{alert('abc','def')}catch(error){console.error(error.message);}
callJavaScript(mBrowser, "alert", 1, true, "abc");
//javascript:try{alert(1,true,'abc')}catch(error){console.error(error.message);}
オブジェクトは正しく渡されないことに注意してください - しかし、引数として渡す前にそれらを直列化することができます。
また、エラーが発生する場所を変更し、コンソールログに転送しました。
webView.setWebChromeClient(new CustomWebChromeClient());
とクライアント
class CustomWebChromeClient extends WebChromeClient {
private static final String TAG = "CustomWebChromeClient";
@Override
public boolean onConsoleMessage(ConsoleMessage cm) {
Log.d(TAG, String.format("%s @ %d: %s", cm.message(),
cm.lineNumber(), cm.sourceId()));
return true;
}
}