android-signing-config

Configure Android release build signing with dual-source credentials (env vars + gradle.properties)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "android-signing-config" with this command: npx skills add hitoshura25/claude-devtools/hitoshura25-claude-devtools-android-signing-config

Android Signing Configuration

Configures release build signing with dual-source strategy: environment variables (CI/CD) and gradle.properties (local dev).

Prerequisites

  • Keystores exist in keystores/ directory (run android-keystore-generation first)
  • Android project with Gradle
  • Kotlin DSL (build.gradle.kts)

Inputs

InputRequiredDefaultDescription
project_pathYes.Android project root

Process

Step 1: Detect and Select Environment Variable Prefix

Purpose: Avoid variable name conflicts with other projects by using a project-specific prefix.

Step 1a: Auto-detect project name

# From settings.gradle.kts
PROJECT_NAME=$(grep "rootProject.name" settings.gradle.kts | sed 's/.*"\(.*\)".*/\1/' | tr '[:lower:]' '[:upper:]' | tr '-' '_')
echo "Detected project: $PROJECT_NAME"

Step 1b: Ask user for prefix preference

"Choose environment variable prefix for signing configuration:

  1. ${PROJECT_NAME} (detected from project) - e.g., ${PROJECT_NAME}_SIGNING_KEY_STORE_PATH
  2. APP (generic) - e.g., APP_SIGNING_KEY_STORE_PATH
  3. Custom - Enter your own prefix

Select option (1/2/3):"

Step 1c: Store selected prefix

# Based on user selection:
# Option 1: PREFIX="$PROJECT_NAME"
# Option 2: PREFIX="APP"
# Option 3: PREFIX="{user_custom_prefix}"

echo "Using prefix: $PREFIX"
echo "Example variable: ${PREFIX}_SIGNING_KEY_STORE_PATH"

GitHub Secrets to create later:

  • ${PREFIX}_SIGNING_KEY_STORE_BASE64
  • ${PREFIX}_SIGNING_KEY_ALIAS
  • ${PREFIX}_SIGNING_STORE_PASSWORD
  • ${PREFIX}_SIGNING_KEY_PASSWORD

Step 2: Add Signing Configuration to build.gradle.kts

Update app/build.gradle.kts to add signing configuration:

android {
    namespace = "com.example.app" // Keep existing
    compileSdk = 34 // Keep existing

    defaultConfig {
        // Keep existing config
    }

    // ADD THIS SECTION
    signingConfigs {
        create("release") {
            // Use the prefix selected in Step 1 (replace {PREFIX} with actual prefix)
            val prefix = "{PREFIX}"  // e.g., "APP" or project-specific prefix

            // Priority: environment variables (CI/CD) > gradle.properties (local dev)
            val keystorePath = System.getenv("${prefix}_SIGNING_KEY_STORE_PATH")
                ?: project.findProperty("${prefix}_SIGNING_KEY_STORE_PATH")?.toString()
            val storePass = System.getenv("${prefix}_SIGNING_STORE_PASSWORD")
                ?: project.findProperty("${prefix}_SIGNING_STORE_PASSWORD")?.toString()
            val alias = System.getenv("${prefix}_SIGNING_KEY_ALIAS")
                ?: project.findProperty("${prefix}_SIGNING_KEY_ALIAS")?.toString()
            val keyPass = System.getenv("${prefix}_SIGNING_KEY_PASSWORD")
                ?: project.findProperty("${prefix}_SIGNING_KEY_PASSWORD")?.toString()

            if (keystorePath != null && storePass != null && alias != null && keyPass != null) {
                storeFile = file(keystorePath)
                storePassword = storePass
                keyAlias = alias
                // For PKCS12 keystores, storePassword and keyPassword must be identical
                keyPassword = keyPass
            }
        }
    }

    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
            // ProGuard config set by android-proguard-setup skill
        }
    }

    // Validate signing config only when building release variants
    tasks.matching {
        it.name.matches(Regex(".*[aA]ssemble.*Release.*|.*[bB]undle.*Release.*"))
    }.configureEach {
        doFirst {
            val releaseConfig = android.signingConfigs.getByName("release")
            if (releaseConfig.storeFile == null) {
                throw GradleException(
                    """
                    Release signing not configured!

                    For CI/CD: Set environment variables (using prefix: $prefix):
                      - ${prefix}_SIGNING_KEY_STORE_PATH
                      - ${prefix}_SIGNING_STORE_PASSWORD
                      - ${prefix}_SIGNING_KEY_ALIAS
                      - ${prefix}_SIGNING_KEY_PASSWORD

                    For local development: Add to ~/.gradle/gradle.properties:
                      ${prefix}_SIGNING_KEY_STORE_PATH=/path/to/local-dev-release.jks
                      ${prefix}_SIGNING_STORE_PASSWORD=your-password
                      ${prefix}_SIGNING_KEY_ALIAS=local-dev
                      ${prefix}_SIGNING_KEY_PASSWORD=your-password
                    """.trimIndent()
                )
            }
        }
    }
}

