问题描述
顾名思义,SpeechRecognizer.isRecognitionAvailable()
在Android 11中返回false,我不确定为什么会这样,因为设备(Pixel 3 XL)可以识别语音。 documentation并不表示它在API v30中已更改。奇怪的是,即使isRecognitionAvailable
为假,我仍然可以成功获得STT提示。下面是说明这一点的示例代码。为什么isRecognitionAvailable检查始终为假?该代码无论如何都不完整,但是我添加了重要的相关部分:
AndroidManifest.xml
...
<uses-permission android:name="android.permission.RECORD_AUdio" />
...
MainActivity.kt
...
override fun onCreate(savedInstanceState: Bundle?) {
...
if(ContextCompat.checkSelfPermission(this,Manifest.permission.RECORD_AUdio) != PackageManager.PERMISSION_GRANTED) {
if(shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUdio)) { //rationale prompt
}
val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()
){ isGranted: Boolean ->
if(isGranted) { checkSTT() }
else { //error perms not granted
}
requestPermissionLauncher.launch(Manifest.permission.RECORD_AUdio)
} else { checkSTT() }
}
private fun checkSTT() {
if(SpeechRecognizer.isRecognitionAvailable(this)) { runSTT() }
else { runSTT() //Run anyway because isRecognitionAvailable is always false and STT works anyway?
}
}
private fun runSTT() {
//Yes,I kNow this is deprecated
val sttIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,Locale.US)
startActivityForResult(sttIntent,1)
}
...
解决方法
我想出了解决方案。由于某些原因,从API v30开始,必须将以下内容添加到清单文件中,SpeechRecognizer.isRecognitionAvailable(Context)
才能返回true。我的测试发现,即使它抱怨“此处不允许元素查询”,它也只能在置于<application>
标记之外时起作用。添加suppress AndroidElementNotAllowed
删除警告。
<!--suppress AndroidElementNotAllowed -->
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
<application...