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)
-