You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在HiltViewModel中获取Application/上下文调用谷歌语音转文字API

在Hilt ViewModel中获取Application实例的解决方法

核心方案:通过Hilt构造注入Application

Hilt默认支持Application类型的依赖注入,直接在@HiltViewModel的构造函数中声明Application参数即可获取实例,无需额外配置。

代码修改步骤

  1. 在ViewModel构造函数中添加Application参数并注入:
@HiltViewModel
class SettingsViewModel @Inject constructor(
    private val settingsRepository: SettingsRepository,
    private val application: Application // 新增:注入Application
) : ViewModel(), RecognitionListener
  1. 替换代码中所有需要上下文的地方:
  • 创建SpeechRecognizer时直接使用application(Application本身就是Context的子类)
  • 获取包名时用application.packageName

修改后的完整代码示例

@HiltViewModel
class SettingsViewModel @Inject constructor(
    private val settingsRepository: SettingsRepository,
    private val application: Application // 注入Application
) : ViewModel(), RecognitionListener
{
    data class SpeechState(
        val spokenText: String = "",
        val error: String = ""
    )

    private val _settings = MutableStateFlow(value = Settings())
    val settings: StateFlow<HomeSettings> = _settings.asStateFlow()
    private val speechState = MutableStateFlow(value = SpeechState())

    // 用lazy延迟初始化,避免ViewModel创建时就持有SpeechRecognizer(优化内存)
    private val speechRecognizer: SpeechRecognizer by lazy {
        SpeechRecognizer.createSpeechRecognizer(application).apply {
            setRecognitionListener(this@SettingsViewModel)
        }
    }

    private fun updateResults(speechBundle: Bundle?) {
        val userSaid = speechBundle?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
        speechState.value = speechState.value.copy(spokenText = userSaid?.get(0) ?: "")
        reactToSpeech(speechState.value.spokenText)
    }

    override fun onEndOfSpeech() = speechRecognizer.stopListening()
    override fun onResults(results: Bundle?) = updateResults(speechBundle = results)
    override fun onPartialResults(results: Bundle?) = updateResults(speechBundle = results)

    override fun onError(errorCode: Int) {}

    private val recognizerIntent: Intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
        putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
        putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, application.packageName)
        putExtra(
            RecognizerIntent.EXTRA_LANGUAGE_MODEL,
            RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH
        )
        putExtra(RecognizerIntent.EXTRA_PROMPT, "Talk")
        //putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
    }

    fun startListening(){
        speechRecognizer.startListening(recognizerIntent)
    }

    private fun reactToSpeech(speech: String){
        when(speech){
            "run" -> Log.w("App", "Running!")
            "stop" -> Log.w("App", "Stopped!")
            else -> {}
        }
    }

    override fun onReadyForSpeech(p0: Bundle?) {}
    override fun onBeginningOfSpeech() {}
    override fun onRmsChanged(p0: Float) {}
    override fun onBufferReceived(p0: ByteArray?) {}
    override fun onEvent(p0: Int, p1: Bundle?) {}
}

额外优化提示

  • 用lazy延迟初始化SpeechRecognizer,避免ViewModel初始化时就持有该对象,减少内存占用风险
  • 注意在ViewModel销毁时(重写onCleared()方法)调用speechRecognizer.destroy(),防止内存泄漏

内容的提问来源于stack exchange,提问作者Alix Blaine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:18:18