On this page
Users dictate messages while walking, search hands-free in the kitchen, and record voice notes in meetings. Good voice features are fast, accurate in the user's language and accent, respectful of privacy, and always have a typing fallback.
Your options
| Option | Strengths | Limits |
|---|---|---|
Platform SpeechRecognizer | Built in, streaming partial results, many languages; on-device recognition on newer Android versions | Short utterances; behaviour depends on the device's recognition service |
| ML Kit GenAI Speech Recognition | On-device transcription (alpha at the time of writing) | Device and mode support varies; alpha API |
| Cloud multimodal model (e.g. Gemini with audio input) | Transcribe and summarise, translate or extract in one step | Network, cost, privacy considerations |
| Dedicated cloud speech APIs | Long-form, diarization, specialised models | Backend integration and cost |
Platform SpeechRecognizer as a Flow
sealed interface SpeechEvent {
data class Partial(val text: String) : SpeechEvent
data class Final(val text: String) : SpeechEvent
data class Error(val code: Int) : SpeechEvent
}
@RequiresPermission(Manifest.permission.RECORD_AUDIO)
fun Context.listen(languageTag: String = Locale.getDefault().toLanguageTag()): Flow<SpeechEvent> = callbackFlow {
val recognizer =
if (Build.VERSION.SDK_INT >= 31 && SpeechRecognizer.isOnDeviceRecognitionAvailable(this@listen))
SpeechRecognizer.createOnDeviceSpeechRecognizer(this@listen) // audio stays on device
else SpeechRecognizer.createSpeechRecognizer(this@listen)
recognizer.setRecognitionListener(object : RecognitionListener {
override fun onPartialResults(b: Bundle) {
b.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.firstOrNull()?.let { trySend(SpeechEvent.Partial(it)) }
}
override fun onResults(b: Bundle) {
trySend(SpeechEvent.Final(b.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.firstOrNull().orEmpty()))
close()
}
override fun onError(error: Int) { trySend(SpeechEvent.Error(error)); close() }
override fun onReadyForSpeech(p: Bundle?) {}
override fun onBeginningOfSpeech() {}
override fun onRmsChanged(rms: Float) {}
override fun onBufferReceived(b: ByteArray?) {}
override fun onEndOfSpeech() {}
override fun onEvent(t: Int, b: Bundle?) {}
})
recognizer.startListening(Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, languageTag) // e.g. "hi-IN", "en-IN"
putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
})
awaitClose { recognizer.destroy() }
}.flowOn(Dispatchers.Main) // SpeechRecognizer must be used from the main threadFrom transcript to action with AI
A transcript like "remind me to call the plumber tomorrow at 10" can be turned into a structured intent by a model, using structured output or function calling. See Function Calling.
@Serializable data class ReminderIntent(val title: String, val dateTimeIso: String?)
suspend fun parseReminder(model: GenerativeModel, transcript: String, nowIso: String): ReminderIntent? {
val response = model.generateContent(
"Current time: $nowIso. Extract a reminder from the user's words as JSON with fields " +
"title and dateTimeIso (ISO-8601, null if no time). User said: <said>$transcript</said>"
)
return runCatching { Json { ignoreUnknownKeys = true }.decodeFromString<ReminderIntent>(response.text.orEmpty()) }.getOrNull()
}
// Always show: "Create reminder 'Call the plumber' for tomorrow 10:00?" โ user confirms.Speaking responses: TextToSpeech
class Speaker(context: Context) : TextToSpeech.OnInitListener {
private val tts = TextToSpeech(context, this)
private var ready = false
override fun onInit(status: Int) { ready = status == TextToSpeech.SUCCESS }
fun say(text: String, locale: Locale = Locale.getDefault()) {
if (!ready) return
tts.language = locale
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, "utt-${text.hashCode()}")
}
fun shutdown() = tts.shutdown()
}Permissions and privacy
- Request
RECORD_AUDIOin context, when the user taps the mic, and explain why. - Show a clear recording indicator, and stop listening when the user leaves the screen.
- Prefer on-device recognition for sensitive content. Disclose any cloud processing and retention.
- Never record in the background without explicit, ongoing user awareness.
Use cases
Dictation in forms
Mic button on text fields, with partial results shown live and editable.
Voice notes
Record, transcribe and summarise. See AI Voice-Notes App.
Hands-free commands
Transcribe, parse the intent, confirm, act, speak the result.
Frequently asked questions
Does SpeechRecognizer support Indian languages?
Support depends on the recognition service and language packs on the device. Many devices support Hindi and other Indian languages. Test on target devices, and fall back to typing.
Can I transcribe long recordings?
SpeechRecognizer is designed for short utterances. For long recordings, record audio to a file and transcribe it with an on-device model or a cloud service.
Is audio sent to Google?
With on-device recognizers, audio is processed locally. Other recognition services or cloud APIs may send audio to servers, so check the service and disclose it to users.
Conclusion
Voice features combine speech-to-text (platform, on-device or cloud), optional AI interpretation into structured intents, confirmation before actions, and optional text-to-speech. Request the microphone in context, prefer on-device for privacy, and always keep a typing path.
Next step: generate useful content with AI in Using AI to Generate App Content Dynamically.
Official references
๐ฑ Apps built by Yunok Tech
Real Android apps on Google Play, free to download.
Walzi4K wallpapers for lock and home screenGet it โธ
NotiVaultNotification history: recover dismissed notificationsGet it โธ
Ready to build real Android applications?
Every AI feature still runs inside an Android app that has to be fast, reliable and well structured. Strengthen the Kotlin, Jetpack Compose and architecture skills that AI integrations depend on, then apply these AI concepts with confidence.
Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.
Explore the Android course and take your next step as an Android developer.