forked from trent_larson/crowd-funder-for-time-pwa
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
This commit is contained in:
67
BUILDING.md
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
Normal file
238
doc/android-asset-validation.md
Normal file
@@ -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
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user