Skip to content

Latest commit

 

History

History
421 lines (356 loc) · 15.7 KB

File metadata and controls

421 lines (356 loc) · 15.7 KB
title App Setup
icon mobile
description Set up the Omi Flutter app for development. Build automatically against the local backend harness, or manually with your own.

Overview

There are two ways to set up the Omi app for development:

**Recommended for most developers**
One command setup against the local backend harness
**For custom backends**
Full control over configuration and backend
Don't want to build from source? Download the official app from the [App Store](https://apps.apple.com/us/app/friend-ai-wearable/id6502156163) or [Google Play](https://play.google.com/store/apps/details?id=com.friend.ios).

Prerequisites

Before starting, make sure you have the following installed:

Includes Dart - the core framework Required for iOS development Required for Android development iOS dependency manager You'll also need [NDK](https://developer.android.com/ndk/downloads) to build Opus for ARM devices. The local backend harness additionally needs **Python 3.11** (not 3.12+ — the backend pins 3.11), a **Java runtime** for the Firestore emulator, and **firebase-tools** (or `npx`). `make dev-up` names any of these that are missing.

Build the App Automatically

This is the recommended way to get started. setup.sh builds the dev flavor against the local backend harness — the Python API on port 8000 and the Firebase Auth emulator on port 9099, using the demo-omi-local Firebase project. iOS builds address them as 127.0.0.1; Android builds default to the emulator's host alias 10.0.2.2.

`setup.sh` does **not** start the backend or the emulator — start the harness first (step 1 below), or the app builds and launches but every request fails to connect.

Do not point this build at https://api.omiapi.com/. That API verifies Firebase ID tokens against Omi's production Firebase project, and Firebase tokens are project-scoped, so a demo-omi-local token is rejected with 401 Unauthorized on every call — sign-in appears to succeed and nothing else works. Production data requires the explicit beta profile (see Mobile beta).

Video Walkthrough

<iframe width="560" height="315" src="https://www.youtube.com/embed/U6L8S1SaUls?si=etmPgly-7dhyXmG_" title="Omi App Setup Video Guide" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen ></iframe>

Setup Steps

From the **root of the repository**, one-time setup then start the services:
```bash
make dev-init   # once: creates backend/.venv and copies the env template
make dev-up     # starts the Firestore + Auth emulators and the Python API
```

`make dev-init` builds `backend/.venv` from whatever `python3` resolves to,
and the backend requires **Python 3.11** — make sure that's what you get, or
the harness fails later with import errors.

No provider API keys? Use fake providers instead:

```bash
PROVIDER_MODE=offline make dev-up
```

