fuzzyworld

ai-chat-android-auto / files / README.md

README.md

5.3 KB · history · blame

AI Chat for Android Auto

An Android Auto voice assistant that sends your spoken questions to an AI provider and reads the responses back through the car's speakers.

You choose the provider — Anthropic, OpenAI, Groq, Mistral, Google Gemini, or a local Ollama instance. API keys are stored on-device in EncryptedSharedPreferences and never leave the phone.


How it works

  1. Open the AI Chat for Android Auto app on your phone and configure a provider + API key.
  2. Connect your phone to the car. The app appears in the Android Auto launcher.
  3. Tap Ask AI (or press Play on the steering wheel) and speak your question.
  4. The app sends your question to the provider's API and reads the answer aloud.
  5. Past exchanges appear in the browse list so you can re-ask any previous question.

Setup

Requirements

Phone setup

  1. Install the APK (sideload or Play Store release).
  2. Open AI Chat for Android Auto on your phone.
  3. Select a provider, enter your API key, and tap Save Key.
  4. Tap ↻ to fetch available models and select one.
  5. Grant microphone permission when prompted.

Android Auto

The app registers as a media browser service, so it requires no special permissions beyond a standard media app. If using a sideloaded build, enable Unknown sources for Android Auto via ADB first:

adb shell settings put global android_auto_unknown_sources 1

Supported providers

Provider API key required Web search Notes
Anthropic ✅ ✅ (built-in) Default provider
OpenAI ✅ — GPT-4o and newer
Groq ✅ — Very fast inference
Mistral ✅ —
Google Gemini ✅ —
Ollama (local) — — Requires local server; configure base URL
Custom (OpenAI-compatible) Optional — Any endpoint that speaks /v1/chat/completions

Adding a new provider

OpenAI-compatible API (5 lines)

Add an object to OpenAiCompatibleProvider.kt:

object MyProvider : OpenAiCompatibleProvider() {
    override val id           = "myprovider"       // stable, never change
    override val displayName  = "My Provider"
    override val defaultBaseUrl = "https://api.myprovider.com"
    override val defaultModel = "my-model-name"
    override val requiresApiKey = true
}

Then add MyProvider to the list in ProviderRegistry.kt.

Unique API format

Implement the AiProvider interface directly (see GeminiProvider.kt as an example), then register it in ProviderRegistry.

The interface requires two methods: - ask(apiKey, baseUrl, model, question, onResult) — call the API and return the text response - listModels(apiKey, baseUrl, onResult) — return a list of ModelInfo(id, displayName)


Building from source

# Clone and open in Android Studio, or build from the command line:
./gradlew assembleRelease

Signing credentials go in local.properties (gitignored):

release.storeFile=path/to/release.jks
release.storePassword=...
release.keyAlias=...
release.keyPassword=...

Releasing

Push a tag to trigger the CI pipeline, which builds a signed APK, uploads it to the Package Registry, and creates a GitLab Release with a download link.

git tag v1.2.3 && git push origin v1.2.3

The release will appear under Deploy → Releases in the GitLab sidebar.

CI/CD variables

Configure these in Settings → CI/CD → Variables (all masked):

Variable Description
KEYSTORE_BASE64 Release keystore encoded as base64 (base64 -i claudeauto-release.jks \| pbcopy)
KEYSTORE_PASSWORD Keystore password (used for both the store and the key)

Upcoming work


Attribution

App icon by icongeek26 from the Outline collection on Flaticon.


License

MIT — see LICENSE.

