AgentStack
SKILL verified MIT Self-run

Android Slim Bindings

skill-redth-maui-skillz-android-slim-bindings · by Redth

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…

No reviews yet
0 installs
8 views
0.0% view→install

Install

$ agentstack add skill-redth-maui-skillz-android-slim-bindings

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Android Slim Bindings? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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
  1. File → New → New Module
  2. Select "Android Library"
  3. 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:

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

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:

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:

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):

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:

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:

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

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

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:

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:


  
  MyBinding
  
  
  
  
  
  context
  debug
        
  input
        
  query
  callback

Step 7: Resolve Dependencies

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

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:

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

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

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.