Skip to content

feat(android): add SDK version validation and doctor command#15

Merged
abueide merged 1 commit intomainfrom
feat/android-sdk-version-validation
Apr 16, 2026
Merged

feat(android): add SDK version validation and doctor command#15
abueide merged 1 commit intomainfrom
feat/android-sdk-version-validation

Conversation

@abueide
Copy link
Copy Markdown
Contributor

@abueide abueide commented Apr 16, 2026

Summary

Adds automatic detection and helpful error messages when a project's build.gradle has hardcoded SDK versions that don't match the plugin-provided SDK versions.

Problem

When adopting the Android plugin, users commonly hit build failures like:

Failed to install the following SDK components:
  platforms;android-33 Android SDK Platform 33
The SDK directory is not writable (/nix/store/...)

This happens because:

  1. Their build.gradle has hardcoded compileSdkVersion = 33
  2. The plugin provides API 35 via the immutable Nix store
  3. Gradle tries to download API 33 but can't write to /nix/store

This is confusing and frustrating for new users.

Solution

1. Automatic Validation on Shell Init

When running devbox shell, the plugin now checks for SDK version mismatches and displays a clear warning:

⚠️  WARNING: SDK version mismatch detected

Your android/build.gradle has hardcoded compileSdkVersion=33
But this plugin provides Android API 35

This will cause build failures because Gradle will try to download API 33,
but only API 35 is available in the Nix store.

📋 To fix, update your android/build.gradle to read from environment variables:

    buildscript {
        ext {
            def compileSdkEnv = System.getenv("ANDROID_COMPILE_SDK") ?: System.getenv("ANDROID_MAX_API") ?: "35"
            def targetSdkEnv = System.getenv("ANDROID_TARGET_SDK") ?: System.getenv("ANDROID_MAX_API") ?: "35"
            buildToolsVersion = System.getenv("ANDROID_BUILD_TOOLS_VERSION") ?: "35.0.0"
            compileSdkVersion = compileSdkEnv.toInteger()
            targetSdkVersion = targetSdkEnv.toInteger()
        }
    }

Or, to use API 33, set it in your devbox.json:

    "env": {
        "ANDROID_MAX_API": "33"
    }

Then regenerate the device lock file: devbox run android.sh devices eval

2. Doctor Command

Added android.sh doctor command to diagnose environment and configuration issues:

$ devbox run android.sh doctor

🔍 Android Environment Check
==============================

✓ ANDROID_SDK_ROOT: /nix/store/.../androidsdk/libexec/android-sdk

Tools availability:
  ✓ adb: /nix/store/.../bin/adb
  ✓ emulator: /nix/store/.../bin/emulator
  ✓ sdkmanager: /nix/store/.../bin/sdkmanager
  ✓ avdmanager: /nix/store/.../bin/avdmanager

Plugin-provided SDK versions:
  ANDROID_COMPILE_SDK: 35
  ANDROID_TARGET_SDK: 35
  ANDROID_BUILD_TOOLS_VERSION: 35.0.0
  ANDROID_NDK_VERSION: 27.0.12077973

Project android/build.gradle detected:
  compileSdkVersion = 33
  targetSdkVersion = 33
  buildToolsVersion = "30.0.3"

⚠️  WARNING: SDK version mismatch detected
[... same helpful message as above ...]

3. Documentation

Added comprehensive documentation in README.md covering:

  • How to configure SDK versions (Option 1: use plugin defaults, Option 2: override)
  • Why mismatches happen
  • How to troubleshoot with the doctor command
  • Example build.gradle configuration

Design Principles

  1. Non-blocking: Validation warns but never blocks execution (follows plugin philosophy)
  2. Actionable: Error messages provide copy-paste solutions
  3. Smart detection: Only warns if versions don't match AND aren't reading from env vars
  4. Deterministic: Users can override versions in devbox.json and regenerate lock file

Testing

Tested with:

  • Project with hardcoded SDK versions → shows warning with fix instructions
  • Project already using env vars → no warning
  • Project with matching hardcoded versions → no warning
  • android.sh doctor command → displays full diagnostic info

Related

This was discovered while debugging analytics-react-native E2E test failures where the examples had hardcoded API 33 but the plugin provided API 35.

🤖 Generated with Claude Code

Add automatic detection and helpful error messages when project
build.gradle has hardcoded SDK versions that don't match the
plugin-provided SDK versions.

Features:
- Validate build.gradle on shell init (non-blocking warning)
- New `android.sh doctor` command to diagnose SDK mismatches
- Clear error messages with copy-paste fix instructions
- Documentation on configuring SDK versions

This improves DX when adopting the plugin by catching the common
issue where Gradle tries to download SDK versions that aren't
available in the immutable Nix store.

Example error message:
```
⚠️  WARNING: SDK version mismatch detected

Your android/build.gradle has hardcoded compileSdkVersion=33
But this plugin provides Android API 35

This will cause build failures because Gradle will try to download
API 33, but only API 35 is available in the Nix store.

📋 To fix, update your android/build.gradle to read from environment
variables:

    buildscript {
        ext {
            def compileSdkEnv = System.getenv("ANDROID_COMPILE_SDK") ?: "35"
            compileSdkVersion = compileSdkEnv.toInteger()
        }
    }
```

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@abueide abueide merged commit af43f62 into main Apr 16, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant