共计 2911 个字符,预计需要花费 8 分钟才能阅读完成。
技术背景
语音识别已成为移动应用的核心交互方式,常见于智能助手、实时字幕、语音搜索等场景。Android 平台实现语音识别需解决三大技术挑战:

- 后台服务保活:语音识别通常需要长时间运行,但系统资源限制可能导致服务被回收
- 动态权限管理:Android 6.0+ 要求运行时申请 RECORD_AUDIO 权限
- 设备兼容性:不同厂商 ROM 对麦克风访问存在差异化限制
方案选型
1. Android 原生 SpeechRecognizer
优势:
– 零成本集成,无需额外依赖
– 支持离线识别(API Level 23+)
– 默认使用 Google 语音识别引擎
局限性:
– 识别准确率依赖系统语音引擎版本
– 最长识别时长限制为 60 秒
2. Google Cloud Speech-to-Text
优势:
– 支持 100+ 语言实时识别
– 提供说话人分离等高级功能
– 可定制词汇表提升专业术语识别率
适用场景:
– 需要多语言支持的全球化应用
– 专业领域的高精度识别需求
核心实现
基础集成(Kotlin)
class SpeechRecognitionHelper(context: Context) {private val speechRecognizer = SpeechRecognizer.createSpeechRecognizer(context).apply {
setRecognitionListener(object : RecognitionListener {override fun onReadyForSpeech(params: Bundle?) {// 麦克风准备就绪}
override fun onResults(results: Bundle?) {results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.let {// 处理识别结果}
}
override fun onError(error: Int) {when (error) {SpeechRecognizer.ERROR_NO_MATCH -> retryRecognition()
// 其他错误处理...
}
}
})
}
fun startListening() {
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.RECORD_AUDIO
) == PackageManager.PERMISSION_GRANTED
) {
speechRecognizer.startListening(Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "zh-CN")
putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
}
)
} else {// 请求权限逻辑}
}
}
关键机制实现
- 错误重试机制:
private var retryCount = 0
private const val MAX_RETRY = 2
private fun retryRecognition() {if (retryCount < MAX_RETRY) {Handler(Looper.getMainLooper()).postDelayed({startListening()
retryCount++
}, 1000)
}
}
- 超时控制:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- 在线识别需要 -->
性能优化
音频采样率配置
通过 AudioRecord 调整采样率(参考 AudioFormat.ENCODING_PCM_16BIT):
val sampleRate = when {AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM) >= 48000 -> 48000
else -> 16000
}
长时间任务处理
使用 WorkManager 执行后台识别任务:
val recognitionWork = OneTimeWorkRequestBuilder<SpeechWorker>()
.setConstraints(Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build())
.build()
WorkManager.getInstance(context).enqueue(recognitionWork)
避坑指南
国产 ROM 兼容方案
- 华为 EMUI:
- 在 Manifest 添加
<uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT" /> -
引导用户手动开启应用自启动权限
-
小米 MIUI:
- 使用
PowerManager.isIgnoringBatteryOptimizations检查电池优化状态 - 通过
ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS请求豁免
内存泄漏预防
override fun onDestroy() {
speechRecognizer.apply {setRecognitionListener(null)
destroy()}
super.onDestroy()}
扩展思考
Jetpack Compose 集成
实现实时语音波形动画:
@Composable
fun VoiceWaveform(amplitude: Float) {Canvas(modifier = Modifier.height(40.dp)) {
drawRect(
color = Color.Blue,
size = Size(10f, amplitude * 100),
topLeft = Offset(size.width / 2 - 5, size.height / 2 - amplitude * 50)
)
}
}
实时更新识别结果:
var results by remember {mutableStateOf("") }
LaunchedEffect(Unit) {
speechRecognizer.setRecognitionListener(object : RecognitionListener {override fun onPartialResults(partialResults: Bundle?) {partialResults?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.let {results = it[0]
}
}
})
}
延伸阅读
正文完
