Android模拟器中SpeechRecognizer无法使用的问题求助
问题描述
我是Android应用开发新手,正在使用Kotlin开发语音助手。尝试调用麦克风时发现SpeechRecognizer无法工作,已按照指定视频教程操作,也尝试过GitHub上的相关解决方案,但在模拟器中测试时始终提示SpeechRecognizer不可用,SpeechRecognizer.isRecognitionAvailable始终返回不可用状态。
已尝试以下操作:
- 在应用设置中添加所有权限
- 在模拟器设置中启用麦克风
代码文件
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.firstkotlinproject"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.speech.RecognitionService"/> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FirstKotlinProject" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:background="#525252"> <TextView android:id="@+id/textView_to_change" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFA500" android:textSize="24sp" android:text="Hello" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button_to_click" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView_to_change" android:textColor="#FFA500" android:backgroundTint="#000"/> </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
package com.example.firstkotlinproject import android.app.Activity import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.speech.RecognizerIntent import android.speech.SpeechRecognizer import android.widget.Button import android.widget.TextView import android.widget.Toast import kotlinx.android.synthetic.main.activity_main.* import java.util.* import kotlin.collections.ArrayList class MainActivity : AppCompatActivity() { private val requestCodeDefoult = 102 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) button_to_click.setOnClickListener { askSpeechInput() } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == requestCodeDefoult && resultCode == Activity.RESULT_OK) { val result :ArrayList<String>? = data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS) textView_to_change.text = result?.get(0).toString() } } private fun buttonPressed() :Boolean { var result = false if (button_to_click.isPressed) { result = true } return result } private fun askSpeechInput() { if (!SpeechRecognizer.isRecognitionAvailable(this)) { Toast.makeText(this, "Speech recognition is not avaiable!", Toast.LENGTH_SHORT).show() } else if (!buttonPressed()) { Toast.makeText(this, "Press the button to speak", Toast.LENGTH_SHORT).show() } else { val i = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ITALIAN) i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Say something...") startActivity(i) } } }
解决方案
1. 解决模拟器语音识别服务缺失问题
大部分默认Android模拟器(不带Google服务的版本)没有预装语音识别核心服务,导致SpeechRecognizer.isRecognitionAvailable直接返回false。两种解决方式:
- 创建AVD时选择带Google APIs的系统镜像(比如Android 13+的Google APIs x86_64版本)
- 直接用物理设备测试:物理设备基本都预装了语音识别服务,结果更准确
2. 补全动态权限申请
RECORD_AUDIO属于危险权限,仅在Manifest声明不够,必须动态申请。修改MainActivity代码:
private val RECORD_AUDIO_PERMISSION_REQUEST_CODE = 100 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 检查并申请录音权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), RECORD_AUDIO_PERMISSION_REQUEST_CODE) } button_to_click.setOnClickListener { askSpeechInput() } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == RECORD_AUDIO_PERMISSION_REQUEST_CODE) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "权限已授予", Toast.LENGTH_SHORT).show() } else { Toast.makeText(this, "需要录音权限才能使用语音识别", Toast.LENGTH_SHORT).show() } } }
需要补充的import:
import android.Manifest import android.content.pm.PackageManager import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat
3. 修复代码逻辑错误
buttonPressed()判断无效:点击事件触发后,按钮的isPressed状态已经恢复,导致永远进入"Press the button to speak"分支,直接删除该判断。- 替换
startActivity()为startActivityForResult():原来的调用不会触发onActivityResult回调,修改后才能接收识别结果。
修改后的askSpeechInput():
private fun askSpeechInput() { if (!SpeechRecognizer.isRecognitionAvailable(this)) { Toast.makeText(this, "语音识别不可用!", Toast.LENGTH_SHORT).show() } else { // 再次检查权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), RECORD_AUDIO_PERMISSION_REQUEST_CODE) return } val i = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ITALIAN) i.putExtra(RecognizerIntent.EXTRA_PROMPT, "请说话...") startActivityForResult(i, requestCodeDefoult) } }
4. 移除无用权限
android.speech.RecognitionService是服务声明权限,不是应用需要申请的权限,从AndroidManifest.xml中删除这一行:
<uses-permission android:name="android.speech.RecognitionService"/>
内容的提问来源于stack exchange,提问作者Zaitan_jdjd
相关产品推荐
相关产品推荐

