もう一度元気にしましょう。 JavaScriptからC#コードを呼び出したいとします。ちょうどそれほど気をつけなければ、それはかなり簡単です。
まず、私たちのレイアウトXMLから始めましょう:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<WebView
android:id="@+id/web"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
今、私たちは自分自身をアプリケーションに取得することができます。
[Activity (Label = "Scratch.WebKit", MainLauncher = true)]
public class Activity1 : Activity
{
const string html = @"
<html>
<body>
<p>This is a paragraph.</p>
<button type=""button"" onClick=""Foo.run()"">Click Me!</button>
</body>
</html>";
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
WebView view = FindViewById<WebView>(Resource.Id.web);
view.Settings.JavaScriptEnabled = true;
view.SetWebChromeClient (new MyWebChromeClient());
view.LoadData (html, "text/html", null);
view.AddJavascriptInterface(new Foo(this), "Foo");
}
}
Activity1.html
は、我々が表示さしようとしているHTMLコンテンツです。唯一の興味深い点は、/button/@onClick
属性を指定して、JavaScriptフラグメントFoo.run()
を呼び出すことです。メソッド名( "run")に注意し、小文字の「r」で始まることを確認してください。私たちはこれに後で戻ります。
ノートの他の三つの点があります。
- 我々は
view.Settings.JavaScriptEnabled=true
でJavaScriptを有効にしてください。これがなければJavaScriptを使用できません。
view.SetWebChromeClient()
のインスタンスをMyWebChromeClient
クラス(後で定義)のインスタンスと呼びます。これは「カーゴ・カルト・プログラミング」のビットです:もしそれを提供しなければ、物事は機能しません。どうしてか分かりません。私たちが代わりにview.SetWebChromeClient(new WebChromeClient())
一見同等の操作を行う場合は、実行時にエラーが発生します。
E/Web Console(4865): Uncaught ReferenceError: Foo is not defined at data:text/html;null,%3Chtml%3E%3Cbody%3E%3Cp%3EThis%20is%20a%20paragraph.%3C/p%3E%3Cbutton%20type=%22button%22%20onClick=%22Foo.run()%22%3EClick%20Me!%3C/button%3E%3C/body%3E%3C/html%3E:1
これはどちらか私には意味がありません。
- 私たちはと呼んで、JavaScript名
"Foo"
をクラスFoo
のインスタンスに関連付けます。
今、私たちはMyWebChromeClient
クラス必要があります。
class MyWebChromeClient : WebChromeClient {
}
注それは、実際には何もしませんので、それだけでWebChromeClient
インスタンスを使用すると、物事が失敗する原因となることを、すべてのより多くの興味深いことを。: -/
最後に、私たちは「面白い」ビットを取得、"Foo"
JavaScript変数と関連していた上Foo
クラス:Run()
メソッドが呼び出されたときに
class Foo : Java.Lang.Object, Java.Lang.IRunnable {
public Foo (Context context)
{
this.context = context;
}
Context context;
public void Run()
{
Console.WriteLine ("Foo.Run invoked!");
Toast.MakeText (context, "This is a Toast from C#!", ToastLength.Short)
.Show();
}
}
それだけで短いメッセージを示し。これはAndroidのビルドプロセスのためのモノの間に
仕組み
は、Android Callable Wrappersはすべてオーバーライドされたメソッドおよびすべての実装のJavaインタフェースを宣言し、すべてのJava.Lang.Object
サブクラスのために作成されます。これはAndroidの呼び出し可能ラッパーで、その結果、上記Foo
クラスを含む:
package scratch.webkit;
public class Foo
extends java.lang.Object
implements java.lang.Runnable
{
@Override
public void run()
{
n_run();
}
private native void n_run();
// details omitted for clarity
}
view.AddJavascriptInterface(new Foo(this), "Foo")
が呼び出されたとき、これは、C#タイプではJavaScript "Foo"
変数を関連付けるありませんでした。これは、JavaScript "Foo"
変数を、C#タイプのインスタンスに関連付けられたAndroid Callable Wrapperインスタンスに関連付けました。 (ああ、回り道...)
今、私たちは前述の "squinting"になります。 C#Foo
クラスはJava.Lang.IRunnable
インターフェイスを実装しました。これはjava.lang.Runnable
インターフェイスのC#バインディングです。 Android Callable Wrapperはこうしてそれがjava.lang.Runnable
インターフェイスを実装していると宣言し、Runnable.run
メソッドを宣言します。 Android、つまりAndroidのJavaScriptは、C#の種類を「認識」しません。代わりにAndroid Callable Wrappersが表示されます。したがって、run()
メソッド、ではなく、のRun()
メソッドを宣言するために、JavaScript/JavaScriptがアクセスするタイプであるため、JavaScriptコードはFoo.Run()
(大文字の 'R')を呼び出さず、Foo.run()
(小文字の「r」)を呼び出しています。
JavaScriptがFoo.run()
を起動すると、その後、Androidの呼び出し可能ラッパーscratch.webview.Foo.run()
メソッドはJNIで喜びを通して、本当にあなたが最初の場所でやってみたかったのすべてであるFoo.Run()
C#メソッドの実行中に結果呼び出されます。
私はrun()を好きではありません!
JavaScriptメソッドがrun()
であることが気に入らない場合や、パラメータなどを追加する必要がある場合、世界ははるかに複雑になります(少なくともAndroid 4.2のMonoと[Export]
のサポートまで)。
- 必要な名前と署名を提供する既存のバインドされたインターフェイスまたは仮想クラスメソッドを検索します。その後、メソッドをオーバーライドしてインターフェイスを実装してください。上の例のように見えます。
- 独自のJavaクラスをロールバックします。詳細については、monodroid mailing listにお尋ねください。この回答は長くなってきています。
これは確かに良い硬い飲み物に値します! –
答えをありがとう!非常に詳細 – d10sfan
IRunnableが必要ですか、それとも元の質問に含まれているだけですか? api 17の@JavascriptInterfaceの新しい要件はどのようにソリューションに影響しますか? – hultqvist