Android WebViewを介してJavaScriptからJava関数を呼び出す

Call Java function from JavaScript over Android WebView


質問 written by Community @2017-05-23 10:31:15Z

: 69 : 3 : 62

私は自分のAndroidアプリでいくつかのJavaコードに同期呼び出しをしたいです。

私はこのソリューションを使用しています: https//stackoverflow.com/a/3338656

私のJavaコード:

final class MyWebChromeClient extends WebChromeClient {
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            Log.d("LogTag", message);
            result.confirm();
            return true;
        }
    }

私のJavaScriptコード:

<html>
<script>
function java_request(){
    alert('test');
}
</script>
<body>
<h2>Welcome</h2>
<div id="area"></div>
<form>
<input type="button" value="java_call" onclick="java_request()">
</form>
</body>
</html>

java_callボタンをタップすると、ボタンが押された状態になります。 コンソールログに'test'れます。 ここまではすべて正常です。

問題は、ボタンが通常の状態に戻らないことです。 それは押された状態にとどまります。 JavaScriptの実行が壊れているのでしょうか。

ボタンが通常の状態に戻らないのはなぜですか?

回答 1 written by Pablo Cegarra @2019-01-09 14:01:41Z
95

私はこれがジャバスクリプトにジャバコードを実行させるための最良の解決策であるとは思わない。 こちらを参照してください。

JavaScriptを介して呼び出し可能にするためにネイティブコードをHTMLに公開する場合は、Webビューの宣言について次の手順を実行します。

JavaScriptInterface jsInterface = new JavaScriptInterface(this);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(jsInterface, "JSInterface");

クラスJavaScriptInterface宣言しJavaScriptInterface

Declare the class JavaScriptInterface:

私はビデオを再生するための単一の関数を宣言していますが、あなたはあなたが望むものなら何でもすることができます。

最後に、単純なJavaScript呼び出しを介してWebViewコンテンツでこれを呼び出します。

I am declaring a single function for playing a video, but you can do whatever you want.

例は私のもう一つの答え、ビデオの再生についてのものですが、十分に説明しているはずです。

編集 @ CedricSoubrieのコメントによると:アプリケーションのターゲットバージョンが17以上に設定されている場合は、Webビューにエクスポートする各メソッドの上に注釈@JavascriptInterfaceを追加する必要があります。

コメント 1

情報をありがとう、私はこの解決策を見ました。この解決策のための2.3.Xにバグがあるので、私はそれを使いたくありません。回避策は非常に素晴らしかったです。

written by ozkolonur @2012-05-02 16:22:29Z

コメント 2

@ ozkolonur私はAndroid 2.2以降のすべてのバージョンでこれを使っていますが、バグは見たことがありません。あなたはそれが何であるかを共有できますか。リンクも大歓迎です。

written by ボリス・ストランドジェフ @2012-05-03 06:54:24Z

コメント 3

code.google.com/p/android/issues/detail?id=12987

written by ozkolonur @2012-05-03 11:10:48Z

コメント 4

@ Maarten:実際にはこれが私の答えの唯一のエラーではありませんでした。私は今それを修正しました。

written by ボリス・ストランドジェフ @2012-12-19 14:28:30Z

コメント 5

@BorisStrandjev非常に明確な答え!バージョン17以降のJavaScriptから利用できるようにするには、 "@ JavascriptInterface"アノテーションを追加する必要があります。出典: developer.android.com/guide/webapps/webview.html

written by CedricSoubrie 2013 @2013-04-21 03:39:13Z

回答 2 written by R. Maynard @2014-06-30 16:12:54Z
1

あなたの関数は 'true'を返します。 それはあなたのHTMLコードの 'onclick'プロパティをtrueに等しくします、従ってボタンは 'clicked'のままです。

回答 3 written by tyolab @2018-03-12 06:11:01Z
1

" YourJavaScriptInterface "クラスで定義されたメソッドは、公開したい各メソッドに "@JavascriptInterface"というアノテーションを付けることを忘れないでください。そうしないと、メソッドはトリガーされません。

たとえば、次のコードは、Webビューページからの呼び出し用のGoogle Cloud Print JavaScriptインターフェイスからのものです。

        final class PrintDialogJavaScriptInterface {
        @JavascriptInterface
        public String toString() { return JS_INTERFACE; }

        @JavascriptInterface
        public String getType() {
            return cloudPrintIntent.getType();
        }

        @JavascriptInterface
        public String getTitle() {
            return cloudPrintIntent.getExtras().getString("title");
        }

        @JavascriptInterface
        public String getContent() {
            try {
                ContentResolver contentResolver = getActivity().getContentResolver();
                InputStream is = contentResolver.openInputStream(cloudPrintIntent.getData());
                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                byte[] buffer = new byte[4096];
                int n = is.read(buffer);
                while (n >= 0) {
                    baos.write(buffer, 0, n);
                    n = is.read(buffer);
                }
                is.close();
                baos.flush();

                return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
        }

        @JavascriptInterface
        public String getEncoding() {
            return CONTENT_TRANSFER_ENCODING;
        }

        @JavascriptInterface
        public void onPostMessage(String message) {
            if (message.startsWith(CLOSE_POST_MESSAGE_NAME)) {
                finish();
            }
        }
    }