Android

Android app development with gomobile, Gradle, and modern tooling. USE WHEN building Android apps, working with gomobile bindings, managing Android SDK/NDK, running emulators, debugging with adb, or publishing to Play Store.

$ インストール

git clone https://github.com/vdemeester/home /tmp/home && cp -r /tmp/home/dots/.config/claude/skills/Android ~/.claude/skills/home

// tip: Run this command in your terminal to install the skill


name: Android description: Android app development with gomobile, Gradle, and modern tooling. USE WHEN building Android apps, working with gomobile bindings, managing Android SDK/NDK, running emulators, debugging with adb, or publishing to Play Store.

Android Development

Expert guidance on Android application development with first-class support for Go integration via gomobile, modern Gradle build system, SDK/NDK management, and deployment workflows.

Purpose

Guide Android development following official best practices, with specialized support for:

  • Gomobile integration: Building Go libraries (AAR) and apps for Android
  • Modern Gradle: Kotlin DSL, version catalogs, and build optimization
  • SDK management: Android SDK, NDK, and command-line tools
  • Development workflows: Build, debug, test, and deploy Android apps
  • Nix integration: Using Android tools in NixOS environments

Context Detection

This skill activates when:

  • Current directory contains build.gradle, build.gradle.kts, or AndroidManifest.xml
  • Git repository has Android project structure (app/, gradle/)
  • User mentions gomobile, Android SDK, adb, or Android development
  • Working with .aar, .apk, or .aab files
  • Commands like gradle, adb, gomobile, or sdkmanager are mentioned

Workflow Routing

When executing a workflow, output this notification directly:

Running the **WorkflowName** workflow from the **Android** skill...
WorkflowTriggerFile
GomobileBind"build go library for android", "create AAR", "gomobile bind"workflows/GomobileBind.md
GomobileApp"build android app with go", "gomobile build", "standalone go app"workflows/GomobileApp.md
Setup"setup android dev", "install android sdk", "android environment"workflows/Setup.md
Build"build apk", "build aab", "gradle build", "assemble"workflows/Build.md
Debug"debug android", "adb logcat", "android logs", "troubleshoot app"workflows/Debug.md
Emulator"android emulator", "avd", "virtual device", "start emulator"workflows/Emulator.md
Gradle"gradle dependencies", "build.gradle", "android dependencies"workflows/Gradle.md
Publish"publish to play store", "sign apk", "release build", "keystore"workflows/Publish.md
Test"android tests", "instrumentation", "ui tests", "espresso"workflows/Test.md
Nix"android on nix", "nixpkgs android", "android sdk nix"workflows/Nix.md

Core Principles

  1. Gomobile for Go integration: Use gomobile bind for libraries, gomobile build for standalone apps
  2. Modern Gradle: Prefer Kotlin DSL (.gradle.kts) over Groovy
  3. Version catalogs: Centralize dependency versions in libs.versions.toml
  4. Multi-architecture: Support arm64-v8a, armeabi-v7a, x86_64, x86
  5. Type safety: Handle Go ↔ Java/Kotlin type conversions carefully
  6. SDK tools: Use sdkmanager and avdmanager for command-line management
  7. Reproducible builds: Lock dependency versions and use consistent tooling

Android Project Structure

Standard Android Project

myapp/
├── app/
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/com/example/myapp/
│   │   │   │   └── MainActivity.kt
│   │   │   ├── res/
│   │   │   │   ├── layout/
│   │   │   │   ├── values/
│   │   │   │   └── drawable/
│   │   │   └── AndroidManifest.xml
│   │   ├── test/              # Unit tests
│   │   └── androidTest/       # Instrumentation tests
│   ├── build.gradle.kts
│   └── proguard-rules.pro
├── gradle/
│   └── libs.versions.toml     # Version catalog
├── build.gradle.kts           # Root build file
├── settings.gradle.kts        # Project settings
├── gradle.properties
└── local.properties           # SDK location (not in git)

Android Project with Gomobile

myapp/
├── app/
│   ├── libs/
│   │   └── mylib.aar          # Generated by gomobile bind
│   ├── src/main/
│   │   ├── java/
│   │   └── AndroidManifest.xml
│   └── build.gradle.kts
├── golib/                     # Go library source
│   ├── mylib.go
│   └── go.mod
├── build-aar.sh              # Script to build AAR with gomobile
└── gradle/

Gomobile Overview

What is Gomobile?

