🏗️ Build and Test JellyTau / Run Tests (push) Successful in 29m49s
🏗️ Build and Test JellyTau / Supply Chain (push) Successful in 57s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 9m25s
Traceability Validation / Check Requirement Traces (push) Successful in 17s
🏗️ Build and Test JellyTau / Android Compile Check (push) Failing after 51s
Gitea artifacts need an account with read access to download, which makes them useless for handing a build to someone outside the project -- the actual reason a test APK gets built in the first place. An optional publish input attaches the APK to a pre-release instead, whose assets are a plain public URL on a public repo. No merge to master, no MR, no version tag, and the tester needs no account. Safe from a feature branch on two counts. The tag is test-<branch> rather than v*, and only v* triggers build-release.yml, so nothing else reacts to it. And it cannot reach existing users: the desktop updater reads a static latest.json from the updater branch, not the release list. Re-dispatching the same branch replaces the APK on the existing pre-release rather than accumulating one release per attempt.
140 lines
6.4 KiB
Markdown
140 lines
6.4 KiB
Markdown
# ⚠️ 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)**
|
|
```bash
|
|
./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)**
|
|
```bash
|
|
./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:
|
|
|
|
| build | applicationId | launcher name | versionName | signed with |
|
|
|---|---|---|---|---|
|
|
| `release` | `com.dtourolle.jellytau` | jellytau | `0.5.5` | real key (`.env`) |
|
|
| `release --debug` | `com.dtourolle.jellytau.debug` | JellyTau Debug | `0.5.5-debug-release` | debug keystore |
|
|
| `debug` | `com.dtourolle.jellytau.debug` | JellyTau Debug | `0.5.5-debug` | debug keystore |
|
|
|
|
`release --debug` is the **side-by-side release**: fully R8-minified, exactly
|
|
what ships, but packaged into the debug slot and signed with the local debug
|
|
keystore. It exists because R8 has broken release APKs here before (stripping
|
|
JNI-loaded player/security classes), and reproducing that previously meant
|
|
building with the real key and clobbering your working install. It shares the
|
|
applicationId *and* signature with the plain debug build, so the two replace
|
|
each other cleanly; only the versionName suffix tells you which is installed.
|
|
|
|
```bash
|
|
./scripts/build-and-deploy.sh release --device --debug # build + install it
|
|
```
|
|
|
|
The flag is plumbed through as `JT_SIDE_BY_SIDE=1`, read by `build.gradle.kts`.
|
|
CI never sets it, so distributable release builds are untouched.
|
|
|
|
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. This is not optional and cannot be shared:
|
|
Android gives each applicationId its own UID and enforces the boundary in the
|
|
kernel. (`sharedUserId` is deprecated since API 29 and cannot be added to an
|
|
already-installed app anyway.) You log in again in the debug app, once.
|
|
- 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).
|
|
|
|
### Getting a test APK out of CI
|
|
|
|
`.gitea/workflows/build-test-apk.yml` builds one from **any branch, on demand**
|
|
— run it from Gitea's Actions tab (`workflow_dispatch`) against the ref you want.
|
|
It is not a release: nothing is tagged, published, or signed with the real key.
|
|
|
|
Two variants, both installing into the `com.dtourolle.jellytau.debug` slot:
|
|
|
|
| Variant | What it is | When |
|
|
|---------|-----------|------|
|
|
| `side-by-side-release` (default) | R8-minified, exactly what ships, signed with the debug keystore | Almost always — a plain debug build cannot catch R8 stripping JNI-loaded classes, which has broken release APKs here before |
|
|
| `debug` | Unminified | When you need readable stack traces |
|
|
|
|
There is deliberately **no push trigger**: the runner has one slot shared with
|
|
two other projects, so building on every feature-branch commit would starve
|
|
them. The APK lands as the `jellytau-test-apk` artifact (7-day retention), named
|
|
for the branch and short SHA, with its size and SHA256 in the run summary.
|
|
|
|
#### Sending a build to an outside tester
|
|
|
|
Gitea **artifacts require an account** with read access to download, so an
|
|
artifact is no use to someone outside the project. Tick **`publish`** on the
|
|
dispatch and the APK is also attached to a **pre-release**, whose assets are a
|
|
plain public URL on a public repo — no account, no MR, no merge to `master`.
|
|
|
|
Two things make that safe to do from a feature branch:
|
|
|
|
- The tag is `test-<branch>`, **not** `v*`. Only `v*` triggers
|
|
`build-release.yml`, so nothing else reacts to it.
|
|
- It cannot reach existing users. The desktop updater reads a static
|
|
`latest.json` from the `updater` branch, not the release list, so a
|
|
pre-release published this way is invisible to anyone without the link.
|
|
|
|
Re-dispatching for the same branch replaces the APK on the existing
|
|
pre-release rather than piling up one release per attempt. Delete the release
|
|
when testing is over.
|
|
|
|
### 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!
|