Build FadCam Pro+ APK (Custom) #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build FadCam Pro+ APK (Custom) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| icon_base64: | |
| description: 'Icon image as base64 string (PNG/JPG)' | |
| required: true | |
| type: string | |
| app_name: | |
| description: 'Custom app name (max 50 chars, alphanumeric + spaces)' | |
| required: true | |
| type: string | |
| jobs: | |
| build-pro-plus-apk: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Java 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: 17 | |
| distribution: 'temurin' | |
| cache: 'gradle' | |
| - name: Install ImageMagick and WebP tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y imagemagick webp | |
| - name: Setup local.properties with release keystore | |
| run: | | |
| echo "KEYSTORE_FILE=$RUNNER_TEMP/release.keystore" >> local.properties | |
| echo "KEYSTORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> local.properties | |
| echo "KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> local.properties | |
| echo "KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> local.properties | |
| - name: Decode and write keystore | |
| run: | | |
| echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > $RUNNER_TEMP/release.keystore | |
| if [ ! -f "$RUNNER_TEMP/release.keystore" ]; then | |
| echo "❌ Keystore file not created" | |
| exit 1 | |
| fi | |
| echo "✓ Keystore file created" | |
| echo "✓ local.properties configured" | |
| - name: Validate and sanitize app name | |
| run: | | |
| APP_NAME="${{ inputs.app_name }}" | |
| # Check length | |
| if [ ${#APP_NAME} -gt 50 ]; then | |
| echo "❌ App name must be 50 characters or less" | |
| exit 1 | |
| fi | |
| # Remove leading/trailing whitespace and special characters | |
| # Keep only alphanumeric, spaces, and hyphens | |
| SANITIZED=$(echo "$APP_NAME" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | sed 's/[^a-zA-Z0-9 -]//g') | |
| # Verify it's not empty after sanitization | |
| if [ -z "$SANITIZED" ]; then | |
| echo "❌ App name contains no valid characters" | |
| exit 1 | |
| fi | |
| echo "FINAL_APP_NAME=$SANITIZED" >> $GITHUB_ENV | |
| echo "✓ App name sanitized: $SANITIZED" | |
| - name: Decode and validate icon | |
| run: | | |
| # Decode base64 to temp file | |
| echo "${{ inputs.icon_base64 }}" | base64 -d > /tmp/icon_temp.png | |
| # Check if file was created and is valid image | |
| if ! file /tmp/icon_temp.png | grep -q "image"; then | |
| echo "Invalid image file. Please provide a valid PNG or JPG image in base64 format" | |
| exit 1 | |
| fi | |
| # Check minimum size (192x192) | |
| DIMENSIONS=$(identify -format "%wx%h" /tmp/icon_temp.png) | |
| echo "Icon dimensions: $DIMENSIONS" | |
| WIDTH=$(echo $DIMENSIONS | cut -d'x' -f1) | |
| HEIGHT=$(echo $DIMENSIONS | cut -d'x' -f2) | |
| if [ $WIDTH -lt 192 ] || [ $HEIGHT -lt 192 ]; then | |
| echo "Icon must be at least 192x192 pixels" | |
| exit 1 | |
| fi | |
| echo "✓ Icon validated: ${WIDTH}x${HEIGHT}" | |
| - name: Process icon - resize and convert to WebP | |
| run: | | |
| # Define density sizes (mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi) | |
| SIZES=(48 72 96 144 192) | |
| DENSITY_NAMES=(mdpi hdpi xhdpi xxhdpi xxxhdpi) | |
| # Create temp directory for processed icons | |
| mkdir -p /tmp/icons_webp | |
| for i in "${!SIZES[@]}"; do | |
| SIZE=${SIZES[$i]} | |
| DENSITY=${DENSITY_NAMES[$i]} | |
| # Resize to square, convert to WebP | |
| convert /tmp/icon_temp.png \ | |
| -resize ${SIZE}x${SIZE}! \ | |
| -gravity center \ | |
| -extent ${SIZE}x${SIZE} \ | |
| /tmp/icons_webp/ic_launcher_${DENSITY}.webp | |
| echo "✓ Created ic_launcher_${DENSITY}.webp (${SIZE}x${SIZE})" | |
| done | |
| - name: Replace icon files in mipmap folders | |
| run: | | |
| SIZES=(48 72 96 144 192) | |
| DENSITY_NAMES=(mdpi hdpi xhdpi xxhdpi xxxhdpi) | |
| for i in "${!SIZES[@]}"; do | |
| DENSITY=${DENSITY_NAMES[$i]} | |
| # Replace all ic_launcher* files in this density folder | |
| MIPMAP_DIR="app/src/main/res/mipmap-${DENSITY}" | |
| if [ -d "$MIPMAP_DIR" ]; then | |
| # Copy processed icon as ic_launcher_foreground (what adaptive icon uses) | |
| cp /tmp/icons_webp/ic_launcher_${DENSITY}.webp "$MIPMAP_DIR/ic_launcher_foreground.webp" | |
| # Also update ic_launcher.webp for non-adaptive fallback | |
| cp /tmp/icons_webp/ic_launcher_${DENSITY}.webp "$MIPMAP_DIR/ic_launcher.webp" | |
| echo "✓ Updated $MIPMAP_DIR" | |
| fi | |
| done | |
| - name: Update app name in build config | |
| run: | | |
| APP_NAME="${{ inputs.app_name }}" | |
| echo "APP_NAME=$APP_NAME" >> $GITHUB_ENV | |
| - name: Build Pro+ APK (Custom build with user icon/name) | |
| run: | | |
| chmod +x ./gradlew | |
| # Build standalone proPlus with custom app name | |
| ./gradlew assembleProPlus -PcustomAppName="${{ env.FINAL_APP_NAME }}" | |
| - name: Verify APK was built | |
| run: | | |
| if [ -f "app/build/outputs/apk/default/proPlus/app-default-proPlus.apk" ]; then | |
| echo "✓ Pro+ APK built successfully" | |
| ls -lh app/build/outputs/apk/default/proPlus/app-default-proPlus.apk | |
| else | |
| echo "✗ APK not found" | |
| ls -lh app/build/outputs/apk/default/proPlus/ || echo "Directory doesn't exist" | |
| exit 1 | |
| fi | |
| - name: Upload APK artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: fadcam-pro-plus-apk | |
| path: app/build/outputs/apk/default/proPlus/app-default-proPlus.apk | |
| retention-days: 1 | |
| - name: Build summary | |
| run: | | |
| echo "## ✅ FadCam Pro+ APK Built Successfully" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Build Details:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- Package ID: com.fadcam.proplus" >> $GITHUB_STEP_SUMMARY | |
| echo "- App Name: ${{ env.FINAL_APP_NAME }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Build Type: Pro+ (Custom, Debuggable)" >> $GITHUB_STEP_SUMMARY | |
| echo "- Architecture: arm64-v8a" >> $GITHUB_STEP_SUMMARY | |
| echo "- Commit: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Timestamp: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Download:**" >> $GITHUB_STEP_SUMMARY | |
| echo "APK is available in the workflow artifacts (expires in 24 hours)" >> $GITHUB_STEP_SUMMARY |