Repository navigation
Conversation
…bubble A Kotlin app in App/BlurtAndroid, modelled on Wispr Flow's Android bubble: it floats over other apps while a keyboard is up; tap to dictate, tap again, and the words land in the focused field. - One streamed POST to the dictation route, the same request the Mac and iPhone make: config first, then 16 kHz PCM frames as they're recorded, the text before the cursor as stt_prompt, and the engine's cleanup instruction (copied verbatim) as llm_instruction. - An accessibility service finds the focused field across windows, inserts with the spacing rule, and reports whether a keyboard is on screen. A field that reports no cursor gets a paste: Telegram's empty box reports its "Message" placeholder as text with selection -1. - The iPhone's style presets (copied verbatim) plus a custom style. - The API key is encrypted under an Android Keystore key. - Icons are built from the b icon in the Blurt Figma file. Not built or checked by CI. AGENTS.md gains a repo-map entry; prettier also realigns one existing table row there that already failed `prettier --check` on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A port of the Mac's sign-in (Sources/AssemblyAI/OAuth and the engine's AssemblyAIAccount): authorization code with PKCE on the dashboard's consent page in a Custom Tab, the access token traded for the connection's API key, renewal, and a sign-out that revokes server-side. - Off unless local.properties sets blurt.oauth.* (the Mac's SignIn.local.xcconfig values), so builds without them show only the paste-a-key path, as the Mac's release builds do. - Reuses the Mac's redirect, com.assemblyai.blurt://oauth/callback, which the Connected App already lists; MainActivity is singleTask so the redirect lands on the open setup screen. - The minted key goes where a pasted one does; the session sits beside it, encrypted under the same Keystore key (SecureStore). - No renewal timer on Android: renews when the app opens and when the bubble starts a dictation, and at once (at most every 15 min) when dictation reports the key refused. - A sandbox sign-in dictates against its own host (dictationOrigin). Untested end to end: the sandbox values weren't available. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Target Android 16 (API 36), which Play requires of new apps from 2026-08-31; AGP 8.10.1 for compileSdk 36. - Play's prominent disclosure for the Accessibility API: step 4's "Open settings" first shows what Blurt typing reads, what goes to AssemblyAI, and that password fields are never read; only "Agree and continue" opens the settings. The service declares isAccessibilityTool="false". - Release signing with an upload key kept outside the repo: its path in local.properties, its password from BLURT_UPLOAD_PASSWORD or the macOS Keychain. `./gradlew bundleRelease` builds the .aab Play takes. Built and signature-verified; not yet run on a device. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
A first Android version of Blurt in
App/BlurtAndroid(Kotlin, Gradle), modelled on Wispr Flow's Android bubble. It floats over other apps while a keyboard is up: tap it, speak, tap again, and the words land in the focused field.dictation.assemblyai.com/v1/transcribe/live. Theconfigpart goes first, then 16 kHz mono PCM frames as they're recorded, with the text before the cursor asstt_promptand the engine's cleanup instruction asllm_instruction.DictationClient.ktmirrorsAssemblyAITranscriber.swift.-1.StylePreset.swift), plus Custom, appended with the engine's style preamble.Sources/AssemblyAI/OAuthand the engine'sAssemblyAIAccount: PKCE on the consent page in a Custom Tab, the access token traded for the connection's API key, renewal, and a sign-out that revokes server-side. It reuses the Mac's redirect,com.assemblyai.blurt://oauth/callback. It's off unlesslocal.propertiessetsblurt.oauth.*(the Mac'sSignIn.local.xcconfigvalues), the same way the Mac's release builds leave it off. Android can't keep a renewal timer running, so it renews when the app opens, when a dictation starts, and at once when dictation reports the key refused. A sandbox sign-in dictates against its own host.Two files copy Swift text verbatim and must be kept in sync by hand:
CleanupInstruction.ktand the presets inStyles.kt.AGENTS.mdgains a repo-map entry. Prettier also realigns one existing table row there (AVAudioEngine), which already failedprettier --checkonmain.Not done yet: key terms, text shortcuts, release signing, tests.
How it was tested
Built and installed with
./gradlew installDebug, then used on a Galaxy Z Fold (Android 17): dictation into Telegram and other apps, styles, drag and snap, keyboard-only visibility.Sign in with AssemblyAI is untested end to end: the sandbox values weren't available. With no
blurt.oauth.*set, the setup screen is unchanged (paste-a-key only).Android Lint: no issues beyond dependency-version and backup notices.
scripts/check.sh --portablepasses for the files this touches. Several linters weren't installed locally, so they were skipped. Nothing in CI builds or checks the Android app yet.scripts/check.shpasses (or CI will, if I'm not on a Mac)I read AGENTS.md and this doesn't reintroduce anything deliberately removed
Docs updated if behavior changed
🤖 Generated with Claude Code