Check what came up with `make dev-status`, and stop it later with
`make dev-down`. Ports, seeded local users, and troubleshooting live in the
[local emulator runbook](https://github.com/BasedHardware/omi/blob/main/backend/docs/runbooks/local-emulator-manual-qa.md).
```bash cd app ``` ```bash bash setup.sh ios ``` ```bash bash setup.sh android ``` Open the app in your IDE and hit run: - **Xcode**: Open `app/ios` folder - **Android Studio**: Open `app/android` folder
Or run from terminal:
```bash
flutter run --flavor dev
```
The automatic setup runs entirely on your machine — local API, local emulators, no production data — making it the fastest way to start building apps and making changes. On a physical iPhone, set `OMI_DEV_HOST` to your Mac's LAN or Tailscale address before running both `setup.sh ios` and `make dev-up` (in the same shell, or exported so both commands see it) — this now makes the harness itself listen there too, not just the app you build. Only a private address works (LAN, e.g. `192.168.x.x`, or Tailscale/CGNAT, e.g. `100.x.x.x`); a public address is rejected. Use `OMI_DEV_BIND_HOST` instead if you want the harness to bind a different address than the one the app is compiled to reach.

Build the App Manually

Manual setup gives you full control, allowing you to use your own backend.

Ensure Flutter is installed by following the official [Flutter Installation Guide](https://docs.flutter.dev/get-started/install).
Verify your setup:
```bash
flutter doctor -v
```

<AccordionGroup>
  <Accordion title="Example output" icon="terminal">
    ```
    [✓] Flutter (Channel stable, 3.44.5, on macOS 15.4.1)
    [✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
    [✓] Xcode - develop for iOS and macOS (Xcode 16.4)
    [✓] Chrome - develop for the web
    [✓] Android Studio (version 2025.1)
    [✓] VS Code (version 1.101.0)
    [✓] Connected device (4 available)
    [✓] Network resources
    ```
  </Accordion>
  <Accordion title="Recommended versions" icon="info-circle">
    This project is tested with specific tool versions. See [`app/setup.sh`](https://github.com/BasedHardware/omi/blob/main/app/setup.sh) for recommended versions:
    - Flutter 3.44.5
    - Xcode 16.4
    - Android SDK Platform 35
    - NDK 28.2.13676358
    - JDK 21

    To set a specific JDK on macOS:
    ```bash
    flutter config --jdk-dir /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home
    ```
  </Accordion>
</AccordionGroup>
From the `app` directory, install packages: ```bash cd app flutter pub get ``` Navigate to iOS directory and install CocoaPods dependencies: ```bash cd ios pod install pod repo update ``` Create your environment file from the template: ```bash cd .. cat .env.template > .dev.env ``` Edit `.dev.env` and add your API keys:
| Key | Description |
|-----|-------------|
| `API_BASE_URL` | Your backend URL — `http://127.0.0.1:8000/` for the local harness, or [set up your own](/doc/developer/backend/Backend_Setup) |
| `GOOGLE_MAPS_API_KEY` | Optional - for location features |

<Warning>
Be sure to include the trailing `/` in `API_BASE_URL` or you'll get malformed URLs. If you change this later, delete the builds folder and recreate the runner.
</Warning>

<Warning>
Whatever backend you point at must verify Firebase ID tokens against the
**same Firebase project** the app signs into. Tokens are project-scoped, so a
mismatch returns **401 Unauthorized** on every authenticated call while
sign-in still appears to succeed. Omi's shared `https://api.omiapi.com/`
verifies against the production project and will reject tokens from the
`demo-omi-local` emulator or from your own Firebase project.
</Warning>
Generate necessary files: ```bash dart pub run build_runner clean dart pub run build_runner build ``` Firebase is **mandatory** for the app to run.
<Warning>
`setup.sh` installs **local emulator Firebase configs** (the `demo-omi-local`
project) for the `dev` flavor. If you're using the local backend harness (the
common case), they're already in place — skip to the next step. These configs
only work against the Firebase Auth emulator; they are not credentials for
any hosted Firebase project.

**Never run `flutterfire configure`** against Omi's bundle IDs — it overwrites the prebuilt prod credentials in `app/ios/Config/Prod/`, `app/lib/firebase_options_prod.dart`, and `app/android/app/src/prod/`.
</Warning>

If you need your **own** Firebase project (custom backend):

1. Follow the official [Firebase Flutter Setup](https://firebase.google.com/docs/flutter/setup) through Step 1
2. For Apple login, [create an identifier](https://developer.apple.com/account/resources/identifiers/list) first
3. Configure `flutterfire config` using **your own** bundle IDs and **your own** project — not Omi's
4. Generate SHA1/SHA256 keys for your keystore and add them to Firebase ([StackOverflow guide](https://stackoverflow.com/a/56091158) | [Official Docs](https://support.google.com/firebase/answer/9137403?hl=en))

<Tip>
If you're facing auth issues, enable Google/Apple sign-in in the Firebase Console under **Authentication → Sign-in method**.
</Tip>
Select your target device and run: ```bash flutter run -v --flavor dev ```
To build an APK:
```bash
flutter build apk --flavor dev
```

Code Formatting

We use dart format with a line length of 120 characters.

To automatically format code on commit, install the pre-commit hook:

# From the root of the repository
ln -s -f ../../scripts/pre-commit .git/hooks/pre-commit

Troubleshooting

- Run `flutter doctor -v` for detailed output - Follow the suggestions to fix each issue - Make sure all required SDKs are installed - Ensure CocoaPods is installed: `sudo gem install cocoapods` - Run `pod install` in the `ios` directory - Try `pod repo update` if dependencies fail - Check NDK is installed via Android Studio SDK Manager - Verify JDK version matches requirements (JDK 21) - Accept all Android licenses: `flutter doctor --android-licenses` - Enable Google/Apple sign-in in Firebase Console - Verify SHA1/SHA256 keys are added to Firebase - Check bundle IDs match your Firebase configuration `setup.sh` builds against `http://127.0.0.1:8000` but does not start anything. Run `make dev-up` from the repo root first, and confirm with `make dev-status`.
On a physical device, `127.0.0.1` is the phone — set `OMI_DEV_HOST` to your
Mac's LAN or Tailscale address before running **both** `setup.sh` (so the
build points at your machine) and `make dev-up` (so the harness actually
listens there — it defaults to loopback-only otherwise, which is why a
device build alone used to reach nothing). Export it in the same shell so
both commands see it. The Android emulator uses `10.0.2.2` by default.
The app and the backend are on **different Firebase projects**. Firebase ID tokens are project-scoped: a token minted for one project cannot be verified by a backend initialized for another, so authentication succeeds locally and every authenticated API call is rejected.
This shows up on the manual path, where you choose both sides: your own
Firebase project signs the user in while `API_BASE_URL` points at a backend
initialized for a different project. Point `API_BASE_URL` at a backend that
verifies against *your* project.

Omi's shared `https://api.omiapi.com/` is never a valid target for a
self-configured build — it verifies against Omi's own Firebase project, and
the `demo-omi-local` configs `setup.sh` installs are emulator-only fakes that
no hosted backend can verify. Production data requires the explicit `beta`
profile.
**Symptoms:** - The dev build runs fine while `flutter run` is attached, then crashes instantly when you open it from the Home Screen after disconnecting (or iOS relaunches it in the background for Bluetooth/VoIP). The phone's crash report ends in `SwiftAwesomeNotificationsPlugin.register(with:)` with `KERN_INVALID_ADDRESS at 0x0`. - `flutter run` itself prints: ``` error: Unable to flip between RX and RW memory protection on pages ```
**Cause:**
Debug builds run the Dart VM in JIT mode, and iOS only lets Flutter tooling
start a JIT VM on a physical device. Without it, `FlutterEngine` init returns
nil, the app's `FlutterViewController` has no engine, and plugin registration
has nothing to register against. The app now shows a notice explaining this
instead of crashing, but it still cannot run.

**Solutions:**

1. **Install an AOT build for untethered use (physical devices):**
   ```bash
   OMI_MOBILE_BUILD_MODE=profile bash setup.sh ios
   ```
   Profile (or `release`) builds open from the Home Screen on their own. You
   lose hot reload; press `d` in `flutter run` to detach and keep the app running.
   `setup.sh ios` warns whenever a debug build is about to land on a physical iPhone.

2. **Use the iOS Simulator for debug-mode development:**
   - The simulator has no JIT restriction, so `flutter run --flavor dev` works
     from the Home Screen too.

Need Help?

Search the help channel or ask questions Report bugs or browse existing issues

Related Documentation

Set up your own Omi backend Create Omi apps and integrations Flash and update device firmware How to contribute to Omi