# ePhone — Android build guide (core calling)

This builds the field-engineer app: register to `go.mindserv.co`, dialpad,
outbound (auto `80`-prefix + `X-CLI`), incoming-call screen, two-way audio,
Mute/Speaker/Hold/Hang-up. No CallKeep/push yet (added in the next phase).

Everything the browser test proved is baked into `src/`. You just wrap it in a
React Native Android shell.

---

## 1. Install the toolchain (one-time)

VS Code alone can't build Android. Install:

1. **Node.js LTS** (18 or 20) — https://nodejs.org
2. **JDK 17** (Temurin/Adoptium) — https://adoptium.net  → verify `java -version` shows 17
3. **Android Studio** — https://developer.android.com/studio
   In Android Studio → *SDK Manager*, install:
   - **Android SDK Platform 34**
   - **Android SDK Build-Tools 34**
   - **Android SDK Platform-Tools**
   - **Android Emulator** + one **AVD** (e.g. Pixel 6, API 34) — or use a real phone.

4. **Environment variables** (Windows — System Properties → Environment Variables):
   - `ANDROID_HOME = C:\Users\<you>\AppData\Local\Android\Sdk`
   - Add to `Path`:
     - `%ANDROID_HOME%\platform-tools`
     - `%ANDROID_HOME%\emulator`
   - `JAVA_HOME = C:\Program Files\Eclipse Adoptium\jdk-17...`

   Restart the terminal, then verify: `adb --version` and `java -version` both work.

> Physical phone is easiest: enable **Developer options → USB debugging**, plug in
> USB, accept the prompt, confirm `adb devices` lists it.

---

## 2. Create the React Native project shell

In a folder where you keep code (NOT inside the ePhone repo):

```bash
npx @react-native-community/cli@latest init ePhoneApp
cd ePhoneApp
```
This generates the `android/` Gradle project. Confirm the stock app runs first:
```bash
npx react-native run-android
```
You should see the default RN welcome screen on your device/emulator. **Get this
green before adding our code** — it proves your toolchain works.

---

## 3. Drop in the ePhone source

Copy from `ePhone/mobile/` into the new `ePhoneApp/`:

- Copy the whole **`src/`** folder → `ePhoneApp/src/`
- Overwrite **`index.js`** with `ePhone/mobile/index.js`

(`App.tsx` from the RN template at the project root is now unused — our entry is
`src/App.tsx`, referenced by `index.js`.)

---

## 4. Install dependencies

```bash
npm i jssip react-native-webrtc react-native-incall-manager \
      @react-native-async-storage/async-storage events
```

- `events` — jssip/our SipEngine import Node's `EventEmitter`; this npm package
  provides it in React Native (without it the bundler errors "Unable to resolve
  module events").

React Native 0.71+ autolinks these native modules — no manual linking needed.

---

## 5. Android native config

### a) Minimum SDK — react-native-webrtc needs API 24+
Edit `android/build.gradle`, in `buildscript { ext { … } }`:
```gradle
minSdkVersion = 24
```

### b) Permissions — edit `android/app/src/main/AndroidManifest.xml`
Add these inside `<manifest>` (above `<application>`):
```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
```

### c) (If build complains about missing camera) react-native-webrtc pulls camera
APIs even for audio-only. If Gradle errors on camera, that's fine at runtime —
we never request the camera. No action usually needed.

---

## 6. Run it

Start your emulator (or plug in the phone), then:
```bash
npx react-native run-android
```

If Metro isn't already running:
```bash
npx react-native start
```

---

## 7. First-run test (mirrors the browser flow)

1. App opens on the **Login** screen — server fields prefilled to `go.mindserv.co`.
2. Enter a **distinct agent** — e.g. `agent2` / `agent2pass` (don't reuse `agent1`;
   keep that for the browser). → **Sign In**.
3. Dialpad shows **● Online · Ext agent2**.
4. **Outbound:** type a 10-digit mobile (e.g. `9818222951`) → green call button.
   The app auto-formats to `809818222951` and sends `X-CLI`. Phone rings, answer,
   confirm two-way audio.
5. **Inbound:** point a DID at `agent2` in `[trunk-in]`
   (`exten => <DID>,1,Dial(PJSIP/agent2,45,rtT)` + `dialplan reload`), call the DID
   → the app shows the incoming-call screen.

---

## Troubleshooting

- **"Unable to resolve module events"** → you missed `npm i events` (step 4).
- **Registers in browser but not app** → check the phone has internet and the
  clock is correct (TLS). Watch `adb logcat | grep -i jssip` and, server-side,
  `sudo asterisk -rx "pjsip set logger on"`.
- **No audio / one-way** → confirm `RECORD_AUDIO` was granted (Android will prompt
  on first launch); check `MODIFY_AUDIO_SETTINGS` is present. On native,
  react-native-webrtc auto-plays remote audio — InCallManager handles routing.
- **App crashes on launch citing WebRTC** → `minSdkVersion` still < 24 (step 5a).
- **Build too slow / OOM** → in `android/gradle.properties` set
  `org.gradle.jvmargs=-Xmx2048m`.

Once core calling works on Android, the next phase adds `react-native-callkeep`
(native lock-screen call UI) and FCM VoIP push (wake when backgrounded) — the
`CallManager.ts` / `PushService.ts` files are already written for that step.
