# Android App

This guide covers building and contributing to the KayakNet Android app.

## Overview

The Android app provides:

* Full KayakNet connectivity
* Chat (rooms and DMs)
* Marketplace browsing
* Domain lookup
* Native Android experience

## Tech Stack

* **Language:** Kotlin
* **UI:** Jetpack Compose
* **Architecture:** MVVM
* **Networking:** Ktor HTTP client
* **Build:** Gradle

## Project Structure

```
android/
├── app/
│   ├── src/main/
│   │   ├── java/com/kayaknet/
│   │   │   ├── MainActivity.kt
│   │   │   ├── KayakNetApp.kt
│   │   │   ├── ui/
│   │   │   │   ├── screens/
│   │   │   │   │   ├── HomeScreen.kt
│   │   │   │   │   ├── ChatScreen.kt
│   │   │   │   │   ├── MarketScreen.kt
│   │   │   │   │   └── DomainsScreen.kt
│   │   │   │   └── theme/
│   │   │   │       └── Theme.kt
│   │   │   └── network/
│   │   │       └── KayakNetClient.kt
│   │   ├── res/
│   │   │   ├── drawable/
│   │   │   └── values/
│   │   └── AndroidManifest.xml
│   └── build.gradle.kts
├── build.gradle.kts
└── settings.gradle.kts
```

## Building

### Prerequisites

* Android Studio Hedgehog (2023.1.1) or later
* JDK 17
* Android SDK (API 34)

### Build Steps

```bash
# Clone repository
git clone https://github.com/KayakNet/KayakNet.git
cd KayakNet/android

# Build debug APK
./gradlew assembleDebug

# Output: app/build/outputs/apk/debug/app-debug.apk
```

### Build Release APK

```bash
# Create signing key (first time only)
keytool -genkey -v -keystore kayaknet.keystore \
  -alias kayaknet -keyalg RSA -keysize 2048 -validity 10000

# Build release
./gradlew assembleRelease

# Output: app/build/outputs/apk/release/app-release.apk
```

## GitHub Actions

Automated builds via GitHub Actions:

```yaml
# .github/workflows/android.yml
name: Build Android APK

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
      - name: Build APK
        run: |
          cd android
          chmod +x gradlew
          ./gradlew assembleDebug
      - name: Upload APK
        uses: actions/upload-artifact@v4
        with:
          name: kayaknet-debug
          path: android/app/build/outputs/apk/debug/app-debug.apk
```

## Architecture

### Network Communication

The app communicates with the KayakNet backend via HTTP:

```kotlin
class KayakNetClient(private val baseUrl: String) {
    private val client = HttpClient(CIO) {
        install(ContentNegotiation) {
            json()
        }
    }
    
    suspend fun getChatRooms(): List<ChatRoom> {
        return client.get("$baseUrl/api/chat/rooms").body()
    }
    
    suspend fun sendMessage(room: String, content: String) {
        client.post("$baseUrl/api/chat/send") {
            setBody(FormDataContent(Parameters.build {
                append("room", room)
                append("content", content)
            }))
        }
    }
}
```

### Bootstrap Connection

```kotlin
val bootstrapUrl = "http://203.161.33.237:8080"
val client = KayakNetClient(bootstrapUrl)
```

### UI with Jetpack Compose

```kotlin
@Composable
fun ChatScreen(viewModel: ChatViewModel) {
    val messages by viewModel.messages.collectAsState()
    
    Column {
        LazyColumn(modifier = Modifier.weight(1f)) {
            items(messages) { msg ->
                MessageItem(msg)
            }
        }
        MessageInput(onSend = { viewModel.sendMessage(it) })
    }
}
```

## Features Implementation

### Chat

* Rooms list from `/api/chat/rooms`
* Messages from `/api/chat/history`
* Send via POST `/api/chat/send`
* Polling for updates (1s interval)

### Marketplace

* Listings from `/api/market/listings`
* Details from `/api/market/listing?id=X`
* Categories and search supported

### Domains

* Lookup via `/api/domains/lookup?domain=X`
* My domains from `/api/domains/mine`

## Testing

### Unit Tests

```bash
./gradlew test
```

### Instrumented Tests

```bash
./gradlew connectedAndroidTest
```

### Manual Testing

1. Install APK on device/emulator
2. Ensure KayakNet node is running
3. App should connect automatically

## Known Issues

### No Local Node

The Android app connects to the bootstrap node, not a local node. This means:

* Relies on bootstrap availability
* No local proxy mode
* Limited offline capability

### Future: Embedded Node

Planned: Embed Go node using gomobile:

```bash
gomobile bind -target=android ./pkg/mobile
```

## Contributing

### Code Style

* Kotlin conventions
* Compose best practices
* Clear naming
* Comments for complex logic

### Pull Requests

1. Fork repository
2. Create feature branch
3. Test on multiple devices
4. Submit PR with description

## Troubleshooting

### Build Fails

```bash
# Clean and rebuild
./gradlew clean
./gradlew assembleDebug
```

### Connection Issues

* Verify bootstrap is running
* Check internet connectivity
* Try with VPN if needed

### UI Issues

* Check Compose version compatibility
* Verify Material3 components
* Test on different screen sizes


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.kayaknet.io/development/android.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
