From b777a6e2232bb6544c1865860dab774de5fd7556 Mon Sep 17 00:00:00 2001 From: Android PowerUser <88908510+Android-PowerUser@users.noreply.github.com> Date: Wed, 3 Jun 2026 16:14:38 +0200 Subject: [PATCH 1/2] Enable Gradle build cache and unsigned AAB build --- .github/workflows/manual.yml | 32 ++++++++++++++++++++++++++------ app/build.gradle.kts | 8 ++++---- gradle.properties | 2 +- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index e7f81564..81eb3007 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -136,6 +136,14 @@ jobs: distribution: 'temurin' cache: gradle + - name: Cache Gradle build cache + uses: actions/cache@v4 + with: + path: ~/.gradle/build-cache + key: gradle-build-cache-${{ runner.os }}-${{ hashFiles('**/*.gradle.kts', '**/gradle.properties', 'app/src/**', 'humanoperator/src/**') }} + restore-keys: | + gradle-build-cache-${{ runner.os }}- + - name: Decode google-services.json (app) env: GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON_APP }} @@ -152,8 +160,8 @@ jobs: - name: Fix gradle.properties for CI run: | sed -i '/org.gradle.java.home=/d' gradle.properties - sed -i 's/org.gradle.jvmargs=.*/org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m/' gradle.properties - sed -i 's/kotlin.daemon.jvmargs=.*/kotlin.daemon.jvmargs=-Xmx1536m -XX:MaxMetaspaceSize=512m/' gradle.properties + sed -i '/kotlin.daemon.jvmargs=/d' gradle.properties + sed -i 's/org.gradle.jvmargs=.*/org.gradle.jvmargs=-Xmx3072m -XX:MaxMetaspaceSize=512m/' gradle.properties - name: Grant execute permission for gradlew run: chmod +x gradlew @@ -178,10 +186,22 @@ jobs: with: name: humanoperator-debug path: humanoperator/build/outputs/apk/debug/humanoperator-debug.apk + + - name: Build app release AAB (unsigned) + if: env.BUILD_APP == 'true' + run: ./gradlew :app:bundleRelease + + - name: Upload app release AAB (unsigned) + if: env.BUILD_APP == 'true' + uses: actions/upload-artifact@v4 + with: + name: app-release-aab-unsigned + path: app/build/outputs/bundle/release/app-release.aab + - name: Build summary run: | echo "### Build Summary" >> $GITHUB_STEP_SUMMARY - echo "| Module | Built |" >> $GITHUB_STEP_SUMMARY - echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY - echo "| app | ${{ env.BUILD_APP }} |" >> $GITHUB_STEP_SUMMARY - echo "| humanoperator | ${{ env.BUILD_HUMANOPERATOR }} |" >> $GITHUB_STEP_SUMMARY + echo "| Module | Built | Artefakte |" >> $GITHUB_STEP_SUMMARY + echo "|--------|-------|-----------|" >> $GITHUB_STEP_SUMMARY + echo "| app | ${{ env.BUILD_APP }} | APK (debug) + AAB (release, unsigned) |" >> $GITHUB_STEP_SUMMARY + echo "| humanoperator | ${{ env.BUILD_HUMANOPERATOR }} | APK (debug) |" >> $GITHUB_STEP_SUMMARY diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5362a462..d948e837 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -27,8 +27,8 @@ val missingReleaseSigningEnv = releaseSigningEnv .filterValues { it.isNullOrBlank() } .keys -val isReleaseTaskRequested = gradle.startParameter.taskNames.any { task -> - task.contains("release", ignoreCase = true) +val isAssembleReleaseRequested = gradle.startParameter.taskNames.any { task -> + task.contains("assemble", ignoreCase = true) && task.contains("release", ignoreCase = true) } val missingReleaseSigningEnvText = missingReleaseSigningEnv.joinToString(separator = ", ") @@ -183,14 +183,14 @@ androidComponents { } tasks.configureEach { - if (name == "assemble$variantNameCap") { + if (name == "assemble$variantNameCap" || name == "bundle$variantNameCap") { dependsOn(verifyTask) } } } } -if (isReleaseTaskRequested && missingReleaseSigningEnv.isNotEmpty()) { +if (isAssembleReleaseRequested && missingReleaseSigningEnv.isNotEmpty()) { error( "Release signing env vars missing for module :app: ${missingReleaseSigningEnvText}. " + "Set ANDROID_KEYSTORE_PATH, ANDROID_KEY_ALIAS, ANDROID_KEYSTORE_PASSWORD and ANDROID_KEY_PASSWORD." diff --git a/gradle.properties b/gradle.properties index dc68f3c8..c28aa2a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,7 +15,7 @@ org.gradle.java.home=/root/.local/share/mise/installs/java/17.0.2 org.gradle.parallel=false # Enable Gradle build cache -org.gradle.caching=false +org.gradle.caching=true # Enable configuration on demand org.gradle.configureondemand=true From 4855435de5e48d86b6ae519839e1e88804ad396b Mon Sep 17 00:00:00 2001 From: Android PowerUser <88908510+Android-PowerUser@users.noreply.github.com> Date: Sun, 7 Jun 2026 14:28:17 +0200 Subject: [PATCH 2/2] Update default system message on first start --- .../com/google/ai/sample/util/SystemMessagePreferences.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/google/ai/sample/util/SystemMessagePreferences.kt b/app/src/main/kotlin/com/google/ai/sample/util/SystemMessagePreferences.kt index 7410da83..4ad868c6 100644 --- a/app/src/main/kotlin/com/google/ai/sample/util/SystemMessagePreferences.kt +++ b/app/src/main/kotlin/com/google/ai/sample/util/SystemMessagePreferences.kt @@ -14,7 +14,7 @@ object SystemMessagePreferences { private const val KEY_FIRST_START_COMPLETED = "first_start_completed" // New flag // Content from pasted_content.txt - private const val DEFAULT_SYSTEM_MESSAGE_ON_FIRST_START = """You are on an App on a Smartphone. Your app is called Screen Operator. You start from this app. Proceed step by step! DON'T USE TOOL CODE! You must operate the screen with exactly following commands: "home()" "back()" "recentApps()" "openApp("sample")" for buttons and words: "click("sample")" "longClick("sample")" "tapAtCoordinates(x, y)" "tapAtCoordinates(x percent of screen%, y percent of screen%)" "scrollDown()" "scrollUp()" "scrollLeft()" "scrollRight()" "scrollDown(x, y, how much pixel to scroll, duration in milliseconds)" "scrollUp(x, y, how much pixel to scroll, duration in milliseconds)" "scrollLeft(x, y, how much pixel to scroll, duration in milliseconds)" "scrollRight(x, y, how much pixel to scroll, duration in milliseconds)" "scrollDown(x percent of screen%, y percent of screen%, how much percent to scroll%, duration in milliseconds)" "scrollUp(x percent of screen%, y percent of screen%, how much percent to scroll, duration in milliseconds)" "scrollLeft(x percent of screen%, y percent of screen%, how much percent to scroll, duration in milliseconds)" "scrollRight(x percent of screen%, y percent of screen%, how much percent to scroll, duration in milliseconds)" scroll status bar down: "scrollUp(540, 0, 1100, 50)" "takeScreenshot()" "Termux("command")" To write text, search and click the textfield thereafter: "writeText("sample text")" You need to write the already existing text, if it should continue exist. If the keyboard is displayed, you can press "Enter()". Otherwise, you have to open the keyboard by clicking on the text field. Don't write the commands if you're just planing about it or messaging me. If you have questions, open Screen Operator, ask your question(s), and do not use takeScreenshot() until you receive an answer. Retrieve information using "retrieve("sample")" if some is passed to your task. You can see the screen and get additional Informations about them with: "takeScreenshot()" You need this command at the end of every message until you are finish. When you're done don't say "takeScreenshot()"""" + private const val DEFAULT_SYSTEM_MESSAGE_ON_FIRST_START = """You are on an App on a Smartphone. Your app is called Screen Operator. You start from this app. Proceed step by step! DON'T USE TOOL CODE! You must operate the screen with exactly following commands: "home()" "back()" "recentApps()" "openApp("sample")" for buttons and words: "click("sample")" "longClick("sample")" "tapAtCoordinates(x, y)" "tapAtCoordinates(x percent of screen%, y percent of screen%)" "scrollDown()" "scrollUp()" "scrollLeft()" "scrollRight()" "scrollDown(x, y, how much pixel to scroll, duration in milliseconds)" "scrollUp(x, y, how much pixel to scroll, duration in milliseconds)" "scrollLeft(x, y, how much pixel to scroll, duration in milliseconds)" "scrollRight(x, y, how much pixel to scroll, duration in milliseconds)" "scrollDown(x percent of screen%, y percent of screen%, how much percent to scroll%, duration in milliseconds)" "scrollUp(x percent of screen%, y percent of screen%, how much percent to scroll, duration in milliseconds)" "scrollLeft(x percent of screen%, y percent of screen%, how much percent to scroll, duration in milliseconds)" "scrollRight(x percent of screen%, y percent of screen%, how much percent to scroll, duration in milliseconds)" scroll status bar down: "scrollUp(540, 0, 1100, 50)" "Wait(seconds)" "Termux("command")" "takeScreenshot()" To write text, search and click the textfield thereafter: "writeText("sample text")" You need to write the already existing text, if it should continue exist. If the keyboard is displayed, you can press "Enter()". Otherwise, you have to open the keyboard by clicking on the text field. Don't write the commands if you're just planing about it or messaging me. If you have questions, open Screen Operator, ask your question(s), and do not use takeScreenshot() until you receive an answer. Retrieve information using "retrieve("sample")" if some is passed to your task. You can see the screen and get additional Informations about them with: "takeScreenshot()" You need this command at the end of every message until you are finish. When you're done don't say "takeScreenshot()"""" private fun prefs(context: Context) = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) /**