Gomobile enables Go code to run on Android (and iOS). Two main modes:

  1. gomobile bind: Create native library (AAR) from Go package

    • Go code becomes Android library
    • Called from Java/Kotlin
    • Best for integrating Go into existing Android apps
  2. gomobile build: Create standalone Android app

    • Entire app written in Go
    • Uses gomobile app package
    • Limited Android UI capabilities

Type Mapping (Go ↔ Java/Kotlin)

Go TypeJava TypeKotlin TypeNotes
boolbooleanBoolean
int, int32intInt32-bit
int64longLong64-bit
float32floatFloat
float64doubleDouble
stringStringString
[]bytebyte[]ByteArray
errorExceptionExceptionBecomes checked exception
interfaceinterfaceinterfaceMust have exported methods
structclassclassExported fields become getters/setters

Gomobile Limitations

What works:

  • Exported functions and methods
  • Basic types (int, string, float, bool)
  • Slices of basic types
  • Interfaces with exported methods
  • Structs with exported fields
  • Callbacks via interfaces

What doesn't work:

  • Generic types (Go 1.18+ generics)
  • Maps (use structs or custom types)
  • Channels (use callbacks instead)
  • Unexported types/functions
  • Complex nested types
  • Variadic functions

Android SDK Management

SDK Structure

$ANDROID_HOME/
├── build-tools/
│   └── 34.0.0/              # Build tools version
├── cmdline-tools/
│   └── latest/
│       └── bin/
│           ├── sdkmanager
│           └── avdmanager
├── emulator/                # Android Emulator
├── ndk/
│   └── 26.1.10909125/      # NDK version
├── platform-tools/          # adb, fastboot
└── platforms/
    └── android-34/          # API level 34

Essential Tools

  • sdkmanager: Install and update SDK packages
  • avdmanager: Create and manage Android Virtual Devices (AVDs)
  • adb: Android Debug Bridge (device communication)
  • emulator: Run Android Virtual Devices
  • gradle: Build system

Gradle Configuration

Version Catalog (gradle/libs.versions.toml)

[versions]
agp = "8.3.0"                    # Android Gradle Plugin
kotlin = "1.9.22"
compileSdk = "34"
minSdk = "24"
targetSdk = "34"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version = "1.12.0" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version = "1.6.1" }
material = { group = "com.google.android.material", name = "material", version = "1.11.0" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

Root build.gradle.kts

plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
}

App build.gradle.kts

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
}

android {
    namespace = "com.example.myapp"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.myapp"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = "17"
    }
}

dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.appcompat)
    implementation(libs.material)

    // Add gomobile AAR
    implementation(files("libs/mylib.aar"))
}

Testing

Test Types

  1. Local Unit Tests (src/test/)

    • Run on JVM
    • Fast, no Android device needed
    • Use JUnit, Mockito
  2. Instrumentation Tests (src/androidTest/)

    • Run on Android device/emulator
    • Test Android framework APIs
    • Use AndroidJUnit4, Espresso
  3. UI Tests

    • Test user interface
    • Use Espresso, UI Automator
    • Run on device/emulator

Example Unit Test

// src/test/java/com/example/myapp/CalculatorTest.kt
import org.junit.Test
import org.junit.Assert.*

class CalculatorTest {
    @Test
    fun addition_isCorrect() {
        val calculator = Calculator()
        assertEquals(4, calculator.add(2, 2))
    }
}

Example Instrumentation Test

// src/androidTest/java/com/example/myapp/MainActivityTest.kt
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.rules.ActivityScenarioRule
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MainActivityTest {
    @get:Rule
    val activityRule = ActivityScenarioRule(MainActivity::class.java)

    @Test
    fun testButtonClick() {
        // Test implementation
    }
}

Signing and Publishing

Debug Signing

Android Studio automatically creates debug keystore:

  • Location: ~/.android/debug.keystore
  • Password: android
  • Alias: androiddebugkey

Release Signing

Create release keystore:

keytool -genkey -v \
  -keystore release.keystore \
  -alias myapp \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000

Configure in app/build.gradle.kts:

android {
    signingConfigs {
        create("release") {
            storeFile = file("../release.keystore")
            storePassword = System.getenv("KEYSTORE_PASSWORD")
            keyAlias = "myapp"
            keyPassword = System.getenv("KEY_PASSWORD")
        }
    }

    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
        }
    }
}

Build Types

  • APK: Android Package (direct install)

    ./gradlew assembleRelease
    # Output: app/build/outputs/apk/release/app-release.apk
    
  • AAB: Android App Bundle (Play Store)

    ./gradlew bundleRelease
    # Output: app/build/outputs/bundle/release/app-release.aab
    

