SpeechRecognizer.isRecognitionAvailable() 在 Android 11 中始终为假
SpeechRecognizer.isRecognitionAvailable() always false in Android 11
正如标题所暗示的,SpeechRecognizer.isRecognitionAvailable()
returns 在 Android 11 中是错误的,我不确定为什么会这样,因为设备 (Pixel 3 XL) 配备了语音识别功能。 documentation 并不表示它在 API v30 中发生了变化。奇怪的是,即使isRecognitionAvailable
为false,我仍然成功得到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)
到 return 为真。我的测试发现它仅在放置在 <application>
标记之外时才有效,即使它抱怨“此处不允许元素查询”。添加 suppress AndroidElementNotAllowed
以删除警告。
<!--suppress AndroidElementNotAllowed -->
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
<application...
正如标题所暗示的,SpeechRecognizer.isRecognitionAvailable()
returns 在 Android 11 中是错误的,我不确定为什么会这样,因为设备 (Pixel 3 XL) 配备了语音识别功能。 documentation 并不表示它在 API v30 中发生了变化。奇怪的是,即使isRecognitionAvailable
为false,我仍然成功得到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)
到 return 为真。我的测试发现它仅在放置在 <application>
标记之外时才有效,即使它抱怨“此处不允许元素查询”。添加 suppress AndroidElementNotAllowed
以删除警告。
<!--suppress AndroidElementNotAllowed -->
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
<application...