Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8eb030a
Add reusable Android client and Godot service hello world
linuxificator Aug 23, 2026
a9fdc55
Enable Android texture compression for Godot export
linuxificator Aug 23, 2026
98f0fc8
Print Android smoke-test logs before assertions
linuxificator Aug 23, 2026
65cc8b2
Keep Android hello-world client alive across Activity recreation
linuxificator Aug 23, 2026
115006b
Document reusable Android AmyClient in hello world
linuxificator Aug 23, 2026
42d3841
Document reusable client and framework-isolated Android design
linuxificator Aug 23, 2026
e62a9cd
Fix Godot Android AAR packaging and ABI-specific exports
linuxificator Aug 23, 2026
c29d2b0
Run Android template install together with Godot export
linuxificator Aug 23, 2026
5a1146c
Preserve Godot Android smoke diagnostics
linuxificator Aug 23, 2026
2ba6ca8
Fix Godot Android service bridge and diagnostics
linuxificator Aug 23, 2026
97fee7a
Auto-start AMY service with application
linuxificator Aug 23, 2026
9ef1139
Auto-start AMY service with application
linuxificator Aug 23, 2026
97b6116
Keep AMY lifecycle inside service process
linuxificator Aug 23, 2026
adb912b
Reduce Android client to socket transport only
linuxificator Aug 23, 2026
bd61d8d
Remove redundant Godot Android bridge
linuxificator Aug 23, 2026
5472072
Make Godot Android backend socket-only
linuxificator Aug 23, 2026
571f9c1
Use auto-started AMY service in Android example
linuxificator Aug 23, 2026
eadbadf
Test automatic AMY service startup
linuxificator Aug 23, 2026
ecc9895
Test Godot as socket-only AMY client
linuxificator Aug 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ jobs:
script: |
adb uninstall org.amy.hello >/dev/null 2>&1 || true
adb install android/hello-world/build/outputs/apk/debug/hello-world-debug.apk
adb shell run-as org.amy.hello mkdir -p files
adb shell run-as org.amy.hello touch files/amy-audio-capture.enable
adb logcat -c
adb shell am start -W -n org.amy.hello/.MainActivity
sleep 10
adb logcat -d -s AmyAndroid:I AmyAudioCapture:I AmyService:I AmyHelloWorld:I '*:S' > /tmp/amy-first.log
adb logcat -d -s AmyAndroid:I AmyAudioCapture:I AmyAutoStart:I AmyService:I AmyHelloWorld:I '*:S' > /tmp/amy-first.log
cat /tmp/amy-first.log
grep -q 'AMY service auto-start requested' /tmp/amy-first.log
test "$(grep -c 'AMY/Oboe started' /tmp/amy-first.log)" -eq 1
grep -q 'AMY output route: deviceId=' /tmp/amy-first.log
test "$(grep -c 'C scale complete' /tmp/amy-first.log)" -eq 1
Expand All @@ -98,10 +102,14 @@ jobs:

adb uninstall org.amy.hello
adb install android/hello-world/build/outputs/apk/debug/hello-world-debug.apk
adb shell run-as org.amy.hello mkdir -p files
adb shell run-as org.amy.hello touch files/amy-audio-capture.enable
adb logcat -c
adb shell am start -W -n org.amy.hello/.MainActivity
sleep 10
adb logcat -d -s AmyAndroid:I AmyAudioCapture:I AmyService:I AmyHelloWorld:I '*:S' > /tmp/amy-second.log
adb logcat -d -s AmyAndroid:I AmyAudioCapture:I AmyAutoStart:I AmyService:I AmyHelloWorld:I '*:S' > /tmp/amy-second.log
cat /tmp/amy-second.log
grep -q 'AMY service auto-start requested' /tmp/amy-second.log
test "$(grep -c 'AMY/Oboe started' /tmp/amy-second.log)" -eq 1
grep -q 'AMY output route: deviceId=' /tmp/amy-second.log
test "$(grep -c 'C scale complete' /tmp/amy-second.log)" -eq 1
Expand Down
205 changes: 205 additions & 0 deletions .github/workflows/godot-android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
name: Godot Android AMY

on:
pull_request:
paths:
- "android/**"
- "godot/**"
- "src/amy_unix_socket.c"
- "src/amy_unix_socket.h"
- ".github/workflows/godot-android.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
godot-android:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v5

- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "17"

- uses: android-actions/setup-android@v3

- name: Install Android SDK components
run: |
yes | sdkmanager --licenses >/dev/null
sdkmanager \
"platforms;android-36" \
"build-tools;35.0.1" \
"ndk;27.0.12077973" \
"cmake;3.22.1"

