-
Notifications
You must be signed in to change notification settings - Fork 529
Blueprint
.NET SDK for Android née Xamarin.Android is a set of tooling to create Android apps in C#.
What are the various "pieces" of Xamarin.Android, and what are their relationships with each other?
TODO
The Xamarin.Android binding process, broadly speaking, involves three steps:
- Parse
.class
files -- present in.jar
and.aar
files -- into an XML description. Theclass-parse
utility is responsible for generating this XML description. - Consume the XML description, and generate a set of C# files which bind the types in (1).
The Xamarin.Android
generator
utility is responsible for this. - Compile the C# from (2) into the final assembly.
class-parse
and generator
are implicitly used as part of the Xamarin.Android @(EmbeddedJar)
and @(InputJar)
build action within Binding projects, and in .NET for Android via the @(AndroidLibrary)
build action, when %(AndroidLibrary.Bind)
=True.
See also:
- https://docs.microsoft.com/en-us/xamarin/android/platform/binding-java-library/
- https://docs.microsoft.com/en-us/xamarin/android/deploy-test/building-apps/build-items#androidlibrary
TODO: Determine of the App Startup AndroidX Library should change how we do things.
TODO: Find some sources to elaborate on the "pre-Xamarin startup" bits.
When the user taps on an App icon on an Android device, the Activity
associated with that App is looked up. If a process for that Activity
doesn't already exist, a process will be created (somewhere) in Zygote.java
, an Application
singleton instance is created based on the contents of //application/@android:name
attribute within AndroidManifest.xml
, and eventually all relevant <provider/>
s will be constructed.
This is where xamarin-android enters the picture: during the App Build Process, a <provider/>
is always added to AndroidManifest.xml
, one per detected process name:
<provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="1999999999" android:authorities="com.xamarin.android.helloworld.mono.MonoRuntimeProvider.__mono_init__" />
This XML fragment causes MonoRuntimeProvider
to be instantiated, and the Content Provider lifecycle to be started. We don't use <provider/>
to actually add a Content Provider; we use it because this was the earliest point we could find during Android process startup through which we could execute code.
When MonoRuntimeProvider.attachInfo()
is invoked by Android, xamarin-android has an opportunity to load Mono. This is done via MonoPackageManager.LoadApplication()
, which is the primary Java-side startup code path.
MonoPackageManager.LoadApplication()
loads various native libraries, including libmonodroid.so
. Once libmonodroid.so
has been loaded, mono.android.Runtime
methods can be invoked, in particular Runtime.initInternal()
. Through the glory of JNI native method resolution, Runtime.initInternal()
is resolved as the C symbol Java_mono_android_Runtime_initInternal()
.
Runtime.initInternal()
is responsible for preparing the process for managed code execution:
- Initialize MonoVM
- Find assemblies included with the App
- etc., etc.
Once MonoVM has been initialized, Mono.Android.dll
is loaded, then JNIEnv.Initialize()
is invoked. This gives Mono.Android.dll
a chance to perform initialization.
Once Runtime.initInternal()
completes, MonoPackageManager.attachInfo()
returns, and normal Android app startup resumes.
Primary source code locations:
- https://github.com/xamarin/xamarin-android/blob/main/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java
- https://github.com/xamarin/xamarin-android/blob/main/src/java-runtime/java/mono/android/MonoPackageManager.java
- https://github.com/xamarin/xamarin-android/tree/main/src/monodroid/jni
- https://github.com/xamarin/xamarin-android/blob/main/src/monodroid/jni/monodroid-glue.cc
- https://github.com/xamarin/xamarin-android/blob/main/src/java-runtime/java/mono/android/Runtime.java
- https://github.com/xamarin/xamarin-android/blob/main/src/Mono.Android/Android.Runtime/JNIEnv.cs
The pieces which make of Xamarin.Android include:
"Glue" code for running apps on Android device, process startup, etc.
Primary source code locations are:
- https://github.com/xamarin/xamarin-android/tree/main/src/java-runtime
- https://github.com/xamarin/xamarin-android/tree/main/src/monodroid
- https://github.com/xamarin/xamarin-android/blob/main/src/Mono.Android/Android.Runtime/JNIEnv.cs
- https://github.com/xamarin/xamarin-android/blob/main/src/Mono.Android/Android.Runtime/AndroidRuntime.cs
class-parse
parses .class
and .jar
files, and produces an XML description of the Java APIs found.
Primary source code locations are:
- https://github.com/xamarin/java.interop/tree/main/src/Xamarin.Android.Tools.Bytecode
- https://github.com/xamarin/Java.Interop/tree/main/tools/class-parse
Create C# bindings from XML description.
Also can optionally attempt to import Javadoc documentation, as imported from java-source-utils
, and convert into C# XML Documentation Comments.
Primary source code locations are:
- https://github.com/xamarin/java.interop/tree/main/src/Java.Interop.Tools.Generator
- https://github.com/xamarin/java.interop/tree/main/src/Xamarin.SourceWriter
- https://github.com/xamarin/java.interop/tree/main/tools/generator
Quickly update existing app installs on an Android device, for quick dev inner loops. Part of Xamarin.Android.Build.Tasks
.
https://github.com/xamarin/monodroid#commercial-xamarinandroid-dependencies
Create Java “stub” code to permit Java-to-managed method invocations. Required for on-device app use. Part of Xamarin.Android.Build.Tasks.
Docs:
- https://docs.microsoft.com/en-us/xamarin/android/platform/java-integration/android-callable-wrappers
Primary source code locations are:
Java source code parser, using com.github.javaparser
.
Exists to improve Java Library bindings in Xamarin.Android/.NET for Android. Bindings in Xamarin.Android frequently hit two common pitfalls:
- Lack of parameter names.
- Lack of documentation.
Java method parameter names are useful in-and-of-themselves. However, parameter names are also used when turning *Listener
interfaces into events, wherein each method parameter becomes an *EventArgs
property. See also: Events and Listeners in API Design.
The problem with Java method parameter names is that by default, Java .class
files don't contain parameter names. Java .class
files can contain parameter names, but only if javac -parameters
was used to compile the Java source code, which frequently is not the case. If parameter names aren't present, then names such as p0
are used, which results in very ugly *EventArgs
types.
Additionally, Java libraries frequently provide documentation, in the form of Javadoc documentation within Java source code.
java-source-utils
parses Java source code, extracting parameter names and Javadoc documentation. The extracted information can then be used by the Xamarin.Android generator
utility to provide parameter name information. generator
can also attempt to convert the extracted Javadoc documentation into C# XML Documentation Comments.
See also:
- https://github.com/xamarin/java.interop/commit/69e1b80afd81ac502494e4bc2a2de75f5171c73f
- https://github.com/xamarin/java.interop/commit/7574f166008bb45c0df97315aae7907ac25f8602
java-source-utils
is used by Xamarin.Android, via the @(JavaSourceJar)
build item.
Primary source code locations are:
Core binding for the Android API.
Primary source code locations are:
- APK Tests on the Hyper V Emulator
- Design Time Build System
- Profile MSBuild Tasks
- Diagnose Fast Deployment Issues
- Preview layout XML files with Android Studio
- Documentation