- проверьте журнал, мы видим «SpeechRecouncer start», isListening = true» и «SpeechRecouncer end», но не можем получить текст в input_area. И проверьте, что журнал не наткнулся на onResults;
- А еще самое интересное на BeginningOfSpeech 和onEndOfSpeech не вызывался, поскольку мы не нашли соответствующие журналы,
ps, AudioPermission в порядке.
'''
пакет com.jack_test.call_peter_3.ui.main
импорт android.Manifest
импорт android.content.Intent
импорт android.content.pm.PackageManager
импорт android.os.Bundle
импорт android.speech.RecognitionListener
импорт android.speech.RecouncerIntent
импорт android.speech.SpeechRecouncer
импортировать android.util.Log
импортировать android.view.MotionEvent
импортировать android.widget.Toast
импорт androidx.core.content.ContextCompat
импорт androidx.activity.result.contract.ActivityResultContracts
импорт androidx.activity.viewModels
импорт androidx.appcompat. app.AppCompatActivity
импорт androidx.core.app.ActivityCompat
импорт androidx.recyclerview.widget.LinearLayoutManager
импортировать com.jack_test.call_peter_3.databinding.ActivityMainBinding
импортировать com.jack_test.call_peter_3.ui.chat.ChatAdapter
импортировать com.jack_test.call_peter_3.viewmodel. ChatViewModel
импорт dagger.hilt.android.AndroidEntryPoint
import java.util.*
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {'''Код: Выделить всё
private lateinit var binding: ActivityMainBinding private val viewModel: ChatViewModel by viewModels() // 初始化 ChatAdapter private val chatAdapter: ChatAdapter by lazy { ChatAdapter() } // 声明 SpeechRecognizer private lateinit var speechRecognizer: SpeechRecognizer // 标志位,跟踪是否正在进行语音识别 private var isListening: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 使用 View Binding binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) Log.d("SpeechRecognition", "ViewBinding 初始化完成") // 设置 RecyclerView binding.recyclerViewMessages.apply { layoutManager = LinearLayoutManager(this@MainActivity) adapter = chatAdapter } // 观察 LiveData 中的消息列表 viewModel.messagesLiveData.observe(this) { messages -> chatAdapter.submitList(messages) if (messages.isNotEmpty()) { binding.recyclerViewMessages.scrollToPosition(messages.size - 1) } } // 发送按钮点击事件 binding.buttonSend.setOnClickListener { val message = binding.editTextMessage.text.toString().trim() if (message.isNotEmpty()) { viewModel.sendMessage(message) binding.editTextMessage.text.clear() } else { Toast.makeText(this, "请输入消息", Toast.LENGTH_SHORT).show() } } // 初始化 SpeechRecognizer if (SpeechRecognizer.isRecognitionAvailable(this)) { speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this) Log.d("SpeechRecognition", "SpeechRecognizer 创建成功") speechRecognizer.setRecognitionListener(object : RecognitionListener { override fun onReadyForSpeech(params: Bundle?) { Log.d("SpeechRecognition", "准备开始语音输入") } override fun onBeginningOfSpeech() { Log.d("SpeechRecognition", "开始语音输入") } override fun onRmsChanged(rmsdB: Float) { // 可以用于显示音量变化 } override fun onBufferReceived(buffer: ByteArray?) { // 可以处理接收到的音频缓冲 } override fun onEndOfSpeech() { // 识别结束,重置标志位并启用录音按钮 isListening = false binding.buttonVoiceInput.isEnabled = true updateVoiceInputButton() Log.d("SpeechRecognition", "语音输入结束") } override fun onError(error: Int) { // 处理错误并重置标志位 val errorMessage = when (error) { SpeechRecognizer.ERROR_AUDIO -> "音频问题" SpeechRecognizer.ERROR_CLIENT -> "客户端问题" SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "权限不足" SpeechRecognizer.ERROR_NETWORK -> "网络问题" SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "网络超时" SpeechRecognizer.ERROR_NO_MATCH -> "没有匹配的语音" SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "识别器繁忙,请稍后再试" SpeechRecognizer.ERROR_SERVER -> "服务器错误" SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "语音超时" else -> "未知错误: $error" } Toast.makeText( this@MainActivity, "语音识别错误: $errorMessage", Toast.LENGTH_SHORT ).show() Log.e("SpeechRecognition", "语音识别错误: $errorMessage") // 识别出错,重置标志位并启用录音按钮 isListening = false binding.buttonVoiceInput.isEnabled = true updateVoiceInputButton() } override fun onResults(results: Bundle?) { val recognizedText = results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) ?.firstOrNull() ?: "" Log.d("SpeechRecognition", "识别结果: $recognizedText") if (recognizedText.isNotEmpty()) { binding.editTextMessage.setText(recognizedText) } // 重置标志位并启用录音按钮 isListening = false binding.buttonVoiceInput.isEnabled = true updateVoiceInputButton() } override fun onPartialResults(partialResults: Bundle?) { // 可以处理部分结果 } override fun onEvent(eventType: Int, params: Bundle?) { // 可以处理事件 } }) } else { Toast.makeText(this, "设备不支持语音识别功能", Toast.LENGTH_SHORT).show() Log.e("SpeechRecognition", "设备不支持语音识别功能") } // 语音输入按钮长按事件 binding.buttonVoiceInput.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { Log.d("SpeechRecognition", "录音按钮按下,开始语音识别") if (isAudioPermissionGranted()) { startSpeechRecognition() } else { requestAudioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO) } true } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { Log.d("SpeechRecognition", "录音按钮抬起,停止语音识别") stopSpeechRecognition() true } else -> false } } // 初始化按钮颜色 based on isListening updateVoiceInputButton() } // 检查录音权限 private fun isAudioPermissionGranted(): Boolean { return ActivityCompat.checkSelfPermission( this, Manifest.permission.RECORD_AUDIO ) == PackageManager.PERMISSION_GRANTED } // 注册请求权限的 ActivityResult private val requestAudioPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted -> if (isGranted) { Toast.makeText(this, "录音权限已授予", Toast.LENGTH_SHORT).show() Log.d("SpeechRecognition", "录音权限已授予") startSpeechRecognition() } else { Toast.makeText(this, "需要录音权限才能使用语音输入", Toast.LENGTH_SHORT).show() Log.e("SpeechRecognition", "录音权限被拒绝") } } private fun startSpeechRecognition() { if (!isAudioPermissionGranted()) { requestAudioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO) Log.d("SpeechRecognition", "录音权限未授予,已请求权限") return } if (isListening) { Toast.makeText(this, "识别器正在处理中,请稍后再试", Toast.LENGTH_SHORT).show() Log.d("SpeechRecognition", "识别器正在处理中") return } val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { putExtra( RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM ) putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()) putExtra(RecognizerIntent.EXTRA_PROMPT, "请说出你的消息") } try { Log.d("SpeechRecognition", "尝试启动语音识别") speechRecognizer.startListening(intent) isListening = true // 禁用录音按钮,防止重复点击 //binding.buttonVoiceInput.isEnabled = false updateVoiceInputButton() Log.d("SpeechRecognition", "语音识别已启动,isListening = $isListening") } catch (e: Exception) { Toast.makeText(this, "启动语音识别失败: ${e.message}", Toast.LENGTH_SHORT) .show() Log.e("SpeechRecognition", "启动语音识别失败", e) isListening = false binding.buttonVoiceInput.isEnabled = true updateVoiceInputButton() } } private fun stopSpeechRecognition() { if (isListening) { Log.d("SpeechRecognition", "强制停止语音识别") speechRecognizer.stopListening() isListening = false binding.buttonVoiceInput.isEnabled = true updateVoiceInputButton() // 更新按钮颜色 } } // 更新录音按钮颜色 private fun updateVoiceInputButton() { val color = if (isListening) { ContextCompat.getColor(this, android.R.color.holo_red_light) // 设置红色 } else { ContextCompat.getColor(this, android.R.color.holo_green_light) // 设置绿色 } binding.buttonVoiceInput.setColorFilter(color) } override fun onDestroy() { super.onDestroy() if (::speechRecognizer.isInitialized) { speechRecognizer.destroy() Log.d("SpeechRecognition", "SpeechRecognizer 已销毁") } }
Подробнее здесь: https://stackoverflow.com/questions/793 ... -be-called