- name: Enable KVM access when available
run: |
if [ -e /dev/kvm ]; then
sudo chmod 666 /dev/kvm
ls -l /dev/kvm
else
echo "No /dev/kvm on this runner; emulator will use software acceleration"
fi

- uses: gradle/actions/setup-gradle@v4
with:
gradle-version: "8.13"

- name: Build AMY AAR and prepare Godot addon
run: bash godot/android-hello-world/prepare.sh

- name: Inspect prepared AAR
run: |
AAR=godot/android-hello-world/addons/amy_android/amy-service-debug.aar
test -s "$AAR"
unzip -l "$AAR" | tee /tmp/amy-aar-contents.txt
grep -q 'jni/arm64-v8a/libamy_android.so' /tmp/amy-aar-contents.txt
grep -q 'jni/arm64-v8a/libamy_android_client.so' /tmp/amy-aar-contents.txt
grep -q 'jni/x86_64/libamy_android.so' /tmp/amy-aar-contents.txt
grep -q 'jni/x86_64/libamy_android_client.so' /tmp/amy-aar-contents.txt
unzip -p "$AAR" classes.jar > /tmp/amy-classes.jar
unzip -l /tmp/amy-classes.jar | tee /tmp/amy-classes.txt
grep -q 'org/amy/audio/AmyService.class' /tmp/amy-classes.txt
grep -q 'org/amy/audio/AmyClient.class' /tmp/amy-classes.txt
grep -q 'org/amy/audio/AmyAutoStartProvider.class' /tmp/amy-classes.txt
! grep -q 'AmyAndroidBridge.class' /tmp/amy-classes.txt

- name: Install Godot 4.7.2 and export templates
run: |
curl -L --fail --retry 3 \
-o /tmp/godot.zip \
https://github.com/godotengine/godot/releases/download/4.7.2-stable/Godot_v4.7.2-stable_linux.x86_64.zip
unzip -q /tmp/godot.zip -d /tmp/godot
GODOT_BIN="$(find /tmp/godot -maxdepth 1 -type f -name 'Godot*' | head -n1)"
chmod +x "$GODOT_BIN"
sudo cp "$GODOT_BIN" /usr/local/bin/godot

curl -L --fail --retry 3 \
-o /tmp/godot-templates.tpz \
https://github.com/godotengine/godot/releases/download/4.7.2-stable/Godot_v4.7.2-stable_export_templates.tpz
rm -rf /tmp/godot-templates
mkdir -p /tmp/godot-templates
unzip -q /tmp/godot-templates.tpz -d /tmp/godot-templates
mkdir -p "$HOME/.local/share/godot/export_templates/4.7.2.stable"
cp -a /tmp/godot-templates/templates/. \
"$HOME/.local/share/godot/export_templates/4.7.2.stable/"
godot --version

- name: Import Godot project
run: godot --headless --path godot/android-hello-world --import --quit

- name: Export ARM64 phone APK
run: |
mkdir -p godot/android-hello-world/build
godot --headless \
--path godot/android-hello-world \
--install-android-build-template \
--export-debug "Android ARM64" build/godot-amy-hello-arm64.apk
test -s godot/android-hello-world/build/godot-amy-hello-arm64.apk

- name: Export x86_64 CI APK
run: |
godot --headless \
--path godot/android-hello-world \
--export-debug "Android CI x86_64" build/godot-amy-hello-x86_64.apk
test -s godot/android-hello-world/build/godot-amy-hello-x86_64.apk

- name: Verify APK architecture and AMY packaging
run: |
ARM=godot/android-hello-world/build/godot-amy-hello-arm64.apk
X86=godot/android-hello-world/build/godot-amy-hello-x86_64.apk

unzip -l "$ARM" | tee /tmp/amy-arm-apk.txt
grep -q 'lib/arm64-v8a/libgodot_android.so' /tmp/amy-arm-apk.txt
grep -q 'lib/arm64-v8a/libamy_android.so' /tmp/amy-arm-apk.txt
grep -q 'lib/arm64-v8a/libamy_android_client.so' /tmp/amy-arm-apk.txt
! grep -q 'lib/x86_64/' /tmp/amy-arm-apk.txt

unzip -p "$ARM" classes.dex | strings > /tmp/amy-arm-dex.txt
grep -q 'Lorg/amy/audio/AmyService;' /tmp/amy-arm-dex.txt
grep -q 'Lorg/amy/audio/AmyClient;' /tmp/amy-arm-dex.txt
grep -q 'Lorg/amy/audio/AmyAutoStartProvider;' /tmp/amy-arm-dex.txt
! grep -q 'Lorg/amy/audio/AmyAndroidBridge;' /tmp/amy-arm-dex.txt

