# Android Slim Bindings

> 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 i…

- **Type:** Skill
- **Install:** `agentstack add skill-redth-maui-skillz-android-slim-bindings`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Redth](https://agentstack.voostack.com/s/redth)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Redth](https://github.com/Redth)
- **Source:** https://github.com/Redth/maui-skillz/tree/main/.agents/skills/android-slim-bindings

## Install

```sh
agentstack add skill-redth-maui-skillz-android-slim-bindings
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 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

The recommended project structure for Native Library Interop:

```
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

## 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

Ensure you have:
- JDK 17+
- Android SDK with `ANDROID_HOME` environment variable set
- .NET SDK 9+ (recommended for Java Dependency Verification)

> **Note:** You don't need Gradle installed globally—we'll use the Gradle Wrapper which downloads the correct version automatically.

## Step 2: Create the Android Library Project

There are multiple approaches to create the native Android wrapper project. Choose the one that best fits your workflow.

### Option A: Use Android Studio (Recommended for GUI)

The most reliable way to create a properly configured Android library:

1. **Open Android Studio**
2. **File → New → New Project**
3. Select **"No Activity"** template
4. Configure:
   - Name: `MyBindingNative`
   - Package name: `com.example.mybinding`
   - Language: Java or Kotlin
   - Minimum SDK: API 21
5. **File → New → New Module**
6. Select **"Android Library"**
7. Name it `app` (or your preferred module name)

This creates a properly structured project with the latest Gradle plugin versions.

### Option B: Use `gradle init` with Wrapper (CLI)

Use Gradle's built-in initialization to scaffold a project, then convert it to Android:

```bash
# Set your binding name
BINDING_NAME="MyBinding"
PACKAGE_NAME="com.example.mybinding"

# Create directory structure
mkdir -p ${BINDING_NAME}/android/native
mkdir -p ${BINDING_NAME}/android/${BINDING_NAME}.Android.Binding/Transforms
mkdir -p ${BINDING_NAME}/sample/MauiSample

cd ${BINDING_NAME}/android/native

# Download and use Gradle wrapper (no global Gradle install needed)
# This downloads gradle-wrapper.jar and creates gradlew scripts
curl -sL https://services.gradle.org/distributions/gradle-9.2.1-bin.zip -o gradle.zip
unzip -q gradle.zip
./gradle-9.2.1/bin/gradle wrapper --gradle-version 9.2.1
rm -rf gradle.zip gradle-9.2.1

# Initialize a basic Kotlin library project
./gradlew init --type kotlin-library --dsl kotlin --project-name ${BINDING_NAME}Native --package ${PACKAGE_NAME} --no-split-project --java-version 17

# The project needs to be converted to Android Library (see next section)
```

> **Note:** `gradle init` creates a standard JVM library, not an Android library. You'll need to modify the generated files to add Android support (see "Converting to Android Library" below).

### Option C: Clone from Template Repository

Use the Community Toolkit template as a starting point:

```bash
BINDING_NAME="MyBinding"

# Clone the template
git clone https://github.com/AdrianSimionescu/NativeLibraryInterop-Template.git ${BINDING_NAME}
cd ${BINDING_NAME}

# Or use the official CommunityToolkit repo structure
git clone --depth 1 https://github.com/AdrianSimionescu/NativeLibraryInterop-Template.git ${BINDING_NAME}

# Rename files and references
find . -type f -name "*.gradle*" -exec sed -i '' 's/TemplateBinding/'"${BINDING_NAME}"'/g' {} \;
```

### Option D: Manual Creation with Gradle Wrapper

For full control, create the project structure manually but use proper Gradle wrapper initialization:

```bash
BINDING_NAME="MyBinding"
PACKAGE_NAME="com.example.mybinding"
PACKAGE_PATH="${PACKAGE_NAME//./\/}"

# Create directory structure
mkdir -p ${BINDING_NAME}/android/native/app/src/main/java/${PACKAGE_PATH}
mkdir -p ${BINDING_NAME}/android/${BINDING_NAME}.Android.Binding/Transforms
mkdir -p ${BINDING_NAME}/sample/MauiSample

cd ${BINDING_NAME}/android/native

# Create Gradle wrapper (downloads correct Gradle version automatically)
# Using gradle wrapper from a temporary init
mkdir -p tmp && cd tmp
curl -sL https://services.gradle.org/distributions/gradle-9.2.1-bin.zip -o gradle.zip
unzip -q gradle.zip && ./gradle-9.2.1/bin/gradle wrapper --gradle-version 9.2.1
mv gradlew gradlew.bat gradle ../ && cd .. && rm -rf tmp

# Now create the project files (see below)
```

### Creating Gradle Build Files

After setting up the wrapper, create the build files. These files define the project structure and can be version-controlled:

**settings.gradle.kts:**

```kotlin
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        // Add custom repositories as needed
        // maven { url = uri("https://jitpack.io") }
    }
}

rootProject.name = "MyBindingNative"
include(":app")
```

**build.gradle.kts (root):**

```kotlin
plugins {
    // Use version catalog or explicit versions
    // Check latest versions at: https://developer.android.com/build/releases/gradle-plugin
    id("com.android.library") version "8.2.2" apply false
    id("org.jetbrains.kotlin.android") version "1.9.22" apply false
}
```

**app/build.gradle.kts:**

```kotlin
plugins {
    id("com.android.library")
    // Include kotlin plugin only if using Kotlin
    // id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.example.mybinding"
    
    // Check latest SDK versions: https://developer.android.com/about/versions
    compileSdk = 34

    defaultConfig {
        minSdk = 21
        consumerProguardFiles("consumer-rules.pro")
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
    
    // Only needed if using Kotlin
    // kotlinOptions {
    //     jvmTarget = "17"
    // }
}

dependencies {
    // Add the native library you want to wrap
    // implementation("com.squareup.okhttp3:okhttp:4.12.0")
    
    // Common dependencies (only add what you need)
    // implementation("androidx.core:core-ktx:1.12.0")
}
```

### Checking for Latest Versions

Always use current versions for Gradle plugins and dependencies:

```bash
# Check latest Android Gradle Plugin version
curl -s "https://maven.google.com/web/index.html" | grep -o 'com.android.tools.build:gradle:[0-9.]*' | head -1

# Or check the release notes
open "https://developer.android.com/build/releases/gradle-plugin"

# Check latest Kotlin version
curl -s "https://api.github.com/repos/JetBrains/kotlin/releases/latest" | grep '"tag_name"' | cut -d'"' -f4
```

## Step 3: Analyze the Full Dependency Tree

Add your target library to the dependencies and run:

```bash
# Get full dependency tree
./gradlew app:dependencies --configuration releaseRuntimeClasspath

# Get flat list of all dependencies
./gradlew app:dependencies --configuration releaseRuntimeClasspath | grep -E "^[+\\\\]" | sed 's/.*--- //' | sort -u

# For insight into a specific dependency
./gradlew app:dependencyInsight --dependency kotlin-stdlib --configuration releaseRuntimeClasspath
```

**Understanding the output:**
- `->` indicates version conflict resolution (e.g., `1.9.10 -> 1.9.21`)
- `(*)` indicates the dependency was already shown elsewhere (deduplication)
- `(c)` indicates a constraint

### Document Your Dependencies

Create a dependency mapping document:

| Maven Artifact | Version | NuGet Package | Strategy |
|----------------|---------|---------------|----------|
| `androidx.core:core` | 1.12.0 | `Xamarin.AndroidX.Core` | NuGet |
| `org.jetbrains.kotlin:kotlin-stdlib` | 1.9.22 | `Xamarin.Kotlin.StdLib` | NuGet |
| `com.example:internal-lib` | 1.0.0 | N/A | `Bind="false"` |
| `org.jetbrains:annotations` | 23.0.0 | N/A | Ignore |

## Step 4: Create the Wrapper Class

Choose Java or Kotlin based on your preference and the native library's language.

### Java Wrapper

Create `app/src/main/java/com/example/mybinding/DotnetMyBinding.java`:

```bash
mkdir -p app/src/main/java/com/example/mybinding

cat > app/src/main/java/com/example/mybinding/DotnetMyBinding.java  {
            try {
                Thread.sleep(100); // Simulate network delay
                String result = "Result for: " + query;
                callback.onSuccess(result);
            } catch (Exception e) {
                callback.onError(e.getMessage());
            }
        }).start();
    }

    /**
     * Callback with multiple result types
     */
    public interface ComplexCallback {
        void onSuccess(String data, int count, boolean hasMore);
        void onError(int errorCode, String errorMessage);
    }

    /**
     * Complex async operation with multiple callback parameters
     */
    public static void performComplexOperation(
            String input, 
            int options, 
            final ComplexCallback callback) {
        
        // Perform operation...
        callback.onSuccess("data", 42, true);
    }

    // MARK: - View Creation

    /**
     * Create a native view to embed in .NET MAUI
     * @param context Android context
     * @return The native view
     */
    public static View createView(Context context) {
        // Create and return your native view
        // return new TheNativeLibrary.CustomView(context);
        
        View view = new View(context);
        view.setBackgroundColor(0xFF0066CC);
        return view;
    }

    // MARK: - Event Handling

    /**
     * Event listener interface
     */
    public interface EventListener {
        void onEvent(String eventType, String eventData);
    }

    private static EventListener eventListener;

    /**
     * Register an event listener
     */
    public static void setEventListener(EventListener listener) {
        eventListener = listener;
        
        // Wire up to native library's events
        // TheNativeLibrary.setEventHandler(event -> {
        //     if (eventListener != null) {
        //         eventListener.onEvent(event.type, event.data);
        //     }
        // });
    }

    /**
     * Remove the event listener
     */
    public static void removeEventListener() {
        eventListener = null;
    }

    // MARK: - Configuration

    /**
     * Set configuration options
     * Use simple types that marshal easily
     */
    public static void configure(
            String apiKey,
            String apiSecret,
            int timeout,
            boolean enableLogging) {
        
        // Apply configuration to native library
        Log.d(TAG, "Configured with apiKey: " + apiKey);
    }
}
EOF
```

### Kotlin Wrapper (Alternative)

Create `app/src/main/kotlin/com/example/mybinding/DotnetMyBinding.kt`:

```bash
mkdir -p app/src/main/kotlin/com/example/mybinding

cat > app/src/main/kotlin/com/example/mybinding/DotnetMyBinding.kt 
  
    net9.0-android
    enable
    true
    21
  

  
  
    
  

  
  
    
    
    
    
    
  

  
  
    
    
  

  
  
    
    
  

```

### Update Metadata.xml

Edit the generated `Transforms/Metadata.xml` to customize the bindings:

```xml

  
  MyBinding
  
  
  
  
  
  context
  debug
        
  input
        
  query
  callback

```

## Step 7: Resolve Dependencies

This is the critical step. When you build, .NET 9+ will report dependency errors:

```bash
cd android/${BINDING_NAME}.Android.Binding
dotnet build
```

### Understanding Dependency Errors

| Error | Meaning | Solution |
|-------|---------|----------|
| **XA4241** | No known NuGet package exists | Use `AndroidMavenLibrary` with `Bind="false"` or `AndroidIgnoredJavaDependency` |
| **XA4242** | Microsoft maintains a NuGet package | Install the suggested NuGet package |

### Dependency Resolution Decision Tree

```
For each unsatisfied dependency:
│
├─ Is there a XA4242 suggestion?
│   └─ YES → Install the suggested NuGet package
│
├─ Is the dependency needed from C#?
│   ├─ YES → Find/create a binding NuGet or create your own binding
│   └─ NO → Use AndroidMavenLibrary with Bind="false"
│
├─ Is it a compile-time only dependency (annotations, processors)?
│   └─ YES → Use AndroidIgnoredJavaDependency
│
└─ Otherwise → Create a separate binding project or include AAR/JAR directly
```

### Finding NuGet Packages for Maven Dependencies

Microsoft-maintained packages include artifact tags. Search by tag:

```bash
# Search NuGet for a specific Maven artifact
dotnet package search "artifact=androidx.core:core" --source https://api.nuget.org/v3/index.json

# Or use curl
curl -s "https://azuresearch-usnc.nuget.org/query?q=tags:artifact=androidx.core:core&take=10" | jq '.data[] | {id: .id, version: .version}'
```

### Common Maven-to-NuGet Mapp

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Redth](https://github.com/Redth)
- **Source:** [Redth/maui-skillz](https://github.com/Redth/maui-skillz)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-redth-maui-skillz-android-slim-bindings
- Seller: https://agentstack.voostack.com/s/redth
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
