ホームページ > ウェブフロントエンド > jsチュートリアル > Android における Java と JavaScript の相互作用の詳細な説明

Android における Java と JavaScript の相互作用の詳細な説明

黄舟
リリース: 2017-03-15 17:30:58
オリジナル
1689 人が閲覧しました

Android は、Web ページを処理するための非常に強力な WebView コントロールを提供します。Web ページでは、JavaScript も非常に重要なスクリプトです。この記事では、JavaコードとJavaScriptコード間の相互呼び出しを実装する方法を紹介します。

実装方法

Javaとjsのやりとりを実現するととても便利です。通常は次の手順のみが必要です。

  • WebView は JavaScript スクリプトの実行を有効にします

  • WebView は、JavaScript 呼び出しの対話型インターフェイスを設定します。

  • クライアントと Web ページは、相互に呼び出すコードを記述します。

このサンプルコード

説明の便宜上、すべてのコードを最初に掲載しています

Javaコード

package com.example.javajsinteractiondemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends Activity {
  private static final String LOGTAG = "MainActivity";
  @SuppressLint("JavascriptInterface")
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      final WebView myWebView = (WebView) findViewById(R.id.myWebView);
      WebSettings settings = myWebView.getSettings();
      settings.setJavaScriptEnabled(true);
      myWebView.addJavascriptInterface(new JsInteration(), "control");
      myWebView.setWebChromeClient(new WebChromeClient() {});
      myWebView.setWebViewClient(new WebViewClient() {

          @Override
          public void onPageFinished(WebView view, String url) {
              super.onPageFinished(view, url);
              testMethod(myWebView);
          }

      });
      myWebView.loadUrl("file:///android_asset/js_java_interaction.html");
  }

  private void testMethod(WebView webView) {
      String call = "javascript:sayHello()";

      call = "javascript:alertMessage(\"" + "content" + "\")";

      call = "javascript:toastMessage(\"" + "content" + "\")";

      call = "javascript:sumToJava(1,2)";
      webView.loadUrl(call);

  }

  public class JsInteration {

      @JavascriptInterface
      public void toastMessage(String message) {
          Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
      }

      @JavascriptInterface
      public void onSumResult(int result) {
          Log.i(LOGTAG, "onSumResult result=" + result);
      }
  }

}
ログイン後にコピー

フロントエンドWebコード

<html>
<script type="text/javascript">
    function sayHello() {
        alert("Hello")
    }

    function alertMessage(message) {
        alert(message)
    }

    function toastMessage(message) {
        window.control.toastMessage(message)
    }

    function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
    }
</script>
Java-Javascript Interaction In Android
</html>
ログイン後にコピー

呼び出し例

jsはJavaを呼び出します

呼び出し形式はウィンドウです.jsInterfaceName.methodName(parameterValues ) この例では、注入インターフェイス名として control を使用します。

function toastMessage(message) {
  window.control.toastMessage(message)
}

function sumToJava(number1, number2){
   window.control.onSumResult(number1 + number2)
}
ログイン後にコピー

JavaはJSを呼び出します

webViewがjsを呼び出す基本形式はwebView.loadUrl("javascript:methodName(parameterValues)")です

パラメータなし、戻り値なしでjsを呼び出します関数

String call = "javascript:sayHello()";
webView.loadUrl(call);
ログイン後にコピー

パラメータ付きでjsを呼び出します関数

パラメータ値としての strings では二重引用符をエスケープする必要があることに注意してください。

String call = "javascript:alertMessage(\"" + "content" + "\")";
webView.loadUrl(call);
ログイン後にコピー

パラメータと戻り値を使用して js 関数を呼び出す

Android 4.4 より前の Android には、js 関数を直接呼び出して値を取得するメソッドが提供されていなかったため、それ以前は、Java が js メソッドを呼び出し、js メソッドを呼び出すという一般的な考え方がありました。 Java コードを再度呼び出して値を返します。

1.Javaがjsコードを呼び出し

String call = "javascript:sumToJava(1,2)";
webView.loadUrl(call);
ログイン後にコピー

2.js関数の処理をjavaメソッドを呼び出して結果を返す

function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
}
ログイン後にコピー

3.Javaがコールバックメソッドでjs関数の戻り値を取得

@JavascriptInterface
public void onSumResult(int result) {
  Log.i(LOGTAG, "onSumResult result=" + result);
}
ログイン後にコピー

4.4処理

