# Android Fastlane Setup

> Setup Fastlane for Play Store deployment with supply and screengrab Use when this capability is needed.

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

---


# Android Fastlane Setup

Configures Fastlane with `supply` for Play Store deployment and `screengrab` for screenshot automation.

## Prerequisites

- Ruby 2.7+ installed
- Android project
- Play Store service account JSON

## Inputs

| Input | Required | Default | Description |
|-------|----------|---------|-------------|
| package_name | Yes | - | Android app package name (e.g., com.example.app) |
| service_account_path | Yes | - | Path to service account JSON file |

## Process

### Step 1: Check Ruby Installation

```bash
# Check Ruby version
ruby --version || echo "❌ Ruby not found. Please install Ruby 2.7+ first."

# Install Bundler if needed
gem install bundler --no-document
```

### Step 2: Create Gemfile

Create `./Gemfile`:

```ruby
source "https://rubygems.org"

gem "fastlane"
gem "screengrab"
```

### Step 3: Install Dependencies

```bash
bundle install
```

This will create `Gemfile.lock` and install all dependencies.

### Step 4: Create Fastlane Directory Structure

```bash
mkdir -p fastlane
mkdir -p fastlane/metadata/android/en-US/images/phoneScreenshots
mkdir -p fastlane/metadata/android/en-US/images/sevenInchScreenshots
mkdir -p fastlane/metadata/android/en-US/images/tenInchScreenshots
mkdir -p fastlane/metadata/android/en-US/changelogs
```

### Step 5: Create Appfile

Create `./fastlane/Appfile`:

```ruby
# Path to service account JSON for Play Store API
json_key_file(ENV['PLAY_STORE_SERVICE_ACCOUNT'] || "service-account.json")

# Your app's package name
package_name("{PACKAGE_NAME}")
```

**Important:** Replace `{PACKAGE_NAME}` with the actual package name.

### Step 6: Create Fastfile

Create `./fastlane/Fastfile` with comprehensive deployment lanes:

```ruby
default_platform(:android)

platform :android do
  # ============================================
  # Build Lanes
  # ============================================

  desc "Build debug APK and test APK for screenshots"
  lane :build_for_screenshots do
    gradle(task: "clean")
    gradle(task: "assembleDebug")
    gradle(task: "assembleAndroidTest")
  end

  desc "Build release bundle"
  lane :build_release do
    gradle(task: "clean")
    gradle(task: "bundleRelease")
  end

  # ============================================
  # Screenshot Lane
  # ============================================

  desc "Capture screenshots for Play Store"
  lane :screenshots do
    build_for_screenshots
    capture_android_screenshots
  end

  # ============================================
  # Deployment Lanes
  # ============================================

  desc "Deploy to internal testing track"
  lane :deploy_internal do
    build_release
    upload_to_play_store(
      track: "internal",
      release_status: "completed",
      aab: "app/build/outputs/bundle/release/app-release.aab"
    )
  end

  desc "Deploy to beta/closed testing track"
  lane :deploy_beta do |options|
    build_release

    # Support staged rollout
    rollout = options[:rollout] || 1.0

    upload_to_play_store(
      track: "beta",
      release_status: rollout < 1.0 ? "inProgress" : "completed",
      rollout: rollout < 1.0 ? rollout.to_s : nil,
      aab: "app/build/outputs/bundle/release/app-release.aab"
    )
  end

  desc "Deploy to production track"
  lane :deploy_production do |options|
    build_release

    # Default to 10% staged rollout for safety
    rollout = options[:rollout] || 0.1

    upload_to_play_store(
      track: "production",
      release_status: rollout < 1.0 ? "inProgress" : "completed",
      rollout: rollout < 1.0 ? rollout.to_s : nil,
      aab: "app/build/outputs/bundle/release/app-release.aab"
    )
  end

  desc "Increase production rollout percentage"
  lane :increase_rollout do |options|
    rollout = options[:rollout] || 0.5

    upload_to_play_store(
      track: "production",
      release_status: rollout < 1.0 ? "inProgress" : "completed",
      rollout: rollout < 1.0 ? rollout.to_s : nil,
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true
    )
  end

  desc "Halt production rollout"
  lane :halt_rollout do
    upload_to_play_store(
      track: "production",
      release_status: "halted",
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true
    )
  end

  # ============================================
  # Metadata Lanes
  # ============================================

  desc "Upload metadata only (no APK/AAB)"
  lane :upload_metadata do
    upload_to_play_store(
      skip_upload_aab: true,
      skip_upload_apk: true
    )
  end

  desc "Upload screenshots only"
  lane :upload_screenshots do
    upload_to_play_store(
      skip_upload_aab: true,
      skip_upload_apk: true,
      skip_upload_metadata: true
    )
  end

  # ============================================
  # Version Management
  # ============================================

  desc "Get current version from version.properties"
  lane :get_version do
    version_file = "../version.properties"
    if File.exist?(version_file)
      props = {}
      File.readlines(version_file).each do |line|
        key, value = line.strip.split("=")
        props[key] = value if key && value
      end
      UI.message("Version: #{props['VERSION_NAME']} (#{props['VERSION_CODE']})")
      props
    else
      UI.user_error!("version.properties not found. Run /devtools:version-management first.")
    end
  end

  # ============================================
  # Full Release Workflows
  # ============================================

  desc "Full internal release: screenshots + build + deploy"
  lane :release_internal do
    screenshots
    deploy_internal
  end

  desc "Full beta release: build + deploy"
  lane :release_beta do |options|
    deploy_beta(rollout: options[:rollout])
  end

  desc "Full production release: build + deploy with staged rollout"
  lane :release_production do |options|
    deploy_production(rollout: options[:rollout])
  end
end
```

