# Release Signing — Read this BEFORE rebuilding the APK

## What this fixes

If your users are seeing **"App not installed as package conflicts with an existing package"** when they tap *Update* in the in-app popup, it's because **each APK you've built so far has been signed with a different key** (Gradle's auto-debug key, which is regenerated per machine / per run). Android's package manager refuses to update an installed app over an APK with a different signature — that's a security feature, not a bug.

The cure is simple: **sign every release with the same keystore, every time.**

## One-time setup (do this ONCE, then never again)

```bash
# from the repo root
./scripts/generate-release-keystore.sh
```

The script:
1. Creates `frontend/android/release-keystore.jks` (RSA 2048, valid 100 years).
2. Creates `frontend/android/keystore.properties` with the alias + passwords.
3. `chmod 600` on both files.

Both files are **gitignored** (see `frontend/android/.gitignore` — added below).

## ⚠️ Back up the keystore IMMEDIATELY

Copy `release-keystore.jks` and `keystore.properties` to:
- A cloud drive (Google Drive, Dropbox, OneDrive)
- A USB stick stored offline
- A password manager (1Password / Bitwarden) as encrypted attachments

**If you lose them, nobody can update from any version you've already published.** They will all hit the same "package conflicts" error you saw on screen, forever, until they uninstall manually.

## Every release after that

```bash
./scripts/bump-version.sh 1.0.3            # bumps versionName + versionCode
cd frontend && yarn cap:sync               # copy web → android
cd android && ./gradlew assembleRelease    # build SIGNED APK
```

The signed APK appears at:

```
frontend/android/app/build/outputs/apk/release/app-release.apk
```

Upload it to your server, set **Latest version** = `1.0.3` in the admin panel, save. Users on `1.0.2` will install over the top — no uninstall needed.

## ⚠️ The CURRENT 1.0.2 update will still fail

Your users have v1.0.1 installed, which was signed with the (random) auto-debug key from your previous build. v1.0.2 will be signed with your new persistent keystore — different signature → Android still refuses.

**You only have to fix this once.** Two options:

### Option A — ask users to uninstall (one-time pain)
1. Build & publish v1.0.2 normally.
2. Tell users (e.g. via the changelog field in the admin update popup): *"This update requires uninstalling first — sorry, last time. Future updates will be one-tap."*

### Option B — keep current installs functional, force the move on a future release
1. Skip publishing v1.0.2.
2. Build v1.0.3 with the new keystore.
3. Whenever you choose to push it, the same one-time uninstall pain applies — just delayed.

There's no way around the "uninstall once" because the old APK was signed with a key you don't have anymore. After this single break, every future update is seamless.

## How to verify your APK is correctly signed

```bash
$ANDROID_HOME/build-tools/<latest>/apksigner verify --print-certs \
  frontend/android/app/build/outputs/apk/release/app-release.apk
```

You should see your `CN=Nadiplayer, OU=Mobile, ...` certificate. If you see something like `CN=Android Debug` — the keystore wasn't picked up; check that `keystore.properties` exists in `frontend/android/`.

## CI / GitHub Actions

If you ever automate this, set these env vars:

```bash
STORE_PASS=...
KEY_PASS=...
ALIAS=nadiplayer
./scripts/generate-release-keystore.sh
```

The script is non-interactive when those vars are set. Then commit only the gitignored hash of the keystore (or, more practically, store the keystore as a base64-encoded GitHub Actions secret and decode at build time).