後Android 4.4 では、evaluateJavaScript を使用するだけです。これは、戻り値を持つ js メソッドの簡単な対話型の例です

function getGreetings() {
      return 1;
}
ログイン後にコピー

Java コードを使用するときに呼び出すには、evaluateJavascript メソッドを使用します

private void testEvaluateJavascript(WebView webView) {
  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {

  @Override
  public void onReceiveValue(String value) {
      Log.i(LOGTAG, "onReceiveValue value=" + value);
  }});
}
ログイン後にコピー

結果を出力します

I/MainActivity( 1432): onReceiveValue value=1
ログイン後にコピー

注意

  • 上記は、戻り値を String に制限しています。単純な型の場合は、文字列に変換して返します。複雑な データ型 の場合は、文字列形式の json の形式で返すことをお勧めします。

  • evaluateJavascriptメソッドはUIスレッド(メインスレッド)で呼び出す必要があるため、onReceiveValueもメインスレッドで実行されます。

質問の回答

アラートがポップアップ表示できません

WebChromeClientを設定する必要はありません。次のコードに従って設定してください

myWebView.setWebChromeClient(new WebChromeClient() {});
ログイン後にコピー

キャッチされない参照エラー: functionNameが定義されていません

問題は、Webページのjsコードが存在しません読み込みが完了した後、jsメソッドが呼び出されます。解決策は、Web ページが読み込まれた後に js メソッドを呼び出すことです

myWebView.setWebViewClient(new WebViewClient() {

  @Override
  public void onPageFinished(WebView view, String url) {
      super.onPageFinished(view, url);
      //在这里执行你想调用的js函数
  }

});
ログイン後にコピー

Uncaught TypeError: Object [object Object] has no method

セキュリティ制限の問題

問題がバージョン 4.2 以降のマシンでのみ発生する場合上記の場合、それはシステムです。セキュリティ制限の問題です。 Android のドキュメントには次のように書かれています

注意: targetSdkVersion を 17 以降に設定している場合は、Web ページのコードで使用できるようにするメソッドに @JavascriptInterface アノテーションを追加する必要があります (メソッドはパブリックである必要もあります)。注釈を提供しない場合、Android 4.2 以降で実行している場合、Web ページからメソッドにアクセスできなくなります。

中国語の意味は

警告: プログラムのターゲット プラットフォームが 17 以降の場合、@JavascriptInterface アノテーション は、Web ページに公開される呼び出し可能なメソッドに追加する必要があります (このメソッドはパブリックである必要があります)。これを行わないと、Web ページはプラットフォーム 4.2 以降のメソッドにアクセスできなくなります。

2つの解決策
  • targetSdkVersionを17以降に設定し、@JavascriptInterfaceアノテーションを導入します

  • @JavascriptInterfaceという名前のアノテーションインターフェイスを自分で作成して導入します。このインターフェースを混同しないように注意してください。

@JavascriptInterface コードを作成してください

public @interface JavascriptInterface {

}
ログイン後にコピー

コード難読化の問題

難読化されていないコードが正常に実行される場合、難読化されたバージョンのコードはエラーを実行し、Uncaught TypeError: Object [object Object] has no method というプロンプトが表示されます。難読化された例外処理を行っていません。 難読化されたファイルに次のようなコードを追加します

-keep class com.example.javajsinteractiondemo$JsInteration {
    *;
}
ログイン後にコピー

すべての WebView メソッドは同じスレッドで呼び出す必要があります

フィルター ログでこの問題が発見されました。

E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread &#39;JavaBridge&#39;. 
All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, 
FYI main Looper is Looper (main, tid 1) {528712d4})
E/StrictMode( 1546):   at android.webkit.WebView.checkThread(WebView.java:2063)
E/StrictMode( 1546):   at android.webkit.WebView.loadUrl(WebView.java:794)
E/StrictMode( 1546):   at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
E/StrictMode( 1546):   at android.os.Handler.dispatchMessage(Handler.java:102)
E/StrictMode( 1546):   at android.os.Looper.loop(Looper.java:136)
E/StrictMode( 1546):   at android.os.HandlerThread.run(HandlerThread.java:61)
ログイン後にコピー

js 呼び出し後の Java コールバック スレッドはメインスレッドではありません。ログを出力すると、

ThreadInfo=Thread[WebViewCoreThread,5,main]
ログイン後にコピー

を確認できます。 上記の例外を解決するには、メイン スレッドに Webview 操作を追加するだけです。

りー


以上がAndroid における Java と JavaScript の相互作用の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート