# Dewemoji APK Companion Runbook

This is the single guide for APK build, release, direct distribution, and versioning.

## 1) Scope

The Android companion uses:

- local bundled UI (`dewemoji-capacitor/src` -> `dewemoji-capacitor/www`)
- native floating bubble launcher (copy/search workflow)
- direct APK update via hosted `version.json`

The bubble is not an IME and does not perform direct cross-app insertion.

## 2) Prerequisites

1. Node.js `20+`
2. JDK `17`
3. Android SDK / Android Studio
4. `adb`
5. optional signing toolchain (`apksigner`)

Install deps once:

```bash
cd /Users/dwindown/Developments/dewemoji
npm --prefix dewemoji-capacitor install
```

## 3) Source and build model

Do not edit `dewemoji-capacitor/www/*` directly.

- edit source in `dewemoji-capacitor/src/*`
- generate runtime assets via:

```bash
npm --prefix dewemoji-capacitor run build
```

## 4) Debug build and device install

```bash
cd /Users/dwindown/Developments/dewemoji
npm --prefix dewemoji-capacitor run build
cd dewemoji-capacitor
npx cap sync android
cd android
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
```

## 5) Release build

From repo root:

```bash
./scripts/apk/build-release.sh
```

Script behavior:

1. read `versionCode` and `versionName` from `android/app/build.gradle`
2. rebuild web assets
3. run `cap sync android`
4. build release APK
5. sign if signing env vars are present
6. output artifact under `dewemoji-capacitor/dist/apk/`

Output naming:

- `dewemoji-v{versionName}-{versionCode}.apk`

## 6) Signing env (optional but recommended)

```bash
export ANDROID_KEYSTORE_PATH="/absolute/path/release.jks"
export ANDROID_KEYSTORE_PASSWORD="..."
export ANDROID_KEY_ALIAS="..."
export ANDROID_KEY_PASSWORD="..."
```

## 7) Direct release to Cloudflare R2

Required env:

```bash
export R2_ACCOUNT_ID="..."
export R2_ACCESS_KEY_ID="..."
export R2_SECRET_ACCESS_KEY="..."
export R2_BUCKET="dewemoji-downloads"
export R2_PUBLIC_BASE_URL="https://downloads.dewemoji.com"
```

Canonical update URLs used by app updater:

- `https://dewemoji.com/downloads/version.json`
- `https://dewemoji.com/downloads/dewemoji-latest.apk`

Publish:

```bash
./scripts/apk/publish-r2.sh \
  --apk dewemoji-capacitor/dist/apk/dewemoji-v1.1.2-112.apk \
  --version-name 1.1.2 \
  --version-code 112 \
  --min-supported-version-code 100 \
  --notes "Bug fixes and update UX improvements" \
  --force false
```

Verify:

```bash
./scripts/apk/verify-release.sh --base-url https://dewemoji.com/downloads
```

## 8) Versioning rules

1. `versionCode` must increase on every release.
2. `versionName` is user-facing label; ordering uses `versionCode`.
3. upload APK first, then publish/update `version.json`.
4. never compare update order using `versionName`.

Expected `version.json` fields:

- `versionName` (string)
- `versionCode` (number)
- `apkUrl` (string)
- `notes` (optional)
- `force` (optional bool)

## 9) Rollback

1. keep old versioned APK objects immutable
2. repoint latest artifact (`dewemoji-latest.apk`) to known good version
3. republish matching `version.json`
4. rerun verify script

## 10) High-value troubleshooting

### `cap sync android` failures

```bash
npm --prefix dewemoji-capacitor install
cd dewemoji-capacitor
npx cap sync android
```

### Bubble not appearing

1. confirm overlay permission
2. confirm notification permission (Android 13+)
3. remove OEM battery restrictions

### APK still shows old UI

Rebuild assets, sync, and reinstall debug APK.

## 11) Key files

- `dewemoji-capacitor/src/index.html`
- `dewemoji-capacitor/src/app.css`
- `dewemoji-capacitor/src/app.js`
- `dewemoji-capacitor/android/app/build.gradle`
- `dewemoji-capacitor/android/app/src/main/java/com/dewemoji/app/MainActivity.java`
- `dewemoji-capacitor/android/app/src/main/java/com/dewemoji/app/OverlayBubbleService.java`
- `dewemoji-capacitor/android/app/src/main/java/com/dewemoji/app/plugins/DewemojiOverlayPlugin.java`
- `scripts/apk/build-release.sh`
- `scripts/apk/publish-r2.sh`
- `scripts/apk/verify-release.sh`
