चलो एक कदम पीछे ले जाएं। आप जावास्क्रिप्ट से सी # कोड का आह्वान करना चाहते हैं। यदि आपको बस इतना झुकाव नहीं लगता है, तो यह काफी सरल है।
सबसे पहले, चलो हमारे लेआउट 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
विशेषता प्रदान करते हैं जो जावास्क्रिप्ट खंड Foo.run()
को आमंत्रित करता है। विधि का नाम नोट करें ("रन") और यह लोअरकेस 'आर' से शुरू होता है; हम बाद में इस पर वापस आ जाएंगे।
- हम
view.Settings.JavaScriptEnabled=true
साथ जावास्क्रिप्ट सक्षम: वहाँ नोट के तीन अन्य चीजें हैं। इसके बिना, हम जावास्क्रिप्ट का उपयोग नहीं कर सकते हैं।
हम 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
यह या तो मेरे लिए कोई मतलब नहीं है।
- हम के उदाहरण के साथ जावास्क्रिप्ट नाम
"Foo"
को संबद्ध करने के लिए view.AddJavascriptInterface()
पर कॉल करते हैं।
अब हम MyWebChromeClient
वर्ग की जरूरत है:
class MyWebChromeClient : WebChromeClient {
}
ध्यान दें कि यह वास्तव में कुछ भी नहीं है, इसलिए यह सभी को और अधिक दिलचस्प है कि सिर्फ एक WebChromeClient
उदाहरण का उपयोग करते हुए विफल जाने का कारण बनता है।: -:
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();
}
}
यह सिर्फ एक संक्षिप्त संदेश से पता चलता है जब Run()
विधि शुरू हो जाती है/
अंत में, हम "रोचक" बिट, Foo
वर्ग जो "Foo"
JavaScript वैरिएबल के साथ ऊपर जुड़े थे करने के लिए मिल ।
इस कैसे काम करता है
मोनो के दौरान एंड्रॉयड निर्माण प्रक्रिया के लिए, Android Callable Wrappers हर Java.Lang.Object
उपवर्ग है, जो सभी ओवरराइड तरीकों और सभी कार्यान्वित जावा इंटरफेस वाणी के लिए बनाई गई हैं। यह, ऊपर 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")
लागू किया गया था, इस जोड़ नहीं किया गया था सी # प्रकार के साथ जावास्क्रिप्ट "Foo"
चर। यह जावास्क्रिप्ट "Foo"
वैरिएबल को सी # प्रकार के उदाहरण से जुड़े एक एंड्रॉइड कॉलबल रैपर उदाहरण के साथ जोड़ रहा था। (आह, संकेत ...)
अब हम उपरोक्त "squinting" प्राप्त करते हैं। सी # Foo
वर्ग ने Java.Lang.IRunnable
इंटरफ़ेस को कार्यान्वित किया, जो java.lang.Runnable
इंटरफ़ेस के लिए सी # बाध्यकारी है। इस प्रकार एंड्रॉइड कॉलबल रैपर इस प्रकार घोषित करता है कि यह java.lang.Runnable
इंटरफ़ेस लागू करता है, और Runnable.run
विधि घोषित करता है। एंड्रॉइड, और इस प्रकार जावास्क्रिप्ट-इन-एंड्रॉइड, आपके सी # प्रकारों को "देख" नहीं देता है। वे इसके बजाय एंड्रॉइड कॉल करने योग्य लपेटें देखते हैं। नतीजतन, जावा स्क्रिप्ट कोड बुला रहा है नहीं Foo.Run()
(राजधानी 'आर'), यह Foo.run()
(लोअरकेस 'आर') कॉल कर रहा है, क्योंकि प्रकार है कि एंड्रॉयड/जावास्क्रिप्ट की पहुंच है एक run()
विधि वाणी, नहीं एक Run()
विधि।
जब जावास्क्रिप्ट Foo.run()
invokes और फिर Android प्रतिदेय आवरण scratch.webview.Foo.run()
विधि शुरू हो जाती है जो, खुशी JNI है कि के माध्यम से, Foo.Run()
सी # विधि के निष्पादन, जो वास्तव में है में परिणाम सभी आप पहली जगह में करना चाहता था।
लेकिन मुझे रन() पसंद नहीं है!
यदि आपको run()
नामक जावास्क्रिप्ट विधि पसंद नहीं है, या आप पैरामीटर, या अन्य चीजों की किसी अन्य संख्या को पसंद नहीं करते हैं, तो आपकी दुनिया अधिक जटिल हो जाती है (कम से कम एंड्रॉइड 4.2 और [Export]
समर्थन के लिए मोनो तक)। आपको दो चीजों में से एक करना होगा:
- मौजूदा बाध्य इंटरफ़ेस या वर्चुअल क्लास विधि खोजें जो आपके इच्छित नाम और हस्ताक्षर प्रदान करता है। फिर विधि को ओवरराइड करें/इंटरफ़ेस को कार्यान्वित करें, और चीजें ऊपर दिए गए उदाहरण के समान दिखती हैं।
- अपनी खुद की जावा क्लास रोल करें। अधिक जानकारी के लिए monodroid mailing list पर पूछें। यह जवाब लंबे समय तक हो रहा है।
जो निश्चित रूप से एक अच्छा कठोर पेय के योग्य है! –
उत्तर के लिए धन्यवाद! बहुत विस्तृत – d10sfan
क्या इरनेबल आवश्यक है या केवल मूल प्रश्न के रूप में शामिल है? api 17 में @JavascriptInterface की नई आवश्यकता समाधान को कैसे प्रभावित करती है? – hultqvist