Javaで実装されたjavascriptインターフェイスがあります。これは、webviewにロードされたjavascriptコードによって呼び出されます。
JS Inside WebView:
Android.myFunction(function(data){
console.log(data);
});
Java:
public class JavaScriptInterface {
Context context;
WebView webView;
JavaScriptInterface(Context c, WebView w) {
context = c;
webView = w;
}
public void myFunction(String callback) {
//when I log callback, it is "undefined"
String someData = "Yay for data";
String js =
"javascript:(function() { "
+ "var callback = " + callback + ";"
+ "callback('" + someData + "');"
+ "})()";
webView.loadUrl(js);
}
}
Webviewによってロードされる文字列は、最終的に次のようになります。
javascript:(function() {var callback = undefined; undefined();})()
私にはいくつかのアイデアがあります:
a。 JSで文字列としてコールバックを作成します。
b。 Android.myFunction()に渡す前に、コールバックのtoString()を呼び出します。
私の質問は、これを行う最善の方法は何ですか?オブジェクトをAndroidに渡すだけで、魔法のように動作します。明らかにそうではありません。;)次の最善の方法は何ですか?
指定した方法で関数を渡すことはできません。関数をAndroid.myDataに渡しますが、Android.myDataは文字列を受け取ります。代わりに、おそらく
var myCallback = console.log;
Android.myFunction("myCallback");
まだコールバックにデータを渡していないという問題があります。それはあなたの質問に直接関連していませんが、同じキャスト/文字列の問題があるため問題になります(JSON経由で解決可能ですが、Androidその部分を処理しました)。
最後に、おそらくjavascript:文字列を
String js = "javascript:" + callback + "();";
しかし、もちろん、最初にテストしてください;)
同様の問題がありました:Webアプリ内から、ネイティブAndroid確認ダイアログを使用したいと思います。これは、確認ダイアログの結果とともにAndroidからJavascript部分にコールバックする必要があることを意味します。
私はこれを次のように解決しました:
_function foo() {
// user confirmation needed
var dataString = <encode data into string>;
MyClient.showConfirmationDialog('myCallBackFunction', dataString, 'A title', 'A message');
}
_
上記のコードは、Android javascriptインターフェイスを呼び出します(以下を参照)。 javascriptはコールバックメソッドmyCallbackFunction()
を提供し、その名前はパラメーターとしてAndroidに渡されます(データ文字列、タイトル、メッセージとともに)。コールバック関数は次のようになります。
_function myCallbackFunction(dataString, result) {
var data = <decode data from dataString>;
if (result) {
// user has confirmed
} else {
// user has denied
}
}
_
Android側では、最初にアクティビティのonCreate()
メソッドでJavascriptインターフェイスをアクティブにします。
_public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = new WebView(this);
setContentView(webView);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new MyJavascriptInterface(webView), "MyClient");
}
_
MyJavascriptInterface
の実装は、対応するAndroidダイアログを作成し、結果をjavascriptに返します。
_ WebView webView;
public MyJavascriptInterface(WebView w) {
this.webView = w;
}
@JavascriptInterface
public void showConfirmationDialog(final String callbackFunction, final String data, String title,
String message) {
Dialog.OnClickListener positiveListener = new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
webView.loadUrl("javascript:" + callbackFunction + "('" + data + "', true)");
}
};
Dialog.OnClickListener negativeListener = new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
webView.loadUrl("javascript:" + callbackFunction + "('" + data + "', false)");
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(title).setMessage(message).setPositiveButton("Ok", positiveListener)
.setNegativeButton("Cancel", negativeListener).setCancelable(false);
builder.create().show();
}
_
コールバック関数の名前をAndroidに渡すと、確認ダイアログへの複数の呼び出しを使用できます。各呼び出しには、実際のアクションを実行する独自の関数が装備されています。データ文字列には、アクションの実行に必要なすべてのデータが含まれます(Jsonエンコードされたオブジェクトを含めることもできます)。
WebViewでは、ウィンドウコンテキストでJavaScriptを直接実行できます。したがって、リソースURLを介してJavaScriptを渡す必要はありません。
これは、データをhtmlページに戻す承認済みの方法です
/**
* This is an approved way to pass data back to the html page
*/
webView.evaluateJavascript("alert('pass here some ...')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
}
});
公式文書の詳細
現在表示されているページのコンテキストでJavaScriptを非同期に評価します。 null以外の場合、| resultCallback |その実行から返された結果で呼び出されます。このメソッドはUIスレッドで呼び出す必要があり、コールバックはUIスレッドで行われます。
互換性に関する注意。 N以降を対象とするアプリケーションでは、空のWebViewからのJavaScript状態は、loadUrl(String)などのナビゲーション間で保持されなくなりました。たとえば、loadUrl(String)を呼び出す前に定義されたグローバル変数と関数は、読み込まれたページに存在しません。アプリケーションは、代わりにaddJavascriptInterface(Object、String)を使用して、ナビゲーション間でJavaScriptオブジェクトを永続化する必要があります。