Browse Source

feat: Add automatic Android asset validation to prevent build failures

- Add validate_android_assets() function to build-android.sh
- Check for missing source assets (icon.png, splash.png, splash_dark.png)
- Verify Android resources exist (drawable/splash.png, mipmap/*/ic_launcher*.png)
- Auto-regenerate missing resources using @capacitor/assets
- Integrate validation into main build process with exit code 9
- Add npm run assets:validate:android for manual validation
- Support --assets-only flag for asset-only operations
- Create comprehensive documentation in doc/android-asset-validation.md

Fixes build failures caused by missing drawable/splash and mipmap/ic_launcher resources.
Prevents "Android resource linking failed" errors during Gradle builds.

Resolves: Android build failures due to missing asset resources
android-safe-area-insets
Jose Olarte III 3 days ago
parent
commit
8fc9118d50
  1. 67
      BUILDING.md
  2. 238
      doc/android-asset-validation.md
  3. 1
      package.json
  4. 121
      scripts/build-android.sh

67
BUILDING.md

@ -164,6 +164,9 @@ npm run clean:android
npm run build:ios # Regenerates iOS project
npm run build:android # Regenerates Android project
# Fix Android asset issues
npm run assets:validate:android # Validates and regenerates missing Android assets
# Check environment
npm run test:web # Verifies web setup
```
@ -172,6 +175,7 @@ npm run test:web # Verifies web setup
- **iOS**: Ensure Xcode and Command Line Tools are installed
- **Android**: Ensure Android Studio and SDK are configured
- If you encounter "resource drawable/splash not found" errors, run `npm run assets:validate:android`
- **Electron**: Ensure platform-specific build tools are installed
### Next Steps
@ -1184,6 +1188,69 @@ npm run build:android:assets # Generate assets only
npm run build:android:deploy # Build and deploy to connected device
```
#### Android Asset Validation
The Android build system now includes automatic asset validation to prevent build failures caused by missing resources. This system:
- **Validates Source Assets**: Checks that required source files exist in `resources/`
- **Checks Android Resources**: Verifies that generated Android resources are present
- **Auto-Regenerates**: Automatically regenerates missing resources when detected
- **Provides Clear Errors**: Gives helpful guidance when issues occur
##### Asset Validation Commands
```bash
# Validate and regenerate Android assets if needed
npm run assets:validate:android
# Alternative command for asset validation
./scripts/build-android.sh --assets-only
# Check asset configuration only (no regeneration)
npm run assets:validate
```
##### What Gets Validated
**Source Assets (Required):**
- `resources/icon.png` - App icon source
- `resources/splash.png` - Splash screen source
- `resources/splash_dark.png` - Dark mode splash source
**Android Resources (Generated):**
- `android/app/src/main/res/drawable/splash.png` - Splash screen drawable
- `android/app/src/main/res/mipmap-*/ic_launcher.png` - App icons for all densities
- `android/app/src/main/res/mipmap-*/ic_launcher_round.png` - Round app icons for all densities
##### Automatic Validation
Asset validation runs automatically during all Android builds:
```bash
# All these commands now include asset validation
npm run build:android:studio
npm run build:android:prod
npm run build:android:debug
```
If validation fails, the build stops with clear error messages and guidance on how to fix the issues.
##### Troubleshooting Asset Issues
If you encounter asset-related build failures:
```bash
# Check what's missing
npm run assets:validate:android
# Clean and regenerate everything
npm run clean:android
npm run assets:validate:android
npm run build:android:studio
```
For more detailed information, see [Android Asset Validation Documentation](doc/android-asset-validation.md).
#### Android Automated Build Script
The recommended way to build for Android is using the automated build script:

238
doc/android-asset-validation.md

@ -0,0 +1,238 @@
# Android Asset Validation System
**Author**: Matthew Raymer
**Date**: 2025-08-22
**Status**: 🎯 **ACTIVE** - Production Ready
## Overview
The Android Asset Validation System automatically detects and fixes missing Android resources before building, preventing common build failures related to missing splash screens and app icons.
## Problem Solved
Previously, Android builds would fail with errors like:
```
error: resource drawable/splash (aka app.timesafari.app:drawable/splash) not found.
error: resource mipmap/ic_launcher (aka app.timesafari.app:mipmap/ic_launcher) not found.
```
This happened when:
- Source assets existed but weren't generated into Android resources
- Android resource directories were missing
- Asset generation tools weren't run before building
## Solution
### Enhanced Build Script Validation
The `scripts/build-android.sh` script now includes comprehensive asset validation that:
1. **Checks Source Assets**: Validates that required source files exist in `resources/`
2. **Checks Android Resources**: Verifies that generated Android resources exist
3. **Auto-Regenerates**: Automatically regenerates missing resources when detected
4. **Verifies Results**: Confirms that regeneration was successful
### Validation Process
```bash
# Validates and regenerates if needed
npm run assets:validate:android
# Full build with validation
npm run build:android:studio
```
### What Gets Validated
#### Source Assets (Required)
- `resources/icon.png` - App icon source
- `resources/splash.png` - Splash screen source
- `resources/splash_dark.png` - Dark mode splash source
#### Android Resources (Generated)
- `android/app/src/main/res/drawable/splash.png` - Splash screen drawable
- `android/app/src/main/res/mipmap-*/ic_launcher.png` - App icons for all densities
- `android/app/src/main/res/mipmap-*/ic_launcher_round.png` - Round app icons for all densities
### Density Levels Checked
- `mipmap-mdpi` (1x)
- `mipmap-hdpi` (1.5x)
- `mipmap-xhdpi` (2x)
- `mipmap-xxhdpi` (3x)
- `mipmap-xxxhdpi` (4x)
## Usage
### Automatic Validation (Recommended)
The validation runs automatically during all Android builds:
```bash
# Development build with validation
npm run build:android:studio
# Production build with validation
npm run build:android:prod
# Debug build with validation
npm run build:android:debug
```
### Manual Validation
Run validation only to check/fix assets:
```bash
# Validate and regenerate if needed
npm run assets:validate:android
# Alternative command
./scripts/build-android.sh --assets-only
```
### Validation Only (No Regeneration)
Check configuration without fixing:
```bash
npm run assets:validate
```
## Error Handling
### Missing Source Assets
If source assets are missing, the build fails with clear error messages:
```
[ERROR] Missing source assets:
[ERROR] - resources/icon.png
[ERROR] - resources/splash.png
[ERROR] Please ensure all required assets are present in the resources/ directory.
```
### Missing Generated Resources
If generated resources are missing, they're automatically regenerated:
```
[WARN] Missing Android resources detected:
[WARN] - drawable/splash.png
[WARN] - mipmap-mdpi/ic_launcher.png
[INFO] Regenerating Android assets...
[SUCCESS] Android assets regenerated successfully
```
### Generation Failure
If regeneration fails, helpful guidance is provided:
```
[ERROR] Failed to generate Android assets
[INFO] You may need to manually create the missing resources:
[INFO] - android/app/src/main/res/drawable/splash.png
[INFO] - android/app/src/main/res/mipmap-mdpi/ic_launcher.png
```
## Integration Points
### Build Script Integration
The validation is integrated into the main build process:
```bash
# In scripts/build-android.sh
validate_dependencies
validate_android_assets || {
log_error "Android asset validation failed. Please fix the issues above and try again."
exit 9
}
```
### NPM Scripts
New npm scripts for asset management:
```json
{
"assets:validate": "npx tsx scripts/assets-validator.ts",
"assets:validate:android": "./scripts/build-android.sh --assets-only",
"assets:clean": "rimraf android/app/src/main/res/mipmap-* ios/App/App/Assets.xcassets/**/AppIcon*.png ios/App/App/Assets.xcassets/**/Splash*.png || true"
}
```
## Benefits
### For Developers
- **No More Build Failures**: Automatic detection and fixing of missing resources
- **Faster Development**: No need to manually run asset generation tools
- **Clear Error Messages**: Helpful guidance when issues occur
- **Consistent Results**: Same validation on all development machines
### For CI/CD
- **Reliable Builds**: Consistent asset validation across environments
- **Early Detection**: Catches issues before they reach production
- **Automated Fixes**: Self-healing builds when possible
### For Project Maintenance
- **Reduced Support**: Fewer "build doesn't work" issues
- **Documentation**: Clear requirements for required assets
- **Standardization**: Consistent asset structure across the project
## Troubleshooting
### Common Issues
#### "No assets found in the asset path"
This occurs when the `assets/` directory is empty. The validation system automatically copies source assets and regenerates them.
#### "Failed to generate Android assets"
Check that:
- Source assets exist in `resources/`
- `@capacitor/assets` is installed
- You have write permissions to the Android directories
#### "Asset generation completed but some resources are still missing"
This indicates a problem with the asset generation tool. Try:
1. Running `npm install` to ensure dependencies are up to date
2. Manually running `npx @capacitor/assets generate`
3. Checking the asset generation logs for specific errors
### Manual Recovery
If automatic regeneration fails, you can manually create the missing resources:
```bash
# Create missing directories
mkdir -p android/app/src/main/res/drawable
mkdir -p android/app/src/main/res/mipmap-{mdpi,hdpi,xhdpi,xxhdpi,xxxhdpi}
# Copy source assets to assets directory
cp resources/icon.png assets/
cp resources/splash.png assets/
cp resources/splash_dark.png assets/
# Generate assets manually
npx @capacitor/assets generate
# Clean up
rm assets/icon.png assets/splash.png assets/splash_dark.png
```
## Future Enhancements
### Planned Improvements
- **iOS Asset Validation**: Extend validation to iOS assets
- **Asset Quality Checks**: Validate image dimensions and formats
- **Performance Optimization**: Cache validation results
- **CI/CD Integration**: Add validation to GitHub Actions
### Configuration Options
- **Custom Asset Paths**: Support for different asset directory structures
- **Validation Rules**: Configurable validation requirements
- **Skip Options**: Ability to skip validation for specific scenarios
## References
- [Capacitor Assets Documentation](https://github.com/ionic-team/capacitor-assets)
- [Android Resource System](https://developer.android.com/guide/topics/resources/providing-resources)
- [Build Script Documentation](./build-android.sh)
- [Asset Configuration](./capacitor-assets.config.json)
---
**Status**: Active validation system
**Priority**: High
**Maintainer**: Development team
**Next Review**: 2025-09-22

1
package.json

@ -31,6 +31,7 @@
"build:native": "vite build && npx cap sync && npx capacitor-assets generate",
"assets:config": "npx tsx scripts/assets-config.ts",
"assets:validate": "npx tsx scripts/assets-validator.ts",
"assets:validate:android": "./scripts/build-android.sh --assets-only",
"assets:clean": "rimraf android/app/src/main/res/mipmap-* ios/App/App/Assets.xcassets/**/AppIcon*.png ios/App/App/Assets.xcassets/**/Splash*.png || true",
"build:ios": "./scripts/build-ios.sh",
"build:ios:dev": "./scripts/build-ios.sh --dev",

121
scripts/build-android.sh

@ -41,7 +41,7 @@
# 6 - Capacitor sync failed
# 7 - Asset generation failed
# 8 - Android Studio launch failed
# 9 - Resource check failed
# 9 - Android asset validation failed
# Exit on any error
set -e
@ -74,6 +74,117 @@ validate_dependencies() {
log_success "All critical dependencies validated successfully"
}
# Function to validate Android assets and resources
validate_android_assets() {
log_info "Validating Android assets and resources..."
# Check if source assets exist
local missing_assets=()
if [ ! -f "resources/icon.png" ]; then
missing_assets+=("resources/icon.png")
fi
if [ ! -f "resources/splash.png" ]; then
missing_assets+=("resources/splash.png")
fi
if [ ! -f "resources/splash_dark.png" ]; then
missing_assets+=("resources/splash_dark.png")
fi
if [ ${#missing_assets[@]} -gt 0 ]; then
log_error "Missing source assets:"
for asset in "${missing_assets[@]}"; do
log_error " - $asset"
done
log_error "Please ensure all required assets are present in the resources/ directory."
return 1
fi
# Check if Android drawable resources exist
local missing_drawables=()
if [ ! -f "android/app/src/main/res/drawable/splash.png" ]; then
missing_drawables+=("drawable/splash.png")
fi
# Check if mipmap resources exist
local missing_mipmaps=()
local mipmap_dirs=("mipmap-mdpi" "mipmap-hdpi" "mipmap-xhdpi" "mipmap-xxhdpi" "mipmap-xxxhdpi")
for dir in "${mipmap_dirs[@]}"; do
if [ ! -f "android/app/src/main/res/$dir/ic_launcher.png" ]; then
missing_mipmaps+=("$dir/ic_launcher.png")
fi
if [ ! -f "android/app/src/main/res/$dir/ic_launcher_round.png" ]; then
missing_mipmaps+=("$dir/ic_launcher_round.png")
fi
done
# If any resources are missing, regenerate them
if [ ${#missing_drawables[@]} -gt 0 ] || [ ${#missing_mipmaps[@]} -gt 0 ]; then
log_warn "Missing Android resources detected:"
for resource in "${missing_drawables[@]}" "${missing_mipmaps[@]}"; do
log_warn " - $resource"
done
log_info "Regenerating Android assets..."
# Create assets directory if it doesn't exist
mkdir -p assets
# Copy source assets to assets directory for capacitor-assets
cp resources/icon.png assets/ 2>/dev/null || log_warn "Could not copy icon.png"
cp resources/splash.png assets/ 2>/dev/null || log_warn "Could not copy splash.png"
cp resources/splash_dark.png assets/ 2>/dev/null || log_warn "Could not copy splash_dark.png"
# Generate assets
if npx @capacitor/assets generate >/dev/null 2>&1; then
log_success "Android assets regenerated successfully"
# Clean up temporary assets
rm -f assets/icon.png assets/splash.png assets/splash_dark.png
# Verify the resources were created
local verification_failed=false
if [ ! -f "android/app/src/main/res/drawable/splash.png" ]; then
log_error "Failed to generate drawable/splash.png"
verification_failed=true
fi
for dir in "${mipmap_dirs[@]}"; do
if [ ! -f "android/app/src/main/res/$dir/ic_launcher.png" ]; then
log_error "Failed to generate $dir/ic_launcher.png"
verification_failed=true
fi
if [ ! -f "android/app/src/main/res/$dir/ic_launcher_round.png" ]; then
log_error "Failed to generate $dir/ic_launcher_round.png"
verification_failed=true
fi
done
if [ "$verification_failed" = true ]; then
log_error "Asset generation completed but some resources are still missing."
log_info "You may need to manually create the missing resources or check the asset generation process."
return 1
fi
else
log_error "Failed to generate Android assets"
log_info "You may need to manually create the missing resources:"
for resource in "${missing_drawables[@]}" "${missing_mipmaps[@]}"; do
log_info " - android/app/src/main/res/$resource"
done
return 1
fi
else
log_success "All Android assets and resources validated successfully"
fi
return 0
}
# Default values
BUILD_MODE="development"
BUILD_TYPE="debug"
@ -126,7 +237,7 @@ parse_android_args() {
--sync)
SYNC_ONLY=true
;;
--assets)
--assets|--assets-only)
ASSETS_ONLY=true
;;
--deploy)
@ -208,6 +319,12 @@ print_header "TimeSafari Android Build Process"
# Validate dependencies before proceeding
validate_dependencies
# Validate Android assets and resources
validate_android_assets || {
log_error "Android asset validation failed. Please fix the issues above and try again."
exit 9
}
# Log build start
log_info "Starting Android build process at $(date)"
log_info "Build mode: $BUILD_MODE"

Loading…
Cancel
Save