id | title | brief | article | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
9E6D1A1B-1FFF-4718-9580-820EEB2F9D2D |
Call C# from JavaScript |
This recipe illustrates how to call C# class methods from JavaScript. |
|
A screenshot of the demo app created by this recipe is shown below:
Create a C# class that contains methods to be called from JavaScript.
If you are targeting Android API level 17 or later, this
JavaScript-to-C# interface class must annotate each JavaScript-callable
method with [JavascriptInterface]
and [Export]
as shown in the
following example. If you are targeting Android API Level 16 or
earlier, this interface class must implement Java.Lang.IRunnable
as
explained in Android API Level 16 and Earlier (later in this
recipe):
- Create a C# class that is derived from
Java.Lang.Object
. In the following example, we name our classMyJSInterface
and implement a method to display a toast when it is called from JavaScript:
class MyJSInterface : Java.Lang.Object
{
Context context;
public MyJSInterface (Context context)
{
this.context = context;
}
public void ShowToast ()
{
Toast.MakeText(context, "Hello from C#", ToastLength.Short).Show();
}
}
- Annotate each method that is to be exposed to JavaScript with
[Export]
and[JavascriptInterface]
(see IJavascriptInterface for more information about theJavascriptInterface
annotation). In the following example, theShowToast
method is annotated so that it can be called from JavaScript. Note that you must include theJava.Interop
andAndroid.Webkit
using statements as shown in this example:
using Java.Interop;
using Android.Webkit;
...
[Export]
[JavascriptInterface]
public void ShowToast ()
{
Toast.MakeText(context, "Hello from C#", ToastLength.Short).Show();
}
-
Add a project reference to Mono.Android.Export (so you can use the
[Export]
annotation):-
In Visual Studio, right-click References in the Solution Explorer and select Add Reference.... In Visual Studio for Mac, right-click References in the Solution Pad and select Edit References....
-
In the search field, enter
Mono.Android.Export
. When you have located it, enable the check mark next to it and click OK.
-
Next, invoke the ShowToast
method from a JavaScript onClick
event in an HTML document. Before we can do this, we must add our
interface class to the WebView
that displays this HTML content.
-
In the Activity
OnCreate
method, create aWebView
instance and add it as the content view. Add theMyJSInterface
class to thisWebView
instance as follows:-
Set the
WebView
'sJavaScriptEnabled
flag totrue
. -
Use AddJavascriptInterface to add an instance of
MyJSInterface
to theWebView
as its JavaScript interface. -
Load the HTML content into the
WebView
.
The following
OnCreate
example accomplishes these steps, passing in a simple HTML document to theWebView
. Note that the call toAddJavaScriptInterface
associates the JavaScript name "CSharp" with an instance of theMyJSInterface
class (here it is called "CSharp", but you can use any name you like): -
using Android.Webkit;
...
const string html = @"
<html>
<body>
<p>Demo calling C# from JavaScript</p>
</body>
</html>";
...
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
WebView webView = new WebView(this);
SetContentView(webView);
webView.Settings.JavaScriptEnabled = true;
webView.AddJavascriptInterface(new MyJSInterface(this), "CSharp");
webView.LoadData(html, "text/html", null);
}
- Call the C#
ShowToast
method from the HTML document. Add a button to the HTML document that invokes the JavaScript fragmentCsharp.ShowToast()
as shown in this example:
const string html = @"
<html>
<body>
<p>Demo calling C# from JavaScript</p>
<button type=""button"" onClick=""CSharp.ShowToast()"">Call C#</button>
</body>
</html>";
- Build and run the app. The
WebView
presents the HTML document with the "Call C#" button (see the screenshot above on the left). When you press this button, theShowToast
method is invoked, displaying the "Hello from C#" toast as seen in the screenshot above on the right.
In versions of Android at API Level 16 or earlier, your
JavaScript-to-C# interface class must implement Java.Lang.IRunnable
as shown in the following example.
- Create a C# class that is derived from
Java.Lang.Object
andJava.Lang.IRunnable
; this class implements aRun
method that can be called from JavaScript. In the following example, we name our classMyJSInterface
:
class MyJSInterface : Java.Lang.Object, Java.Lang.IRunnable
{
Context context;
public MyJSInterface (Context context)
{
this.context = context;
}
public void Run ()
{
Toast.MakeText(context, "Hello from C#", ToastLength.Short).Show();
}
}
- As explained earlier, add code to the
OnCreate
method to create aWebView
instance, adding theMyJSInterface
JavaScript interface class to this instance. However, to invoke our C# method from JavaScript, we must call therun
method as shown in this example:
const string html = @"
<html>
<body>
<p>Demo calling C# from JavaScript</p>
<button type=""button"" onClick=""CSharp.run()"">Call C#</button>
</body>
</html>";
Xamarin.Android creates an Android Callable Wrapper (ACW) for the
MyJSInterface
class because it derives from Java.Lang.Object
.
Calling AddJavascriptInterface
connects the MyJSInterface
JavaScript variable with the ACW. In this last example, the ACW has the
name run
(lowercase 'r') for its java.lang.Runnable
implementation.
This is why the JavaScript code calls run()
. In turn, the ACW is
bound to the C# class with the Run
method (uppercase 'R').
Jon Pryor's StackOverflow post provides more detailed information about how Xamarin.Android (referred to as Mono for Android in the post) uses Android Callable Wrappers to make "JavaScript-within-Android" functionality possible.