diff --git a/BUILDING.md b/BUILDING.md index 7ac1c1a8..a54742f6 100644 --- a/BUILDING.md +++ b/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: diff --git a/doc/android-asset-validation.md b/doc/android-asset-validation.md new file mode 100644 index 00000000..db77aeb8 --- /dev/null +++ b/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 diff --git a/package.json b/package.json index 77a4ac92..1eee0271 100644 --- a/package.json +++ b/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", diff --git a/scripts/build-android.sh b/scripts/build-android.sh index c795a4b0..f57f70c7 100755 --- a/scripts/build-android.sh +++ b/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"