| name | android-slim-bindings |
| description | Create and update slim/native platform interop bindings for Android in .NET MAUI and .NET for Android projects. Guides through creating Java/Kotlin wrappers, configuring Gradle projects, resolving Maven dependencies, generating C# bindings, and integrating native Android libraries using the Native Library Interop (NLI) approach. Use when asked about Android bindings, AAR/JAR integration, Kotlin interop, Maven dependencies, or bridging native Android SDKs to .NET. |
When to use this skill
Activate this skill when the user asks:
- How do I create Android bindings for a native library?
- How do I wrap an Android SDK for use in .NET MAUI?
- How do I create slim bindings for Android?
- How do I use Native Library Interop for Android?
- How do I bind a Kotlin library to .NET?
- How do I bind a Java library to .NET?
- How do I integrate an AAR or JAR into .NET MAUI?
- How do I create a Java/Kotlin wrapper for a native Android library?
- How do I update Android bindings when the native SDK changes?
- How do I fix Android binding build errors?
- How do I expose native Android APIs to C#?
- How do I resolve Maven dependencies for Android bindings?
- How do I handle AndroidX dependencies in bindings?
- How do I fix "Java dependency is not satisfied" errors?
- How do I use AndroidMavenLibrary in my binding project?
Overview
This skill guides the creation of Native Library Interop (Slim Bindings) for Android. This modern approach creates a thin native Java/Kotlin wrapper exposing only the APIs you need from a native Android library, making bindings easier to create and maintain.
When to Use Slim Bindings vs Traditional Bindings
| Scenario | Recommended Approach |
|---|
| Need only a subset of library functionality | Slim Bindings |
| Easier maintenance when SDK updates | Slim Bindings |
| Prefer working in Java/Kotlin for wrapper | Slim Bindings |
| Better isolation from breaking changes | Slim Bindings |
| Complex libraries with many dependencies | Slim Bindings |
| Need entire library API surface | Traditional Bindings |
| Creating bindings for third-party developers | Traditional Bindings |
| Already maintaining traditional bindings | Traditional Bindings |
Inputs
| Parameter | Required | Example | Notes |
|---|
| libraryName | yes | FirebaseMessaging, OkHttp | Name of the native Android library to bind |
| bindingProjectName | yes | MyBinding.Android | Name for the C# binding project |
| dependencySource | no | maven, aar, jar | How the native library is distributed |
| targetFrameworks | no | net9.0-android | Target frameworks (default: latest .NET Android) |
| exposedApis | no | List of specific APIs | Which native APIs to expose (helps scope the wrapper) |
| mavenCoordinates | no | com.example:library:1.0.0 | Maven coordinates if library is from Maven repository |
Project Structure
MyBinding/
android/
native/ # Android Studio/Gradle project
app/
src/main/
java/com/example/mybinding/
DotnetMyBinding.java # Java wrapper implementation
kotlin/com/example/mybinding/
DotnetMyBinding.kt # Or Kotlin wrapper
build.gradle.kts
settings.gradle.kts
build.gradle.kts
MyBinding.Android.Binding/
MyBinding.Android.Binding.csproj
Transforms/
Metadata.xml
sample/
MauiSample/ # Sample MAUI app
MauiSample.csproj
MainPage.xaml.cs
README.md
Step-by-step Process
For detailed code examples and full implementation walkthroughs, see references/android-slim-bindings-implementation.md.
Step 1: Analyze Dependencies First
Before creating any bindings, analyze the complete dependency tree of your target library. This is the most critical step and where most binding projects fail.
Prerequisites: JDK 17+, Android SDK with ANDROID_HOME set, .NET SDK 9+. You don't need Gradle installed globally; the Gradle Wrapper downloads the correct version automatically.
Step 2: Create the Android Library Project
Choose one of these approaches:
- Option A: Android Studio (recommended for GUI-based projects: create a "No Activity" project, then add an Android Library module)
- Option B:
gradle init with Wrapper (recommended for CLI-based projects: scaffold with Gradle using the Wrapper, then convert to an Android library)
- Option C: CommunityToolkit NativeLibraryInterop template (clone and use the CommunityToolkit NativeLibraryInterop template as your starting point)
- Option D: Manual creation with Gradle Wrapper (create the project structure manually using the Gradle Wrapper)
After project creation, configure settings.gradle.kts, root build.gradle.kts, and app/build.gradle.kts with your library dependency.
Step 3: Analyze the Full Dependency Tree
./gradlew app:dependencies --configuration releaseRuntimeClasspath
resolution strategy.
Understanding the output: -> = version conflict resolution, (*) = deduplication, (c) = constraint.
Step 4: Create the Wrapper Class
Create a Java or Kotlin wrapper in app/src/main/java/ (or kotlin/) that exposes only the APIs you need. Key guidelines:
- Use simple, marshallable types (String, boolean, int, byte[], Context, View)
- Use callback interfaces for async operations (not Kotlin coroutines or lambdas)
- Prefix class names with
Dotnet for clarity
- Add
@JvmStatic on all Kotlin methods for static access from C#
- Use
object in Kotlin for singleton pattern
Step 5: Build the AAR
./gradlew :app:assembleRelease
Step 6: Create the C# Binding Project
dotnet new androidbinding -n MyBinding.Android.Binding
Key .csproj elements:
< reference the built AARAndroidLibrary>
< NuGet packages for transitive dependenciesPackageReference>
<AndroidMavenLibrary Bind=" Maven deps without NuGet equivalentfalse">
< compile-time only dependenciesAndroidIgnoredJavaDependency>
Configure Transforms/Metadata.xml for namespace renaming and parameter names.
Step 7: Resolve Dependencies
Build and resolve XA4241/XA4242 errors using this decision tree:
For each unsatisfied dependency:
Is there a XA4242 suggestion?
Install the suggested NuGet package
Is the dependency needed from C#?
Find/create a binding NuGet or create your own binding
Use AndroidMavenLibrary with Bind="false"
Is it a compile-time only dependency (annotations, processors)?
Use AndroidIgnoredJavaDependency
Create a separate binding project or include AAR/JAR directly
Common Maven-to-NuGet Mappings
| Maven Artifact | NuGet Package |
|---|
androidx.annotation:annotation | Xamarin.AndroidX.Annotation |
androidx.core:core | Xamarin.AndroidX.Core |
androidx.core:core-ktx | Xamarin.AndroidX.Core.Core.Ktx |
androidx.appcompat:appcompat | Xamarin.AndroidX.AppCompat |
androidx.fragment:fragment | Xamarin.AndroidX.Fragment |
androidx.activity:activity | Xamarin.AndroidX.Activity |
androidx.recyclerview:recyclerview | Xamarin.AndroidX.RecyclerView |
androidx.lifecycle:lifecycle-common | Xamarin.AndroidX.Lifecycle.Common |
org.jetbrains.kotlin:kotlin-stdlib | Xamarin.Kotlin.StdLib |
org.jetbrains.kotlinx:kotlinx-coroutines-core | Xamarin.KotlinX.Coroutines.Core |
com.google.android.material:material | Xamarin.Google.Android.Material |
com.squareup.okhttp3:okhttp | Square.OkHttp3 |
com.google.code.gson:gson | GoogleGson |
Finding NuGet Packages
dotnet package search "artifact=androidx.core:core" --source https://api.nuget.org/v3/index.json
Step 8: Customize Bindings with Metadata
Edit Transforms/Metadata.xml to rename packages, classes, parameters, and remove internal types. Examine obj/Debug/net9.0-android/api.xml after building to construct correct XPath expressions.
Step 9: Build and Verify
dotnet build -c Release
Step 10: Use in Your MAUI App
Add a conditional <ProjectReference>, initialize in MauiProgram.cs using ConfigureLifecycleEvents, and implement callback interfaces by extending Java.Lang.Object.
Updating Bindings When Native SDK Changes
- Update native dependency version in
app/build.gradle.kts
- Re-analyze dependencies with
./gradlew app:dependencies
- Update the Java/Kotlin wrapper if APIs changed
- Rebuild the AAR with
./gradlew :app:assembleRelease
- Update NuGet packages and Maven dependencies in binding
.csproj
- Rebuild C# binding and fix any new XA4241/XA4242 errors
- Update
Metadata.xml for new classes/methods
- Test with sample app
For detailed update instructions, see references/android-slim-bindings-implementation.md.
Troubleshooting
| Error | Cause | Solution |
|---|
| XA4241 / XA4242 | Missing transitive dependency | Use NuGet, AndroidMavenLibrary Bind="false", or AndroidIgnoredJavaDependency |
| "Type is defined multiple times" | Duplicate dependency | Check NuGet/AAR overlap, use Bind="false" |
| "Class does not implement interface member" | Covariant return types | Add custom implementation in Additions/ folder |
| "Cannot find symbol" | Missing Gradle dependency | Verify build.gradle.kts dependencies, rebuild AAR |
NoClassDefFoundError (runtime) | Dependency ignored incorrectly | Remove from AndroidIgnoredJavaDependency, satisfy properly |
UnsatisfiedLinkError (runtime) | Missing .so native library | Include via <AndroidNativeLibrary>, check ABI compatibility |
| Callback not invoked | Wrong thread / GC'd reference | Use MainThread.BeginInvokeOnMainThread(), hold strong reference |
For detailed troubleshooting with code examples, see references/android-slim-bindings-implementation.md.
Quick Reference
Type Mapping
| Java/Kotlin Type | C# Type | Notes |
|---|
String | string | Direct mapping |
boolean / Boolean | bool | Direct mapping |
int / Integer | int | Direct mapping |
long / Long | long | Direct mapping |
double / Double | double | Direct mapping |
float / Float | float | Direct mapping |
byte[] | byte[] | Direct mapping |
Context | Android.Content.Context | Pass from platform |
View | Android.Views.View | For view creation |
JSONObject | Org.Json.JSONObject | For complex data |
| Callback interface | IJavaObject implementation | See callback pattern |
Things to Avoid in Wrapper API
| Avoid | Use Instead |
|---|
| Kotlin coroutines | Callback interfaces |
| Kotlin lambdas | Java-style interfaces |
| Kotlin data classes | Simple classes with getters |
| Kotlin sealed classes | Enums or class hierarchy |
| Generics (complex) | Specific types or Object |
| Rx/Flow observables | Callback interfaces |
MSBuild Items Reference
| Item | Purpose |
|---|
<AndroidLibrary> | Include AAR/JAR in binding |
<AndroidMavenLibrary> | Download and include from Maven |
<AndroidIgnoredJavaDependency> | Ignore a dependency (compile-time only) |
<AndroidNativeLibrary> | Include .so files |
<TransformFile> | Metadata transform files |
<PackageReference> | NuGet package reference |
Common Attributes
| Attribute | Values | Purpose |
|---|
Bind | true/false | Whether to generate C# bindings |
Pack | true/false | Whether to include in NuGet package |
JavaArtifact | groupId:artifactId | Declare what Maven artifact this satisfies |
JavaVersion | version | Version of the Maven artifact |
Repository | Central/Google/URL | Maven repository to download from |
Resources
Official Documentation
Version Discovery
Templates and Examples
Reference Files
Output Format
When assisting with Android slim bindings, provide:
- Dependency analysis - Full dependency tree and NuGet mapping strategy
- Project structure - File/folder layout for the binding
- Wrapper code - Complete Java or Kotlin implementation
- Gradle configuration - build.gradle.kts with dependencies
- C# binding project -
.csproj with proper dependency references
- Metadata transforms - Metadata.xml for namespace and parameter renaming
- Usage examples - How to call the binding from MAUI/C#
- Troubleshooting guidance - Common issues and solutions for the specific library
Always verify:
- All transitive dependencies are accounted for
- NuGet packages match required Maven versions
- Wrapper methods use simple, marshallable types
- Callback interfaces are properly designed
- Metadata.xml renames parameters to meaningful names