Files
jellytau/src-tauri/android/README_ANDROID_BUILD.md
T
dtourolle 2cc39cd7fd build(android): install the debug build alongside release as its own app
Testing a debug build meant uninstalling the real one first: same
applicationId signed with a different key is INSTALL_FAILED_UPDATE_
INCOMPATIBLE, so every experiment cost the app's settings, credentials
and offline cache.

The debug build type now carries applicationIdSuffix ".debug" and
versionNameSuffix "-debug", so it installs as com.dtourolle.jellytau.debug
("JellyTau Debug", 0.5.5-debug) with its own data directory — two
independent apps on one device.

Only the *application* id is suffixed. Kotlin classes stay in the
`namespace` package com.dtourolle.jellytau, so the JNI loadClass lookups
in player/android/mod.rs, the manifest <service> entry and the R8 keep
rules are untouched, and the FileProvider authority was already
${applicationId}-relative. Launcher names come from the appLabel /
activityLabel manifestPlaceholders rather than resValue, which would
collide with Tauri's generated strings.xml; release resolves them back to
@string/app_name and merges byte-identical.

deploy-android.sh reports the target package and explains an
UPDATE_INCOMPATIBLE failure instead of leaving it raw; logcat.sh takes a
debug|release argument (it was filtering on com.jellytau.app, a package
that has never existed) and attaches by pid when the app is running.

Verified: aapt2 badging on the built APK reports
com.dtourolle.jellytau.debug / 0.5.5-debug / "JellyTau Debug", and the
release manifest merge is unchanged.
2026-08-16 10:36:48 +02:00

3.3 KiB

⚠️ IMPORTANT: Android Build File Locations

Critical Information for Future Development

DO NOT EDIT FILES IN src-tauri/gen/android/ DIRECTLY!

File Structure

This project has TWO sets of Android source files:

  1. src-tauri/android/ - SOURCE FILES (edit these!)

    • This is the template directory
    • Changes here need to be copied to the generated directory
  2. src-tauri/gen/android/ - GENERATED BUILD DIRECTORY (do not edit directly!)

    • This is where Gradle actually builds the APK
    • Files here may be overwritten during builds

How to Make Changes to Android Code

When you need to modify Android/Kotlin files:

  1. Edit the files in src-tauri/android/src/main/java/

  2. Build using the provided script (which auto-syncs files)

    ./scripts/build-android.sh
    

    The build script automatically runs ./scripts/sync-android-sources.sh which copies:

    • src-tauri/android/src/main/java/com/dtourolle/jellytau/player/ → generated directory
    • src-tauri/android/src/main/java/com/dtourolle/jellytau/security/ → generated directory
  3. Manual sync (if needed)

    ./scripts/sync-android-sources.sh
    

Why This Matters

  • If you only edit src-tauri/gen/android/, your changes will be lost
  • If you only edit src-tauri/android/, your changes won't be in the build
  • You must edit both (or edit source and copy to generated)

Debug and release install side by side

The debug build type sets applicationIdSuffix = ".debug" in app/build.gradle.kts, so a debug build is a genuinely separate Android app:

applicationId launcher name versionName
release com.dtourolle.jellytau jellytau 0.5.5
debug com.dtourolle.jellytau.debug JellyTau Debug 0.5.5-debug

That means:

  • No uninstall step. Debug builds are signed with the local auto-generated ~/.android/debug.keystore, release builds with the real key. Two different keys on the same package is INSTALL_FAILED_UPDATE_INCOMPATIBLE; two different packages is just two apps.
  • Each has its own data directory — separate settings, credentials, downloads and offline cache. A debug experiment cannot corrupt the state of the build you actually use.
  • Only the application id changes. Kotlin classes stay in the namespace package com.dtourolle.jellytau, so the JNI class lookups in src-tauri/src/player/android/mod.rs, the manifest <service> entry and the R8 keep rules in proguard-jellytau.pro are all unaffected. The FileProvider authority is ${applicationId}.fileprovider, so it follows the suffix automatically.
  • The launcher labels come from the appLabel / activityLabel manifestPlaceholders (AndroidManifest.xml uses ${appLabel}), not from resValue, which would collide with Tauri's generated strings.xml.

Follow the right log stream with ./scripts/logcat.sh [debug|release] (defaults to debug).

Key Files

Player-related Kotlin files:

  • player/JellyTauPlayer.kt - Main player implementation
  • player/JellyTauPlaybackService.kt - MediaSession service for lockscreen controls
  • security/SecureStorage.kt - Android Keystore integration for secure credential storage

Always check BOTH locations exist and match after making changes!