# Glass AI Chat

## Purpose

Demonstrate booting AI chat sessions, submitting user prompts, and collecting incremental model output on the glasses.

## Entry points

Glass home:

- `HomeActivity` → `SdkMediaActivity`

Sample Activity:

- `com.rokid.glass.SdkMediaActivity`

## Platform

- Glass

## Main file

- [SdkMediaActivity.kt](https://gitee.com/as_pixar/glass3sdkdemo/blob/main/glassdemo/app/src/main/java/com/rokid/glass/SdkMediaActivity.kt)

## Hot spots

- `binding.btnAiChat.setOnClickListener`  
- `binding.btnStopAiChat.setOnClickListener`  
- `mAIChaLister` stub implementation

Bundle with:

- [SendMessageActivity.kt](https://gitee.com/as_pixar/glass3sdkdemo/blob/main/glassdemo/app/src/main/java/com/rokid/glass/SendMessageActivity.kt) — ASR/TTS flows  
- [HomeActivity.kt](https://gitee.com/as_pixar/glass3sdkdemo/blob/main/glassdemo/app/src/main/java/com/rokid/glass/HomeActivity.kt) — offline wake-word registry

## Related docs

- [Glass3 Glass SDK API reference](/en/terminal-sdk/api-reference/Glass3%20%20SDK(%E7%9C%BC%E9%95%9C%E7%AB%AF)%20API%E6%96%87%E6%A1%A3.md)
- [Quick start](/en/terminal-sdk/getting-started/快速开始.md)

## Flow

1. Tap the AI shortcut.  
2. `GlassSdk.getGlassAiChatService()?.startAiChat(false)` boots the session channel.  
3. `toAiChat(...)` submits the canned prompt bundled with upstream (same wording as upstream repo).  
4. `AiChatListener` streams partial + final payloads.  
5. `endAiChat()` tears down jobs when user aborts.

## Snippets

```kotlin
binding.btnAiChat.setOnClickListener {
    GlassSdk.getGlassAiChatService()?.startAiChat(false)
    GlassSdk.getGlassAiChatService()?.toAiChat(
        "Will it rain in Hangzhou tomorrow?",
        mAIChaLister
    )
}

binding.btnStopAiChat.setOnClickListener {
    GlassSdk.getGlassAiChatService()?.endAiChat()
}
```

```kotlin
private val mAIChaLister = object : AiChatListener.Stub() {
    override fun onAiChatAnswer(
        answer: String?,
        isFinish: Boolean,
        contentType: String?,
        sessionId: String?
    ) {
        L.i(TAG, "onAiChatAnswer: answer = $answer")
    }

    override fun onError(code: Int, message: String) {}
}
```

## Callback matrix handled

- `onContinuousModeUpdate(...)`  
- `onAiChatAnswer(answer, isFinish, contentType, sessionId)`  
- `onError(code, message)`  
- `onAiTakePhoto(filePath)`

## Sequence

```mermaid
sequenceDiagram
    participant UI as Glass UI
    participant AI as AI Chat Service

    UI->>AI: startAiChat(false)
    UI->>AI: toAiChat(prompt, listener)
    AI-->>UI: onAiChatAnswer(chunk, isFinish=false)
    AI-->>UI: onAiChatAnswer(chunk, isFinish=false)
    AI-->>UI: onAiChatAnswer(chunk, isFinish=true)
    UI->>AI: endAiChat()
```

## FAQs

### Why `isFinish` exists

Answers stream chunk-by-chunk — `answer` deltas arrive until `isFinish` asserts completion for that turn.

### `onAiTakePhoto`

Signals device-action intents (e.g. capture) beyond pure texting—helps design assistant scenarios.

### `sessionId`

Log correlation + future multi-turn context—persist for production analytics.

## Voice stack integration

Typical storyboard:

- ASR → user text  
- AI Chat → reasoning / answer  
- TTS → audible reply  

Samples currently split these across pages but you can unify them in one state machine.

## Suggested composition

| Stage | Capability | Sample reference |
| --- | --- | --- |
| Input | Cloud ASR | `SendMessageActivity` |
| Reasoning | AI Chat | `SdkMediaActivity` |
| Output | TTS | `SendMessageActivity` |

## Caveats

- Demo focuses on wiring, not final chat UI.  
- Production assistants should orchestrate ASR + AI + TTS lifecycle in one cohesive controller layer.