### Step 7: Create Screengrabfile

Create `./fastlane/Screengrabfile`:

```ruby
# App package name
app_package_name("{PACKAGE_NAME}")

# Test instrumentation runner (AndroidX)
test_instrumentation_runner("androidx.test.runner.AndroidJUnitRunner")

# APK paths
app_apk_path("app/build/outputs/apk/debug/app-debug.apk")
tests_apk_path("app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")

# Locales to capture (add more as needed)
locales(["en-US"])

# Output directory (matches supply's expected structure)
output_directory("fastlane/metadata/android")

# Clear old screenshots
clear_previous_screenshots(true)

# Use specific test class for screenshots
use_tests_in_classes(["{PACKAGE_NAME}.screenshots.ScreenshotTest"])

# Ending locale (restore device to this locale after)
ending_locale("en-US")
```

**Important:** Replace `{PACKAGE_NAME}` with the actual package name.

### Step 8: Create Metadata Templates

Create initial metadata files:

#### `fastlane/metadata/android/en-US/title.txt`:
```
Your App Name
```

#### `fastlane/metadata/android/en-US/short_description.txt`:
```
Short description (max 80 characters)
```

#### `fastlane/metadata/android/en-US/full_description.txt`:
```
Full description of your app.

Features:
• Feature 1
• Feature 2
• Feature 3

For more information, visit our website.
```

#### `fastlane/metadata/android/en-US/changelogs/default.txt`:
```
• Bug fixes and performance improvements
```

#### `fastlane/metadata/android/en-US/video.txt`:
```
```
(Empty file - add YouTube URL if you have a promo video)

### Step 9: Update .gitignore

Add to `.gitignore`:

```gitignore
# Fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
vendor/bundle

# Don't ignore metadata (we want to track store listing)
!fastlane/metadata/
```

## Verification

**MANDATORY:** Run these commands:

```bash
# Verify Fastlane installed
bundle exec fastlane --version

# Verify lanes are available
bundle exec fastlane lanes

# Test service account connection (optional, requires service account JSON)
# bundle exec fastlane run validate_play_store_json_key
```

**Expected output:**
- Fastlane version number
- List of all lanes (deploy_internal, deploy_beta, etc.)

## Completion Criteria

- [ ] `Gemfile` exists with fastlane and screengrab
- [ ] `bundle install` succeeds
- [ ] `fastlane/Appfile` configured with package name
- [ ] `fastlane/Fastfile` has all deployment lanes
- [ ] `fastlane/Screengrabfile` configured
- [ ] Metadata directory structure created
- [ ] Metadata template files created
- [ ] `.gitignore` updated
- [ ] `bundle exec fastlane lanes` shows all lanes

## Outputs

| Output | Location | Description |
|--------|----------|-------------|
| Gemfile | ./Gemfile | Ruby dependencies |
| Gemfile.lock | ./Gemfile.lock | Locked dependency versions |
| Appfile | ./fastlane/Appfile | Fastlane app configuration |
| Fastfile | ./fastlane/Fastfile | Fastlane lanes |
| Screengrabfile | ./fastlane/Screengrabfile | Screenshot configuration |
| Metadata | ./fastlane/metadata/android/en-US/ | Store listing metadata |

## Troubleshooting

### "Ruby not found"
**Cause:** Ruby not installed
**Fix:** Install Ruby 2.7+ (use rbenv, rvm, or system package manager)

### "bundle: command not found"
**Cause:** Bundler not installed
**Fix:** Run `gem install bundler --no-document`

### "Fastlane lanes don't show"
**Cause:** Fastfile has syntax errors
**Fix:** Run `bundle exec fastlane lanes` and check for Ruby syntax errors

### "Service account validation fails"
**Cause:** Invalid or missing service account JSON
**Fix:** Ensure JSON file exists and has correct permissions in Play Console

## Next Steps

After completing this skill:
1. Run `/devtools:android-app-icon` to generate app icon
2. Run `/devtools:android-screenshot-automation` to setup screenshot capture
3. Run `/devtools:android-store-listing` to create feature graphic and metadata
4. Run `/devtools:android-workflow-internal` to setup GitHub Actions

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/hitoshura25) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-13 -->

