From ab7583eaee48f76143cbca441a62e6ff6e8574ab Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 15:21:06 +0000 Subject: [PATCH 1/7] feat: Add OnePlus 15 Hyper Frames support and fix package name dependency - Implemented Hyper Frames (165Hz) support in `XServerScreen.kt` when using System driver and Adreno Toolkit is disabled. - Refactored `Container.java`, `ShortcutUtils.kt`, and `AndroidManifest.xml` to use dynamic package name (`BuildConfig.APPLICATION_ID`) instead of hardcoded `app.gamenative`. This allows changing the package name (e.g., for system whitelist spoofing) without breaking container paths and shortcuts. --- app/src/main/AndroidManifest.xml | 2 +- .../ui/screen/xserver/XServerScreen.kt | 32 +++++++++++++++++++ .../app/gamenative/utils/ShortcutUtils.kt | 3 +- .../com/winlator/container/Container.java | 16 ++++++---- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index af29c3906..137b452eb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,7 +52,7 @@ android:scheme="home" /> - + diff --git a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt index a96062aa0..85951521e 100644 --- a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt @@ -27,6 +27,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -186,6 +187,37 @@ fun XServerScreen( ContainerUtils.getContainer(context, appId) } + // Hyper Frames (OnePlus 15 / 165Hz support) + LaunchedEffect(Unit) { + val graphicsDriverConfig = KeyValueSet(container.getGraphicsDriverConfig()) + val isAdrenotoolsTurnip = graphicsDriverConfig.get("adrenotoolsTurnip", "1") + val driverVersion = graphicsDriverConfig.get("version", DefaultVersion.WRAPPER) + + // Check if using system driver and adreno toolkit is disabled + val isWrapperOrSystem = !listOf("turnip", "virgl", "vortek", "adreno", "sd-8-elite").contains(container.graphicsDriver) + + if (isWrapperOrSystem && driverVersion == "System" && isAdrenotoolsTurnip == "0") { + val activity = context as? Activity + activity?.let { act -> + act.window?.let { window -> + val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + act.display + } else { + @Suppress("DEPRECATION") + act.windowManager.defaultDisplay + } + + display?.supportedModes?.maxByOrNull { it.refreshRate }?.let { maxMode -> + Timber.i("Hyper Frames: Setting preferred display mode to ${maxMode.modeId} (${maxMode.refreshRate} Hz)") + val layoutParams = window.attributes + layoutParams.preferredDisplayModeId = maxMode.modeId + window.attributes = layoutParams + } + } + } + } + } + val xServerState = rememberSaveable(stateSaver = XServerState.Saver) { mutableStateOf( XServerState( diff --git a/app/src/main/java/app/gamenative/utils/ShortcutUtils.kt b/app/src/main/java/app/gamenative/utils/ShortcutUtils.kt index 849baa724..c4c1d832c 100644 --- a/app/src/main/java/app/gamenative/utils/ShortcutUtils.kt +++ b/app/src/main/java/app/gamenative/utils/ShortcutUtils.kt @@ -12,6 +12,7 @@ import android.graphics.RectF import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Icon import android.os.Build +import app.gamenative.BuildConfig import app.gamenative.MainActivity import app.gamenative.R import coil.ImageLoader @@ -88,7 +89,7 @@ internal suspend fun createPinnedShortcut(context: Context, gameId: Int, label: val appContext = context.applicationContext val shortcutManager = appContext.getSystemService(ShortcutManager::class.java) - val intent = Intent("app.gamenative.LAUNCH_GAME").apply { + val intent = Intent(BuildConfig.APPLICATION_ID + ".LAUNCH_GAME").apply { setClass(appContext, MainActivity::class.java) putExtra("app_id", gameId) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) diff --git a/app/src/main/java/com/winlator/container/Container.java b/app/src/main/java/com/winlator/container/Container.java index 21dc53d7d..e8041bde6 100644 --- a/app/src/main/java/com/winlator/container/Container.java +++ b/app/src/main/java/com/winlator/container/Container.java @@ -20,6 +20,8 @@ import java.io.File; import java.util.Iterator; +import app.gamenative.BuildConfig; + public class Container { public enum XrControllerMapping { BUTTON_A, BUTTON_B, BUTTON_X, BUTTON_Y, BUTTON_GRIP, BUTTON_TRIGGER, @@ -38,14 +40,14 @@ public enum XrControllerMapping { public static final String DEFAULT_WINCOMPONENTS = "direct3d=1,directsound=1,directmusic=0,directshow=0,directplay=0,vcrun2010=1,wmdecoder=1,opengl=0"; public static final String FALLBACK_WINCOMPONENTS = "direct3d=1,directsound=1,directmusic=1,directshow=1,directplay=1,vcrun2010=1,wmdecoder=1,opengl=0"; public static final String[] MEDIACONV_ENV_VARS = { - "MEDIACONV_AUDIO_DUMP_FILE=/data/data/app.gamenative/files/imagefs/home/xuser/audio.dmp", - "MEDIACONV_VIDEO_DUMP_FILE=/data/data/app.gamenative/files/imagefs/home/xuser/video.dmp", - "MEDIACONV_VIDEO_TRANSCODED_FILE=/data/data/app.gamenative/files/imagefs/home/xuser/transcoded.mkv", - "MEDIACONV_AUDIO_TRANSCODED_FILE=/data/data/app.gamenative/files/imagefs/home/xuser/transcoded.wav", - "MEDIACONV_BLANK_AUDIO_FILE=/data/data/app.gamenative/files/imagefs/home/xuser/blank.wav", - "MEDIACONV_BLANK_VIDEO_FILE=/data/data/app.gamenative/files/imagefs/home/xuser/blank.mkv", + "MEDIACONV_AUDIO_DUMP_FILE=/data/data/" + BuildConfig.APPLICATION_ID + "/files/imagefs/home/xuser/audio.dmp", + "MEDIACONV_VIDEO_DUMP_FILE=/data/data/" + BuildConfig.APPLICATION_ID + "/files/imagefs/home/xuser/video.dmp", + "MEDIACONV_VIDEO_TRANSCODED_FILE=/data/data/" + BuildConfig.APPLICATION_ID + "/files/imagefs/home/xuser/transcoded.mkv", + "MEDIACONV_AUDIO_TRANSCODED_FILE=/data/data/" + BuildConfig.APPLICATION_ID + "/files/imagefs/home/xuser/transcoded.wav", + "MEDIACONV_BLANK_AUDIO_FILE=/data/data/" + BuildConfig.APPLICATION_ID + "/files/imagefs/home/xuser/blank.wav", + "MEDIACONV_BLANK_VIDEO_FILE=/data/data/" + BuildConfig.APPLICATION_ID + "/files/imagefs/home/xuser/blank.mkv", }; - public static final String DEFAULT_DRIVES = "D:"+Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"E:/data/data/app.gamenative/storage"; + public static final String DEFAULT_DRIVES = "D:"+Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"E:/data/data/" + BuildConfig.APPLICATION_ID + "/storage"; public static final String DEFAULT_VARIANT = DefaultVersion.VARIANT; public static final String DEFAULT_WINE_VERSION = DefaultVersion.WINE_VERSION; public static final byte STARTUP_SELECTION_NORMAL = 0; From 277df431c528bdd70f4743aeaff9f5c29960fba5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 15:31:54 +0000 Subject: [PATCH 2/7] Add GitHub Actions workflow to build main branch This commit introduces a new workflow `.github/workflows/main_build.yml` to ensure the main branch builds correctly. The workflow: - Triggers on push and pull requests to `master`, and manual dispatch. - Sets up Java 17 and Gradle. - Injects required credentials into `local.properties` (PostHog, Supabase). - Runs `assembleDebug`, `assembleRelease`, and `testDebugUnitTest`. - Uploads the generated Debug and Release APKs as artifacts. This ensures that the codebase is buildable and tests pass. --- .github/workflows/main_build.yml | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/main_build.yml diff --git a/.github/workflows/main_build.yml b/.github/workflows/main_build.yml new file mode 100644 index 000000000..2564e1a45 --- /dev/null +++ b/.github/workflows/main_build.yml @@ -0,0 +1,58 @@ +name: Build Main Branch + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Java 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Inject credentials + run: | + cat < local.properties + POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }} + POSTHOG_HOST=${{ secrets.POSTHOG_HOST }} + SUPABASE_URL=${{ secrets.SUPABASE_URL }} + SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} + EOF + + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v4 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build Debug APK + run: ./gradlew assembleDebug + + - name: Build Release APK + run: ./gradlew assembleRelease + + - name: Run Unit Tests + run: ./gradlew testDebugUnitTest + + - name: Upload Debug APK + uses: actions/upload-artifact@v4 + with: + name: app-debug + path: app/build/outputs/apk/debug/app-debug.apk + + - name: Upload Release APK + uses: actions/upload-artifact@v4 + with: + name: app-release + path: app/build/outputs/apk/release/app-release.apk From 2ccf08d55d63321959a2248dae0f5cce47fd0b42 Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Fri, 2 Jan 2026 10:53:47 -0500 Subject: [PATCH 3/7] Delete .github/workflows/tagged-release.yml --- .github/workflows/tagged-release.yml | 149 --------------------------- 1 file changed, 149 deletions(-) delete mode 100644 .github/workflows/tagged-release.yml diff --git a/.github/workflows/tagged-release.yml b/.github/workflows/tagged-release.yml deleted file mode 100644 index be62bc1fa..000000000 --- a/.github/workflows/tagged-release.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: Create tagged prerelease - -on: - push: - tags: - - "v*" - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: set up Java 17 - uses: actions/setup-java@v4 - with: - java-version: "17" - distribution: "temurin" - cache: gradle - - - name: Validate Gradle wrapper - uses: gradle/actions/wrapper-validation@v4 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Configure Keystore - env: - KEYSTORE: ${{ secrets.KEYSTORE }} - KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} - KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} - KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} - run: | - mkdir -p app/keystores - echo "$KEYSTORE" | base64 --decode > app/keystores/keystore - echo "storeFile=keystores/keystore" >> app/keystores/keystore.properties - echo "keyAlias=$KEYSTORE_KEY_ALIAS" >> app/keystores/keystore.properties - echo "storePassword=$KEYSTORE_STORE_PASSWORD" >> app/keystores/keystore.properties - echo "keyPassword=$KEYSTORE_KEY_PASSWORD" >> app/keystores/keystore.properties - - - name: Configure Production Keystore - env: - PROD_KEYSTORE: ${{ secrets.PROD_KEYSTORE }} - PROD_KEYSTORE_KEY_ALIAS: ${{ secrets.PROD_KEYSTORE_KEY_ALIAS }} - PROD_KEYSTORE_KEY_PASSWORD: ${{ secrets.PROD_KEYSTORE_KEY_PASSWORD }} - PROD_KEYSTORE_STORE_PASSWORD: ${{ secrets.PROD_KEYSTORE_STORE_PASSWORD }} - run: | - mkdir -p app/keystores - echo "$PROD_KEYSTORE" | base64 --decode > app/keystores/prod.keystore - cat < app/keystores/prod-keystore.properties - keyAlias=$PROD_KEYSTORE_KEY_ALIAS - keyPassword=$PROD_KEYSTORE_KEY_PASSWORD - storePassword=$PROD_KEYSTORE_STORE_PASSWORD - EOF - - - name: Inject credentials - run: | - cat < local.properties - POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }} - POSTHOG_HOST=${{ secrets.POSTHOG_HOST }} - SUPABASE_URL=${{ secrets.SUPABASE_URL }} - SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} - EOF - - - name: Install Android SDK Build Tools - run: | - SDKMANAGER="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" - if [ ! -x "$SDKMANAGER" ]; then - SDKMANAGER="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" - fi - yes | "$SDKMANAGER" --install "build-tools;34.0.0" - - - name: Build with Gradle - run: ./gradlew :app:bundleRelease - - - name: Extract APK from Bundle - run: | - java -jar tools/bundletool-all-1.17.2.jar build-apks \ - --bundle=app/build/outputs/bundle/release/app-release.aab \ - --output=app-release.apks \ - --mode=universal - unzip -o app-release.apks universal.apk - - - name: Copy lineage file - run: | - mkdir -p app/keystores - cp prod-debug.lineage app/keystores/prod-debug.lineage - - - name: Dual sign universal APK - env: - DEBUG_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} - DEBUG_KEY_PASS: ${{ secrets.KEYSTORE_KEY_PASSWORD }} - DEBUG_STORE_PASS: ${{ secrets.KEYSTORE_STORE_PASSWORD }} - PROD_ALIAS: ${{ secrets.PROD_KEYSTORE_KEY_ALIAS }} - PROD_KEY_PASS: ${{ secrets.PROD_KEYSTORE_KEY_PASSWORD }} - PROD_STORE_PASS: ${{ secrets.PROD_KEYSTORE_STORE_PASSWORD }} - run: | - BUILD_TOOLS_DIR="${ANDROID_HOME}/build-tools/34.0.0" - if [ ! -d "$BUILD_TOOLS_DIR" ]; then - BUILD_TOOLS_DIR="${ANDROID_SDK_ROOT}/build-tools/34.0.0" - fi - "${BUILD_TOOLS_DIR}/apksigner" sign \ - --lineage app/keystores/prod-debug.lineage \ - --ks app/keystores/keystore \ - --ks-key-alias "$DEBUG_ALIAS" \ - --ks-pass pass:$DEBUG_STORE_PASS \ - --key-pass pass:$DEBUG_KEY_PASS \ - --next-signer --ks app/keystores/prod.keystore \ - --ks-key-alias "$PROD_ALIAS" \ - --ks-pass pass:$PROD_STORE_PASS \ - --key-pass pass:$PROD_KEY_PASS \ - --out universal-signed.apk \ - universal.apk - mv universal-signed.apk universal.apk - - - name: Upload APK for next job - uses: actions/upload-artifact@v4 - with: - name: universal-apk - path: universal.apk - - release: - needs: build - runs-on: ubuntu-latest - - steps: - - name: Download built APK - uses: actions/download-artifact@v4 - with: - name: universal-apk - path: ./ - - - name: Rename APK - run: | - TAG="${GITHUB_REF#refs/tags/}" - mv universal.apk "gamenative-$TAG.apk" - - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ github.ref_name }} - name: ${{ github.ref_name }} - prerelease: true - generate_release_notes: true - files: gamenative-${{ github.ref_name }}.apk - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 8091b6ac3fdabdf87863ccc07ba71a40a1eab962 Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Fri, 2 Jan 2026 10:54:10 -0500 Subject: [PATCH 4/7] Delete .github/workflows/pluvia-pr-check.yml --- .github/workflows/pluvia-pr-check.yml | 38 --------------------------- 1 file changed, 38 deletions(-) delete mode 100644 .github/workflows/pluvia-pr-check.yml diff --git a/.github/workflows/pluvia-pr-check.yml b/.github/workflows/pluvia-pr-check.yml deleted file mode 100644 index c7a45e74b..000000000 --- a/.github/workflows/pluvia-pr-check.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Pull Request build check - -on: - pull_request: - branches: [ "master" ] - paths-ignore: - - '**.md' - - '.gitignore' - - 'keyvalues/**' - - 'media/**' - - '.github/ISSUE_TEMPLATE/**' - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checking out GameNative - uses: actions/checkout@v4 - - name: Setup Java 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - name: Inject credentials - run: | - cat < local.properties - POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }} - POSTHOG_HOST=${{ secrets.POSTHOG_HOST }} - SUPABASE_URL=${{ secrets.SUPABASE_URL }} - SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} - EOF - - name: Validate Gradle wrapper - uses: gradle/actions/wrapper-validation@v4 - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - name: Run unit tests - run: ./gradlew :app:testDebugUnitTest From 9d6a5eef1d1894727c7f395d96586556e2509eee Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Fri, 2 Jan 2026 10:54:40 -0500 Subject: [PATCH 5/7] Update main_build.yml --- .github/workflows/main_build.yml | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/.github/workflows/main_build.yml b/.github/workflows/main_build.yml index 2564e1a45..9559fba7f 100644 --- a/.github/workflows/main_build.yml +++ b/.github/workflows/main_build.yml @@ -13,13 +13,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + [span_0](start_span)uses: actions/checkout@v4[span_0](end_span) - name: Setup Java 17 - uses: actions/setup-java@v4 + [span_1](start_span)uses: actions/setup-java@v4[span_1](end_span) with: java-version: '17' - distribution: 'temurin' + [span_2](start_span)distribution: 'temurin'[span_2](end_span) - name: Inject credentials run: | @@ -29,30 +29,20 @@ jobs: SUPABASE_URL=${{ secrets.SUPABASE_URL }} SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} EOF + [span_3](start_span)# - name: Validate Gradle wrapper - uses: gradle/actions/wrapper-validation@v4 + uses: gradle/actions/wrapper-validation@v4[span_3](end_span) - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Build Debug APK - run: ./gradlew assembleDebug + [span_4](start_span)uses: gradle/actions/setup-gradle@v4[span_4](end_span) - name: Build Release APK - run: ./gradlew assembleRelease - - - name: Run Unit Tests - run: ./gradlew testDebugUnitTest - - - name: Upload Debug APK - uses: actions/upload-artifact@v4 - with: - name: app-debug - path: app/build/outputs/apk/debug/app-debug.apk + [span_5](start_span)run: ./gradlew assembleRelease[span_5](end_span) - name: Upload Release APK - uses: actions/upload-artifact@v4 + [span_6](start_span)uses: actions/upload-artifact@v4[span_6](end_span) with: name: app-release - path: app/build/outputs/apk/release/app-release.apk + [span_7](start_span)path: app/build/outputs/apk/release/app-release.apk[span_7](end_span) + From 767c6e7490314e4b240f7a5f7df4303db092052f Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Fri, 2 Jan 2026 11:07:10 -0500 Subject: [PATCH 6/7] Update app-release-signed.yml --- .github/workflows/app-release-signed.yml | 96 ++++-------------------- 1 file changed, 13 insertions(+), 83 deletions(-) diff --git a/.github/workflows/app-release-signed.yml b/.github/workflows/app-release-signed.yml index e8d2918a8..a647c179e 100644 --- a/.github/workflows/app-release-signed.yml +++ b/.github/workflows/app-release-signed.yml @@ -13,58 +13,32 @@ on: jobs: build: - runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: set up Java 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' cache: gradle + - name: Validate Gradle wrapper uses: gradle/actions/wrapper-validation@v4 + - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 - - name: Configure Keystore - env: - KEYSTORE: ${{ secrets.KEYSTORE }} - KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} - KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} - KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} - run: | - mkdir -p app/keystores - echo "$KEYSTORE" | base64 --decode > app/keystores/keystore - echo "storeFile=keystores/keystore" >> app/keystores/keystore.properties - echo "keyAlias=$KEYSTORE_KEY_ALIAS" >> app/keystores/keystore.properties - echo "storePassword=$KEYSTORE_STORE_PASSWORD" >> app/keystores/keystore.properties - echo "keyPassword=$KEYSTORE_KEY_PASSWORD" >> app/keystores/keystore.properties - - - name: Configure Production Keystore - env: - PROD_KEYSTORE: ${{ secrets.PROD_KEYSTORE }} - PROD_KEYSTORE_KEY_ALIAS: ${{ secrets.PROD_KEYSTORE_KEY_ALIAS }} - PROD_KEYSTORE_KEY_PASSWORD: ${{ secrets.PROD_KEYSTORE_KEY_PASSWORD }} - PROD_KEYSTORE_STORE_PASSWORD: ${{ secrets.PROD_KEYSTORE_STORE_PASSWORD }} - run: | - mkdir -p app/keystores - echo "$PROD_KEYSTORE" | base64 --decode > app/keystores/prod.keystore - cat < app/keystores/prod-keystore.properties - keyAlias=$PROD_KEYSTORE_KEY_ALIAS - keyPassword=$PROD_KEYSTORE_KEY_PASSWORD - storePassword=$PROD_KEYSTORE_STORE_PASSWORD - EOF - + # REPLACED: Secrets are removed. Empty strings "" prevent the Java syntax error. - name: Inject credentials run: | cat < local.properties - POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }} - POSTHOG_HOST=${{ secrets.POSTHOG_HOST }} - SUPABASE_URL=${{ secrets.SUPABASE_URL }} - SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} + POSTHOG_API_KEY="" + POSTHOG_HOST="" + SUPABASE_URL="" + SUPABASE_KEY="" EOF - name: Install Android SDK Build Tools @@ -75,52 +49,15 @@ jobs: fi yes | "$SDKMANAGER" --install "build-tools;34.0.0" + # CHANGED: Switched to assembleDebug so we don't need signing keys - name: Build with Gradle - run: ./gradlew :app:bundleRelease - - - name: Extract APK from Bundle - run: | - java -jar tools/bundletool-all-1.17.2.jar build-apks --bundle=app/build/outputs/bundle/release/app-release.aab --output=app-release.apks --mode=universal - unzip -o app-release.apks universal.apk - - - name: Copy lineage file - run: | - mkdir -p app/keystores - cp prod-debug.lineage app/keystores/prod-debug.lineage - - - name: Dual sign universal APK - env: - DEBUG_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} - DEBUG_KEY_PASS: ${{ secrets.KEYSTORE_KEY_PASSWORD }} - DEBUG_STORE_PASS: ${{ secrets.KEYSTORE_STORE_PASSWORD }} - PROD_ALIAS: ${{ secrets.PROD_KEYSTORE_KEY_ALIAS }} - PROD_KEY_PASS: ${{ secrets.PROD_KEYSTORE_KEY_PASSWORD }} - PROD_STORE_PASS: ${{ secrets.PROD_KEYSTORE_STORE_PASSWORD }} - run: | - BUILD_TOOLS_DIR="${ANDROID_HOME}/build-tools/34.0.0" - if [ ! -d "$BUILD_TOOLS_DIR" ]; then - BUILD_TOOLS_DIR="${ANDROID_SDK_ROOT}/build-tools/34.0.0" - fi - "${BUILD_TOOLS_DIR}/apksigner" sign \ - --lineage app/keystores/prod-debug.lineage \ - --ks app/keystores/keystore \ - --ks-key-alias "$DEBUG_ALIAS" \ - --ks-pass pass:$DEBUG_STORE_PASS \ - --key-pass pass:$DEBUG_KEY_PASS \ - --next-signer --ks app/keystores/prod.keystore \ - --ks-key-alias "$PROD_ALIAS" \ - --ks-pass pass:$PROD_STORE_PASS \ - --key-pass pass:$PROD_KEY_PASS \ - --out universal-signed.apk \ - universal.apk - mv universal-signed.apk universal.apk + run: ./gradlew assembleDebug - name: Upload Artifact - id: upload_app uses: actions/upload-artifact@v4 with: - name: app-release-signed - path: ${{ github.workspace }}/universal.apk + name: app-debug + path: app/build/outputs/apk/debug/app-debug.apk - name: Build changelog text id: changelog @@ -129,11 +66,4 @@ jobs: echo 'log<>"$GITHUB_OUTPUT" echo "$text" >>"$GITHUB_OUTPUT" echo 'EOF' >>"$GITHUB_OUTPUT" - - - name: Post to Discord - env: - DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} - run: | - artifact_url="https://nightly.link/utkarshdalal/GameNative/actions/runs/${{ github.run_id }}/app-release-signed.zip" - payload='{"content":"**New Android build**\nDownload: '"$artifact_url"'\n\nChanges:\n'"${{ steps.changelog.outputs.log }}"'"}' - curl -H 'Content-Type: application/json' -d "$payload" "$DISCORD_WEBHOOK_URL" + From 5d40d8ddada04ef0551815a6ab8a05348e8b738c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 16:24:29 +0000 Subject: [PATCH 7/7] Update Android CI workflow to use gradle.properties and rename file Renamed main_build.yml to android_ci.yml and updated the workflow name to 'Android CI'. Modified the credential injection step to append secrets to gradle.properties instead of local.properties, ensuring they are correctly loaded as project properties to resolve 'illegal start of expression' build errors. Also renamed the debug workflow in app-release-signed.yml to 'Android CI (Debug)' to avoid naming conflicts. --- .github/workflows/android_ci.yml | 46 +++++++++++++++++++++++ .github/workflows/app-release-signed.yml | 2 +- .github/workflows/main_build.yml | 48 ------------------------ 3 files changed, 47 insertions(+), 49 deletions(-) create mode 100644 .github/workflows/android_ci.yml delete mode 100644 .github/workflows/main_build.yml diff --git a/.github/workflows/android_ci.yml b/.github/workflows/android_ci.yml new file mode 100644 index 000000000..4e57bda1f --- /dev/null +++ b/.github/workflows/android_ci.yml @@ -0,0 +1,46 @@ +name: Android CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Java 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Inject credentials + run: | + cat <> gradle.properties + POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }} + POSTHOG_HOST=${{ secrets.POSTHOG_HOST }} + SUPABASE_URL=${{ secrets.SUPABASE_URL }} + SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} + EOF + + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v4 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build Release APK + run: ./gradlew assembleRelease + + - name: Upload Release APK + uses: actions/upload-artifact@v4 + with: + name: app-release + path: app/build/outputs/apk/release/app-release.apk diff --git a/.github/workflows/app-release-signed.yml b/.github/workflows/app-release-signed.yml index a647c179e..ec186af03 100644 --- a/.github/workflows/app-release-signed.yml +++ b/.github/workflows/app-release-signed.yml @@ -1,4 +1,4 @@ -name: Android CI +name: Android CI (Debug) on: push: diff --git a/.github/workflows/main_build.yml b/.github/workflows/main_build.yml deleted file mode 100644 index 9559fba7f..000000000 --- a/.github/workflows/main_build.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Build Main Branch - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - [span_0](start_span)uses: actions/checkout@v4[span_0](end_span) - - - name: Setup Java 17 - [span_1](start_span)uses: actions/setup-java@v4[span_1](end_span) - with: - java-version: '17' - [span_2](start_span)distribution: 'temurin'[span_2](end_span) - - - name: Inject credentials - run: | - cat < local.properties - POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }} - POSTHOG_HOST=${{ secrets.POSTHOG_HOST }} - SUPABASE_URL=${{ secrets.SUPABASE_URL }} - SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} - EOF - [span_3](start_span)# - - - name: Validate Gradle wrapper - uses: gradle/actions/wrapper-validation@v4[span_3](end_span) - - - name: Setup Gradle - [span_4](start_span)uses: gradle/actions/setup-gradle@v4[span_4](end_span) - - - name: Build Release APK - [span_5](start_span)run: ./gradlew assembleRelease[span_5](end_span) - - - name: Upload Release APK - [span_6](start_span)uses: actions/upload-artifact@v4[span_6](end_span) - with: - name: app-release - [span_7](start_span)path: app/build/outputs/apk/release/app-release.apk[span_7](end_span) -