This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Download Microsoft Edge
More info about Internet Explorer and Microsoft Edge
Android Callable Wrappers (ACWs) are required whenever the Android
runtime invokes managed code. These wrappers are required because there
is no way to register classes with ART (the Android runtime) at
runtime. (Specifically, the
JNI DefineClass() function
is not supported by the Android runtime.} Android Callable
Wrappers thus make up for the lack of runtime type registration
support.
Every time
Android code needs to execute a
virtual
or interface
method that is
overridden
or implemented in managed code,
Xamarin.Android must provide a Java proxy so that this method is
dispatched to the appropriate managed type. These Java proxy types are
Java code that has the "same" base class and Java interface list as
the managed type, implementing the same constructors and declaring any
overridden base class and interface methods.
Android callable wrappers are generated by the
monodroid.exe
program during the
build process
: they
are generated for all types that (directly or indirectly) inherit
Java.Lang.Object
.
Android Callable Wrapper Naming
Package names for Android Callable Wrappers are based on the MD5SUM of
the assembly-qualified name of the type being exported. This naming
technique makes it possible for the same fully-qualified type name to
be made available by different assemblies without introducing a
packaging error.
Because of this MD5SUM naming scheme, you cannot directly access your
types by name. For example, the following
adb
command will not work
because the type name
my.ActivityType
is not generated by default:
adb shell am start -n My.Package.Name/my.ActivityType
Also, you may see errors like the following if you attempt to reference
a type by name:
java.lang.ClassNotFoundException: Didn't find class "com.company.app.MainActivity"
on path: DexPathList[[zip file "/data/app/com.company.App-1.apk"] ...
If you do require access to types by name, you can declare a name for
that type in an attribute declaration. For example, here is code that
declares an activity with the fully-qualified name My.ActivityType
:
namespace My {
[Activity]
public partial class ActivityType : Activity {
/* ... */
The ActivityAttribute.Name
property can be set to explicitly declare
the name of this activity:
namespace My {
[Activity(Name="my.ActivityType")]
public partial class ActivityType : Activity {
/* ... */
After this property setting is added, my.ActivityType
can be accessed
by name from external code and from adb
scripts. The Name
attribute
can be set for many different types including Activity
,
Application
, Service
, BroadcastReceiver
, and ContentProvider
:
ActivityAttribute.Name
ApplicationAttribute.Name
ServiceAttribute.Name
BroadcastReceiverAttribute.Name
ContentProviderAttribute.Name
MD5SUM-based ACW naming was introduced in Xamarin.Android 5.0. For more
information about attribute naming, see
RegisterAttribute.
Implementing Interfaces
There are times when you may need to implement an Android interface, such as
Android.Content.IComponentCallbacks.
Since all Android classes and interface extend the
Android.Runtime.IJavaObject
interface, the question arises: how do we implement IJavaObject
?
The question was answered above: the reason all Android types need to
implement IJavaObject
is so that Xamarin.Android has an Android
callable wrapper to provide to Android, i.e. a Java proxy for the given
type. Since monodroid.exe only looks for Java.Lang.Object
subclasses, and Java.Lang.Object
implements IJavaObject
, the answer
is obvious: subclass Java.Lang.Object
:
class MyComponentCallbacks : Java.Lang.Object, Android.Content.IComponentCallbacks {
public void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
// implementation goes here...
public void OnLowMemory ()
// implementation goes here...
Implementation Details
The remainder of this page provides implementation details subject to
change without notice (and is presented here only because developers will
be curious about what's going on).
For example, given the following C# source:
using System;
using Android.App;
using Android.OS;
namespace Mono.Samples.HelloWorld
public class HelloAndroid : Activity
protected override void OnCreate (Bundle savedInstanceState)
base.OnCreate (savedInstanceState);
SetContentView (R.layout.main);
The mandroid.exe program will generate the following Android
Callable Wrapper:
package mono.samples.helloWorld;
public class HelloAndroid
extends android.app.Activity
static final String __md_methods;
static {
__md_methods = "n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n" + "";
mono.android.Runtime.register (
"Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null", HelloAndroid.class, __md_methods);
public HelloAndroid ()
super ();
if (getClass () == HelloAndroid.class)
mono.android.TypeManager.Activate (
"Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null", "", this, new java.lang.Object[] { });
@Override
public void onCreate (android.os.Bundle p0)
n_onCreate (p0);
private native void n_onCreate (android.os.Bundle p0);
Notice that the base class is preserved, and native
method
declarations are provided for each method that is overridden within
managed code.