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

- Skill: `majiayu000/android` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/android`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/android/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/android

---


# 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...
```

| Workflow | Trigger | File |
|----------|---------|------|
| **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 Type | Java Type | Kotlin Type | Notes |
|---------|-----------|-------------|-------|
| `bool` | `boolean` | `Boolean` | |
| `int`, `int32` | `int` | `Int` | 32-bit |
| `int64` | `long` | `Long` | 64-bit |
| `float32` | `float` | `Float` | |
| `float64` | `double` | `Double` | |
| `string` | `String` | `String` | |
| `[]byte` | `byte[]` | `ByteArray` | |
| `error` | `Exception` | `Exception` | Becomes checked exception |
| `interface` | `interface` | `interface` | Must have exported methods |
| `struct` | `class` | `class` | Exported 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`)

```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`

```kotlin
plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
}
```

### App `build.gradle.kts`

```kotlin
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

```kotlin
// 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

```kotlin
// 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:
```bash
keytool -genkey -v \
  -keystore release.keystore \
  -alias myapp \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000
```

Configure in `app/build.gradle.kts`:
```kotlin
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)
  ```bash
  ./gradlew assembleRelease
  # Output: app/build/outputs/apk/release/app-release.apk
  ```

- **AAB**: Android App Bundle (Play Store)
  ```bash
  ./gradlew bundleRelease
  # Output: app/build/outputs/bundle/release/app-release.aab
  ```

## Common Commands

### Gradle

```bash
# 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)

```bash
# 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

```bash
# 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

```nix
{ 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

- [Android Developers](https://developer.android.com/)
- [Gomobile Documentation](https://pkg.go.dev/golang.org/x/mobile/cmd/gomobile)
- [Gradle Documentation](https://docs.gradle.org/)
- [Android Studio](https://developer.android.com/studio)

### Gomobile Resources

- [Gomobile Wiki](https://github.com/golang/go/wiki/Mobile)
- [Gomobile Examples](https://github.com/golang/mobile/tree/master/example)
- [Go on Android](https://godoc.org/golang.org/x/mobile/app)

### Tools

- [Android SDK Command-Line Tools](https://developer.android.com/studio/command-line)
- [ADB Documentation](https://developer.android.com/studio/command-line/adb)
- [Gradle Build Tool](https://gradle.org/)

### Best Practices

- [Android Best Practices](https://developer.android.com/topic/best-practices)
- [Kotlin Style Guide](https://developer.android.com/kotlin/style-guide)
- [Material Design](https://material.io/design)

## 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.