unzip -l "$X86" | tee /tmp/amy-x86-apk.txt
grep -q 'lib/x86_64/libgodot_android.so' /tmp/amy-x86-apk.txt
grep -q 'lib/x86_64/libamy_android.so' /tmp/amy-x86-apk.txt
grep -q 'lib/x86_64/libamy_android_client.so' /tmp/amy-x86-apk.txt
! grep -q 'lib/arm64-v8a/' /tmp/amy-x86-apk.txt

unzip -p "$X86" classes.dex | strings > /tmp/amy-x86-dex.txt
grep -q 'Lorg/amy/audio/AmyService;' /tmp/amy-x86-dex.txt
grep -q 'Lorg/amy/audio/AmyClient;' /tmp/amy-x86-dex.txt
grep -q 'Lorg/amy/audio/AmyAutoStartProvider;' /tmp/amy-x86-dex.txt
! grep -q 'Lorg/amy/audio/AmyAndroidBridge;' /tmp/amy-x86-dex.txt

ARM_SIZE=$(stat -c%s "$ARM")
X86_SIZE=$(stat -c%s "$X86")
echo "ARM64 APK bytes: $ARM_SIZE"
echo "x86_64 APK bytes: $X86_SIZE"
test "$ARM_SIZE" -lt 110000000
test "$X86_SIZE" -lt 120000000

- name: Upload ARM64 phone-test APK
uses: actions/upload-artifact@v4
with:
name: amy-godot-android-hello-world-arm64-apk
path: godot/android-hello-world/build/godot-amy-hello-arm64.apk
if-no-files-found: error

- name: Emulator Godot-to-AMY smoke test
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 35
arch: x86_64
profile: pixel_2
disable-animations: true
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -no-boot-anim
script: |
adb uninstall org.amy.godothello >/dev/null 2>&1 || true
adb install godot/android-hello-world/build/godot-amy-hello-x86_64.apk
adb logcat -c
adb shell monkey -p org.amy.godothello 1 >/dev/null
sleep 15
echo '===== PROCESS LIST =====' > /tmp/amy-godot-diagnostics.txt
adb shell ps -A >> /tmp/amy-godot-diagnostics.txt 2>&1 || true
echo '===== SERVICES =====' >> /tmp/amy-godot-diagnostics.txt
adb shell dumpsys activity services org.amy.godothello >> /tmp/amy-godot-diagnostics.txt 2>&1 || true
echo '===== APP FILES =====' >> /tmp/amy-godot-diagnostics.txt
adb shell run-as org.amy.godothello ls -la files >> /tmp/amy-godot-diagnostics.txt 2>&1 || true
adb shell run-as org.amy.godothello ls -la files/amy.sock >> /tmp/amy-godot-diagnostics.txt 2>&1 || true
adb logcat -d > /tmp/amy-godot.log
echo '===== LOGCAT =====' >> /tmp/amy-godot-diagnostics.txt
cat /tmp/amy-godot.log >> /tmp/amy-godot-diagnostics.txt
cat /tmp/amy-godot-diagnostics.txt

- name: Upload Godot Android smoke diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: amy-godot-android-smoke-diagnostics
path: |
/tmp/amy-godot.log
/tmp/amy-godot-diagnostics.txt
if-no-files-found: warn

- name: Assert Godot-to-AMY smoke result
run: |
cat /tmp/amy-godot.log
grep -q 'AMY service auto-start requested' /tmp/amy-godot.log
grep -q 'AMY native library loaded in service process' /tmp/amy-godot.log
grep -q 'AMY/Oboe started' /tmp/amy-godot.log
grep -q 'AMY Android service ready' /tmp/amy-godot.log
grep -q 'Godot AMY ready' /tmp/amy-godot.log
grep -q 'Godot wire: v0w0V10' /tmp/amy-godot.log
test "$(grep -Ec 'Godot wire: v0n(60|62|64|65|67|69|71|72)l1' /tmp/amy-godot.log)" -eq 8
grep -q 'Godot wire: v0n60l1' /tmp/amy-godot.log
grep -q 'Godot wire: v0n72l1' /tmp/amy-godot.log
grep -q 'Godot C scale complete' /tmp/amy-godot.log
grep -q 'org.amy.godothello:amy' /tmp/amy-godot-diagnostics.txt
grep -q 'amy.sock' /tmp/amy-godot-diagnostics.txt
! grep -q 'Godot AMY error:' /tmp/amy-godot.log
Loading
Loading