Source
1# AI Chat for Android Auto
2
3An Android Auto voice assistant that sends your spoken questions to an AI provider and reads the responses back through the car's speakers.
4
5You choose the provider — Anthropic, OpenAI, Groq, Mistral, Google Gemini, or a local Ollama instance. API keys are stored on-device in `EncryptedSharedPreferences` and never leave the phone.
6
7---
8
9## How it works
10
111. Open the **AI Chat for Android Auto** app on your phone and configure a provider + API key.
122. Connect your phone to the car. The app appears in the Android Auto launcher.
133. Tap **Ask AI** (or press Play on the steering wheel) and speak your question.
144. The app sends your question to the provider's API and reads the answer aloud.
155. Past exchanges appear in the browse list so you can re-ask any previous question.
16
17---
18
19## Setup
20
21### Requirements
22- Android 6.0+ (API 23)
23- Android Auto on the phone
24
25### Phone setup
261. Install the APK (sideload or Play Store release).
272. Open **AI Chat for Android Auto** on your phone.
283. Select a provider, enter your API key, and tap **Save Key**.
294. Tap **↻** to fetch available models and select one.
305. Grant microphone permission when prompted.
31
32### Android Auto
33The app registers as a media browser service, so it requires no special permissions beyond a standard media app. If using a sideloaded build, enable **Unknown sources** for Android Auto via ADB first:
34
35```
36adb shell settings put global android_auto_unknown_sources 1
37```
38
39---
40
41## Supported providers
42
43| Provider | API key required | Web search | Notes |
44|---|---|---|---|
45| [Anthropic](https://console.anthropic.com) | ✅ | ✅ (built-in) | Default provider |
46| [OpenAI](https://platform.openai.com) | ✅ | — | GPT-4o and newer |
47| [Groq](https://console.groq.com) | ✅ | — | Very fast inference |
48| [Mistral](https://console.mistral.ai) | ✅ | — | |
49| [Google Gemini](https://aistudio.google.com) | ✅ | — | |
50| Ollama (local) | — | — | Requires local server; configure base URL |
51| Custom (OpenAI-compatible) | Optional | — | Any endpoint that speaks `/v1/chat/completions` |
52
53---
54
55## Adding a new provider
56
57### OpenAI-compatible API (5 lines)
58
59Add an object to [OpenAiCompatibleProvider.kt](app/src/main/java/net/fuzzyworld/aichat/OpenAiCompatibleProvider.kt):
60
61```kotlin
62object MyProvider : OpenAiCompatibleProvider() {
63 override val id = "myprovider" // stable, never change
64 override val displayName = "My Provider"
65 override val defaultBaseUrl = "https://api.myprovider.com"
66 override val defaultModel = "my-model-name"
67 override val requiresApiKey = true
68}
69```
70
71Then add `MyProvider` to the list in [ProviderRegistry.kt](app/src/main/java/net/fuzzyworld/aichat/ProviderRegistry.kt).
72
73### Unique API format
74
75Implement the `AiProvider` interface directly (see [GeminiProvider.kt](app/src/main/java/net/fuzzyworld/aichat/GeminiProvider.kt) as an example), then register it in `ProviderRegistry`.
76
77The interface requires two methods:
78- `ask(apiKey, baseUrl, model, question, onResult)` — call the API and return the text response
79- `listModels(apiKey, baseUrl, onResult)` — return a list of `ModelInfo(id, displayName)`
80
81---
82
83## Building from source
84
85```bash
86# Clone and open in Android Studio, or build from the command line:
87./gradlew assembleRelease
88```
89
90Signing credentials go in `local.properties` (gitignored):
91
92```properties
93release.storeFile=path/to/release.jks
94release.storePassword=...
95release.keyAlias=...
96release.keyPassword=...
97```
98
99---
100
101## Releasing
102
103Push a tag to trigger the CI pipeline, which builds a signed APK, uploads it to
104the Package Registry, and creates a GitLab Release with a download link.
105
106```bash
107git tag v1.2.3 && git push origin v1.2.3
108```
109
110The release will appear under **Deploy → Releases** in the GitLab sidebar.
111
112### CI/CD variables
113
114Configure these in **Settings → CI/CD → Variables** (all masked):
115
116| Variable | Description |
117|---|---|
118| `KEYSTORE_BASE64` | Release keystore encoded as base64 (`base64 -i claudeauto-release.jks \| pbcopy`) |
119| `KEYSTORE_PASSWORD` | Keystore password (used for both the store and the key) |
120
121---
122
123## Upcoming work
124
125- **Persist conversation history across sessions** — current history is in-memory only and lost when the service stops
126- **Per-provider system prompt customization** — let users adjust the assistant's persona and instructions
127- **Streaming response support** — start speaking the first sentence while the rest of the response is still arriving, reducing perceived latency
128- **Web search for non-Anthropic providers** — integrate an external search API (e.g. Brave Search, Tavily) so all providers can answer current-events questions
129- **Gemini grounding / web search** — wire up Google's native grounding tool for Gemini responses
130- **Hands-free activation** — start listening without tapping, triggered by a wake phrase or steering-wheel button mapping
131- **Export / import configuration** — back up and restore provider settings and API keys
132- **Android Automotive OS (AAOS) support** — native in-car OS support alongside the current Android Auto projection mode
133
134---
135
136## Attribution
137
138App icon by [icongeek26](https://www.flaticon.com/authors/icongeek26) from the [Outline collection](https://www.flaticon.com/authors/icongeek26/outline?author_id=296&type=standard) on [Flaticon](https://www.flaticon.com).
139
140---
141
142## License
143
144MIT — see [LICENSE](LICENSE).