Detection logic:

  • Check if signingConfigs already exists - update if present
  • Check if release buildType already has signingConfig - preserve other settings
  • Don't modify ProGuard settings (handled by separate skill)

Step 2: Update .gitignore

Ensure sensitive files are gitignored:

# Add to .gitignore if not present
grep -q "gradle.properties" .gitignore 2>/dev/null || echo -e "\n# Gradle properties with secrets\ngradle.properties" >> .gitignore

Step 3: Configure Local Development

Ask user permission to update ~/.gradle/gradle.properties:

# Read credentials from KEYSTORE_INFO.txt
LOCAL_PASSWORD=$(grep "Local.*Store Password:" keystores/KEYSTORE_INFO.txt | cut -d: -f2 | xargs)
PROJECT_PATH=$(pwd)
PREFIX="{PREFIX}"  # Use the prefix selected in Step 1

# Add to ~/.gradle/gradle.properties (using selected prefix)
cat >> ~/.gradle/gradle.properties << EOF

# ${PROJECT_PATH} (using prefix: ${PREFIX})
${PREFIX}_SIGNING_KEY_STORE_PATH=${PROJECT_PATH}/keystores/local-dev-release.jks
${PREFIX}_SIGNING_KEY_ALIAS=local-dev
${PREFIX}_SIGNING_STORE_PASSWORD=${LOCAL_PASSWORD}
${PREFIX}_SIGNING_KEY_PASSWORD=${LOCAL_PASSWORD}
EOF

Important: Always ask permission before modifying user's global gradle.properties!

Verification

MANDATORY: Run this command to verify signing works:

# Build release APK
./gradlew assembleRelease

# Verify APK exists
ls -lh app/build/outputs/apk/release/app-release.apk

# Verify APK signature (supports APK Signature Scheme v2/v3)
$ANDROID_HOME/build-tools/34.0.0/apksigner verify --verbose app/build/outputs/apk/release/app-release.apk

# Or if apksigner is in PATH:
apksigner verify --verbose app/build/outputs/apk/release/app-release.apk

Expected output:

  • Release build succeeds
  • APK file exists
  • apksigner shows "Verifies" with v2/v3 scheme confirmation

Outputs

OutputLocationDescription
Signing configapp/build.gradle.ktsDual-source signing configuration
Local config~/.gradle/gradle.propertiesLocal dev credentials

Troubleshooting

"Signing config not found"

Cause: gradle.properties not configured correctly Fix: Verify ~/.gradle/gradle.properties has correct paths and passwords

"Cannot find keystore file"

Cause: Path in gradle.properties is incorrect Fix: Use absolute path: /full/path/to/keystores/local-dev-release.jks

"apksigner verification fails"

Cause: Wrong keystore or passwords Fix: Double-check credentials in KEYSTORE_INFO.txt

Completion Criteria

  • signingConfigs.release exists in app/build.gradle.kts
  • Release buildType uses signingConfig
  • ~/.gradle/gradle.properties configured (or env vars set for CI)
  • ./gradlew assembleRelease succeeds
  • apksigner verify confirms APK is signed (v2/v3 schemes)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

android-playstore-setup

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

android-playstore-scan

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

android-proguard-setup

No summary provided by upstream source.

Repository SourceNeeds Review