Common Commands

Gradle

# Build debug APK
./gradlew assembleDebug

# Build release AAB
./gradlew bundleRelease

# Install on connected device
./gradlew installDebug

# Clean build
./gradlew clean

# List tasks
./gradlew tasks

# Check dependencies
./gradlew dependencies

ADB (Android Debug Bridge)

# List devices
adb devices

# Install APK
adb install app-debug.apk

# Uninstall app
adb uninstall com.example.myapp

# View logs
adb logcat

# View logs for specific app
adb logcat | grep com.example.myapp

# Clear app data
adb shell pm clear com.example.myapp

# Take screenshot
adb shell screencap /sdcard/screen.png
adb pull /sdcard/screen.png

# Get device properties
adb shell getprop

# Start activity
adb shell am start -n com.example.myapp/.MainActivity

Gomobile

# Install gomobile
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init

# Build AAR for Android
gomobile bind -target=android -o mylib.aar ./golib

# Build AAR for specific architectures
gomobile bind -target=android/arm64,android/amd64 -o mylib.aar ./golib

# Build standalone Android app
gomobile build -target=android ./cmd/myapp

# Build with custom app ID
gomobile build -target=android -appid=com.example.myapp ./cmd/myapp

Nix Integration

This repository uses NixOS. Android SDK can be configured via:

Using nixpkgs Android SDK

{ pkgs, ... }:
{
  home.packages = with pkgs; [
    android-studio
    android-tools  # adb, fastboot
  ];

  # Or use androidenv for more control
  android-sdk = pkgs.androidenv.composeAndroidPackages {
    platformVersions = [ "34" ];
    buildToolsVersions = [ "34.0.0" ];
    includeNDK = true;
    ndkVersion = "26.1.10909125";
    includeEmulator = true;
  };
}

See workflows/Nix.md for detailed Nix integration.

Best Practices

General

  • Use Kotlin over Java for new code
  • Follow Material Design guidelines
  • Support multiple screen sizes and orientations
  • Handle configuration changes properly
  • Use Android Architecture Components (ViewModel, LiveData, Room)
  • Implement proper error handling
  • Add crash reporting (Firebase Crashlytics, Sentry)

Gomobile Specific

  • Keep Go API simple and flat
  • Avoid complex nested types
  • Use interfaces for callbacks
  • Document type conversions
  • Test Go code separately from Android integration
  • Consider performance implications of crossing Go/Java boundary
  • Use goroutines carefully (they don't map to Android threads)

Security

  • Never commit keystores to version control
  • Use environment variables for secrets
  • Enable ProGuard/R8 for release builds
  • Validate all user inputs
  • Use HTTPS for network communication
  • Store sensitive data in Android Keystore
  • Follow OWASP Mobile Security guidelines

Performance

  • Use build variants for different configurations
  • Enable code shrinking and obfuscation
  • Optimize images and resources
  • Use vector drawables when possible
  • Profile with Android Profiler
  • Monitor memory usage
  • Implement proper caching strategies

Resources

Official Documentation

Gomobile Resources

Tools

Best Practices

Examples

Example 1: Build Go library as Android AAR

User: "I have a Go package with networking code. How do I use it in my Android app?"
→ Invokes GomobileBind workflow
→ Checks gomobile installation
→ Generates AAR with `gomobile bind`
→ Shows how to add AAR to build.gradle.kts
→ Provides example of calling Go code from Kotlin

Example 2: Debug Android app crash

User: "My app crashes when I click the submit button. How do I debug this?"
→ Invokes Debug workflow
→ Shows how to use `adb logcat` to view crash logs
→ Helps filter logs for the specific app
→ Explains stack trace interpretation
→ Suggests debugging strategies (breakpoints, logging)

Example 3: Setup Android development on NixOS

User: "How do I set up Android development on my NixOS machine?"
→ Invokes Nix workflow
→ Shows nixpkgs Android SDK configuration
→ Explains how to compose Android packages with androidenv
→ Configures environment variables (ANDROID_HOME, PATH)
→ Verifies setup with adb and gradle commands

Philosophy: Android development should embrace modern tooling and practices. Gomobile provides a powerful bridge between Go's excellent concurrency and networking capabilities and Android's vast ecosystem. Use the right tool for each layer: Go for backend logic and performance-critical code, Kotlin for UI and Android framework integration.