@@ -414,62 +414,159 @@ jobs:
414414 path : bundle-artifacts/
415415 continue-on-error : true
416416
417- - name : Download signed APK from Google Play
417+ - name : Download Google Play Signed APK
418418 id : download-apk
419419 env :
420420 PLAY_STORE_SERVICE_ACCOUNT_JSON : ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
421421 run : |
422- # Check if AAB exists
423- AAB_PATH=$(find bundle-artifacts -name "*.aab" 2>/dev/null | head -1)
424- if [ -z "$AAB_PATH" ]; then
425- echo "No AAB found in artifacts, skipping signed APK download"
426- echo "found=false" >> $GITHUB_OUTPUT
427- exit 0
428- fi
429-
430- echo "Found AAB: $AAB_PATH"
431-
432- # Download bundletool
433- echo "Downloading bundletool..."
434- curl -L -o bundletool-all.jar https://github.com/google/bundletool/releases/latest/download/bundletool-all.jar
435-
436- # Verify download
437- if [ ! -f bundletool-all.jar ]; then
438- echo "Failed to download bundletool"
439- exit 1
440- fi
441-
442- # Create a dummy debug keystore for bundletool (required for APK generation)
443- echo "Creating dummy keystore..."
444- keytool -genkey -v -keystore debug.keystore -alias androiddebugkey \
445- -keyalg RSA -keysize 2048 -validity 10000 \
446- -dname "CN=Android Debug,O=Android,C=US" \
447- -storepass android -keypass android
448-
449- # Generate universal APK from the AAB
450- echo "Generating universal APK set..."
451- java -jar bundletool-all.jar build-apks \
452- --bundle="$AAB_PATH" \
453- --output=apks.apks \
454- --mode=universal \
455- --ks=debug.keystore \
456- --ks-pass=pass:android \
457- --ks-key-alias=androiddebugkey \
458- --key-pass=pass:android
459-
460- # Extract the universal APK
461- unzip -q apks.apks universal.apk
462-
463422 VERSION_NAME="${{ needs.prepare.outputs.version }}"
464- OUTPUT_FILE="v2er-${VERSION_NAME}_google_play_signed.apk"
465-
466- # Note: This APK is signed with debug key, the actual Google Play signed APK
467- # is only available after deployment to Play Store
468- mv universal.apk "$OUTPUT_FILE"
423+ VERSION_CODE="${{ needs.prepare.outputs.version_code }}"
424+ PACKAGE_NAME="me.ghui.v2er"
425+
426+ # Create Python script to download signed universal APK
427+ cat > download_signed_apk.py << 'EOF'
428+ import json
429+ import os
430+ import sys
431+ import requests
432+ from google.oauth2 import service_account
433+ from googleapiclient.discovery import build
434+
435+ def download_signed_apk():
436+ try:
437+ # Load service account credentials
438+ service_account_info = json.loads(os.environ['PLAY_STORE_SERVICE_ACCOUNT_JSON'])
439+ credentials = service_account.Credentials.from_service_account_info(
440+ service_account_info,
441+ scopes=['https://www.googleapis.com/auth/androidpublisher']
442+ )
443+
444+ # Build the service
445+ service = build('androidpublisher', 'v3', credentials=credentials)
446+
447+ package_name = os.environ['PACKAGE_NAME']
448+ version_code = int(os.environ['VERSION_CODE'])
449+
450+ print(f"Attempting to download signed APK for {package_name} version {version_code}")
451+
452+ # Get the signed universal APK download URL
453+ # Note: This requires the app to be released and processed by Google Play
454+ result = service.generatedapks().list(
455+ packageName=package_name,
456+ versionCode=version_code
457+ ).execute()
458+
459+ if 'generatedApks' not in result or not result['generatedApks']:
460+ print("No generated APKs found. App may not be processed yet by Google Play.")
461+ return False
462+
463+ # Find universal APK
464+ universal_apk = None
465+ for apk in result['generatedApks']:
466+ if apk.get('targetingInfo', {}).get('abiTargeting') is None:
467+ # This should be the universal APK
468+ universal_apk = apk
469+ break
470+
471+ if not universal_apk:
472+ print("Universal APK not found in generated APKs")
473+ return False
474+
475+ # Download the APK
476+ download_url = universal_apk.get('downloadUrl')
477+ if not download_url:
478+ print("Download URL not available for universal APK")
479+ return False
480+
481+ print(f"Downloading APK from: {download_url}")
482+ response = requests.get(download_url, stream=True)
483+ response.raise_for_status()
484+
485+ output_filename = f"v2er-{os.environ['VERSION_NAME']}_google_play_signed.apk"
486+ with open(output_filename, 'wb') as f:
487+ for chunk in response.iter_content(chunk_size=8192):
488+ f.write(chunk)
489+
490+ print(f"Successfully downloaded: {output_filename}")
491+ print(f"apk_path={output_filename}")
492+
493+ return True
494+
495+ except Exception as e:
496+ print(f"Error downloading signed APK: {str(e)}")
497+ print("This may be because:")
498+ print("1. The app hasn't been processed by Google Play yet")
499+ print("2. The version hasn't been released to any track")
500+ print("3. API permissions are insufficient")
501+ return False
502+
503+ if __name__ == "__main__":
504+ success = download_signed_apk()
505+ sys.exit(0 if success else 1)
506+ EOF
469507
470- echo "Generated APK: $OUTPUT_FILE"
471- echo "apk_path=$OUTPUT_FILE" >> $GITHUB_OUTPUT
472- echo "found=true" >> $GITHUB_OUTPUT
508+ # Set environment variables for the script
509+ export PACKAGE_NAME="$PACKAGE_NAME"
510+ export VERSION_CODE="$VERSION_CODE"
511+ export VERSION_NAME="$VERSION_NAME"
512+
513+ # Run the download script
514+ echo "Attempting to download Google Play signed APK..."
515+ if python3 download_signed_apk.py > download_output.txt 2>&1; then
516+ echo "Successfully downloaded Google Play signed APK"
517+ cat download_output.txt
518+
519+ # Extract the APK path from output
520+ APK_PATH=$(grep "apk_path=" download_output.txt | cut -d'=' -f2)
521+ if [ -f "$APK_PATH" ]; then
522+ echo "apk_path=$APK_PATH" >> $GITHUB_OUTPUT
523+ echo "found=true" >> $GITHUB_OUTPUT
524+ else
525+ echo "APK file not found after download"
526+ echo "found=false" >> $GITHUB_OUTPUT
527+ fi
528+ else
529+ echo "Failed to download Google Play signed APK, falling back to universal APK generation"
530+ cat download_output.txt
531+
532+ # Fallback: Generate universal APK from AAB as before
533+ AAB_PATH=$(find bundle-artifacts -name "*.aab" 2>/dev/null | head -1)
534+ if [ -z "$AAB_PATH" ]; then
535+ echo "No AAB found for fallback, skipping"
536+ echo "found=false" >> $GITHUB_OUTPUT
537+ exit 0
538+ fi
539+
540+ echo "Generating universal APK from AAB as fallback..."
541+
542+ # Download bundletool
543+ curl -L -o bundletool-all.jar https://github.com/google/bundletool/releases/latest/download/bundletool-all.jar
544+
545+ # Create dummy keystore
546+ keytool -genkey -v -keystore debug.keystore -alias androiddebugkey \
547+ -keyalg RSA -keysize 2048 -validity 10000 \
548+ -dname "CN=Android Debug,O=Android,C=US" \
549+ -storepass android -keypass android
550+
551+ # Generate universal APK
552+ java -jar bundletool-all.jar build-apks \
553+ --bundle="$AAB_PATH" \
554+ --output=apks.apks \
555+ --mode=universal \
556+ --ks=debug.keystore \
557+ --ks-pass=pass:android \
558+ --ks-key-alias=androiddebugkey \
559+ --key-pass=pass:android
560+
561+ # Extract APK
562+ unzip -q apks.apks universal.apk
563+ OUTPUT_FILE="v2er-${VERSION_NAME}_google_play_signed.apk"
564+ mv universal.apk "$OUTPUT_FILE"
565+
566+ echo "Generated fallback APK: $OUTPUT_FILE"
567+ echo "apk_path=$OUTPUT_FILE" >> $GITHUB_OUTPUT
568+ echo "found=true" >> $GITHUB_OUTPUT
569+ fi
473570
474571 - name : Create Google Play link info
475572 if : steps.download-apk.outputs.found == 'true'
0 commit comments