# Android Client

Native Android app that wraps the Navi web client in a WebView.

## Location

`android-client/` — standalone Android project (Kotlin, Gradle).

## Architecture

Single-activity app with two screens:

| Activity | Purpose |
|---|---|
| `SetupActivity` | First-launch screen — prompts for server URL, saves to SharedPreferences |
| `MainActivity` | Main screen — full-screen WebView loading the Navi web client |

Server URL is stored in SharedPreferences under key `server_url`. If absent on launch, `SetupActivity` is shown. If the WebView fails to load the main frame, the saved URL is cleared so the next launch prompts again.

## Build & Deploy

```bash
cd android-client

# Debug APK
./gradlew assembleDebug

# Install via adb (device connected via USB)
adb install -r app/build/outputs/apk/debug/app-debug.apk

# One-liner: build + install
./gradlew assembleDebug && adb install -r app/build/outputs/apk/debug/app-debug.apk
```

## WebView configuration

| Setting | Value | Reason |
|---|---|---|
| `javaScriptEnabled` | true | Required for the Vue app |
| `domStorageEnabled` | true | Session state, composables |
| `cacheMode` | `LOAD_NO_CACHE` | Always fetch fresh from server |
| `mixedContentMode` | `ALWAYS_ALLOW` | Local server may serve mixed content |
| `userAgentString` | `…original… NaviAndroid/1.0` | Platform detection in web client |

## External link handling

`shouldOverrideUrlLoading` intercepts all navigation:
- URL host matches the Navi server → handled by WebView (returns `false`)
- Any other host (external link) → opened via `Intent.ACTION_VIEW` in the system browser (returns `true`)

This means links Navi produces in chat (URLs to external sites, generated HTML pages served by nginx, etc.) open in the user's browser, not inside the app.

## Platform detection in web client

The app appends `NaviAndroid/1.0` to the WebView's User-Agent. The web client can detect this:

```js
import { isAndroid } from '@/composables/usePlatform.js'

if (isAndroid) {
  // Android-specific behaviour
}
```

`usePlatform.js` is a single-line composable:
```js
export const isAndroid = navigator.userAgent.includes('NaviAndroid')
```

Use this for any future UI differences between the web client and the Android app (hiding elements, adjusting layout, etc.).

## Back navigation

Hardware back button navigates WebView history if available (`webView.canGoBack()`), otherwise falls through to the default Android behaviour (closes the activity).

## File / image picker

`WebChromeClient.onShowFileChooser` is implemented to support image attachment in chat:
- Requests `CAMERA` and `READ_MEDIA_IMAGES` / `READ_EXTERNAL_STORAGE` permissions at runtime
- Presents a chooser combining gallery picker and camera capture
- Camera photos are saved to `getExternalFilesDir(DIRECTORY_PICTURES)` via `FileProvider`
