""" Android Speech API — SpeechRecognizer, RecognitionListener, RecognitionService, RecognizerIntent 方法签名完全对齐 Android SDK """ import sys import threading import time from typing import Any, Dict, List, Optional, Set, Tuple, Callable from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) __all__ = [ "SpeechRecognizer", "RecognitionListener", "RecognitionService", "RecognizerIntent", "RecognizerResultsIntent", ] # ═══════════════════════════════════════════════════════════════ # SpeechRecognizer # ═══════════════════════════════════════════════════════════════ class SpeechRecognizer(Stub): """SpeechRecognizer — 语音识别器 (桌面麦克风模拟)""" RESULTS_RECOGNITION = "results_recognition" CONFIDENCE_SCORES = "confidence_scores" ERROR_NETWORK_TIMEOUT = 1 ERROR_NETWORK = 2 ERROR_AUDIO = 3 ERROR_SERVER = 4 ERROR_CLIENT = 5 ERROR_SPEECH_TIMEOUT = 6 ERROR_NO_MATCH = 7 ERROR_RECOGNIZER_BUSY = 8 ERROR_INSUFFICIENT_PERMISSIONS = 9 ERROR_TOO_MANY_REQUESTS = 10 ERROR_LANGUAGE_NOT_SUPPORTED = 11 ERROR_LANGUAGE_UNAVAILABLE = 12 ERROR_SERVER_DISCONNECTED = 13 def __init__(self, context: Any = None): super().__init__() self._context = context self._listener: Optional["RecognitionListener"] = None self._is_listening = False self._destroyed = False self._simulate_timer: Optional[threading.Timer] = None @staticmethod def createSpeechRecognizer(context: Any) -> "SpeechRecognizer": """创建语音识别器""" return SpeechRecognizer(context) @staticmethod def isRecognitionAvailable(context: Any) -> bool: """检查语音识别是否可用""" try: import speech_recognition as sr return True except ImportError: try: import whisper # noqa: F401 return True except ImportError: pass return False def setRecognitionListener(self, listener: "RecognitionListener"): """设置识别监听器""" self._listener = listener def startListening(self, intent: Any): """开始语音识别""" if self._destroyed: return self._is_listening = True # 使用简单识别模拟 if self._listener: self._listener.onReadyForSpeech(None) self._listener.onBeginningOfSpeech() # 模拟麦克风音量变化 for i in range(3): self._listener.onRmsChanged(5.0 + i * 2.0) time.sleep(0.05) self._listener.onBufferReceived(bytearray(1024)) self._listener.onEndOfSpeech() # 模拟识别结果 results = {self.RESULTS_RECOGNITION: ["hello world"], self.CONFIDENCE_SCORES: [0.95]} self._listener.onResults(results) def stopListening(self): """停止语音识别""" self._is_listening = False if self._simulate_timer: self._simulate_timer.cancel() self._simulate_timer = None def cancel(self): """取消语音识别""" self._is_listening = False if self._simulate_timer: self._simulate_timer.cancel() self._simulate_timer = None if self._listener: self._listener.onError(self.ERROR_NO_MATCH) def destroy(self): """销毁语音识别器""" self._destroyed = True self._is_listening = False if self._simulate_timer: self._simulate_timer.cancel() self._simulate_timer = None self._listener = None def toString(self) -> str: return f"SpeechRecognizer(listening={self._is_listening})" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════════ # RecognitionListener # ═══════════════════════════════════════════════════════════════ class RecognitionListener(Stub): """RecognitionListener — 语音识别监听器""" def __init__(self): super().__init__() def onReadyForSpeech(self, params: Any): """准备开始语音识别回调""" pass def onBeginningOfSpeech(self): """开始说话回调""" pass def onRmsChanged(self, rmsdB: float): """音量变化回调""" pass def onBufferReceived(self, buffer: bytearray): """接收音频缓冲区回调""" pass def onEndOfSpeech(self): """说话结束回调""" pass def onError(self, error: int): """错误回调""" pass def onResults(self, results: Dict[str, Any]): """识别结果回调""" pass def onPartialResults(self, partialResults: Dict[str, Any]): """部分识别结果回调""" pass def onSegmentResults(self, segmentResults: Dict[str, Any]): """分段结果回调""" pass def onEndOfSegmentedSession(self, sessionId: int): """分段会话结束回调""" pass def onLanguageDetection(self, language: str): """语言检测回调""" pass def onEvent(self, eventType: int, params: Any): """事件回调""" pass def toString(self) -> str: return f"RecognitionListener@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════════ # RecognitionService # ═══════════════════════════════════════════════════════════════ class RecognitionService(Stub): """RecognitionService — 语音识别服务""" SERVICE_INTERFACE = "android.speech.RecognitionService" SERVICE_META_DATA = "android.speech" def __init__(self): super().__init__() self._callback: Optional["RecognitionService.Callback"] = None def onStartListening(self, intent: Any, listener: "RecognitionService.Callback"): """开始监听回调""" pass def onCancel(self, listener: "RecognitionService.Callback"): """取消回调""" pass def onStopListening(self, listener: "RecognitionService.Callback"): """停止监听回调""" pass def onDestroy(self): """销毁回调""" pass def oneShotListening(self, intent: Any, listener: "RecognitionService.Callback"): """一次性监听""" if listener: listener.readyForSpeech(None) listener.beginningOfSpeech() listener.endOfSpeech() results = {SpeechRecognizer.RESULTS_RECOGNITION: ["hello"]} listener.results(results) def getCurrentCallback(self) -> Optional["RecognitionService.Callback"]: return self._callback # ═══════════════════════════════════════════════════════════ # Callback # ═══════════════════════════════════════════════════════════ class Callback(Stub): """RecognitionService.Callback — 识别服务回调""" def __init__(self): super().__init__() def results(self, results: Dict[str, Any]): """返回识别结果""" pass def partialResults(self, partialResults: Dict[str, Any]): """返回部分结果""" pass def error(self, error: int): """返回错误""" pass def beginningOfSpeech(self): """开始说话回调""" pass def bufferReceived(self, buffer: bytearray): """接收音频缓冲区回调""" pass def endOfSpeech(self): """说话结束回调""" pass def readyForSpeech(self, params: Any): """准备开始语音识别""" pass def rmsChanged(self, rmsdB: float): """音量变化回调""" pass def toString(self) -> str: return f"RecognitionService.Callback@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF def toString(self) -> str: return f"RecognitionService@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════════ # RecognizerIntent # ═══════════════════════════════════════════════════════════════ class RecognizerIntent(Stub): """RecognizerIntent — 识别器 Intent 常量""" ACTION_RECOGNIZE_SPEECH = "android.speech.action.RECOGNIZE_SPEECH" ACTION_WEB_SEARCH = "android.speech.action.WEB_SEARCH" ACTION_VOICE_SEARCH_HANDS_FREE = "android.speech.action.VOICE_SEARCH_HANDS_FREE" ACTION_GET_LANGUAGE_DETAILS = "android.speech.action.GET_LANGUAGE_DETAILS" EXTRA_LANGUAGE_MODEL = "android.speech.extra.LANGUAGE_MODEL" EXTRA_LANGUAGE = "android.speech.extra.LANGUAGE" EXTRA_MAX_RESULTS = "android.speech.extra.MAX_RESULTS" EXTRA_PARTIAL_RESULTS = "android.speech.extra.PARTIAL_RESULTS" EXTRA_CALLING_PACKAGE = "android.speech.extra.CALLING_PACKAGE" EXTRA_PROMPT = "android.speech.extra.PROMPT" EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS = "android.speech.extra.SPEECH_INPUT_MINIMUM_LENGTH_MILLIS" EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS = "android.speech.extra.SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS" EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS = "android.speech.extra.SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS" EXTRA_CONFIDENCE_SCORES = "android.speech.extra.CONFIDENCE_SCORES" EXTRA_RESULTS = "android.speech.extra.RESULTS" EXTRA_SECURE = "android.speech.extra.SECURE" EXTRA_SUPPORTED_LANGUAGES = "android.speech.extra.SUPPORTED_LANGUAGES" EXTRA_LANGUAGE_PREFERENCE = "android.speech.extra.LANGUAGE_PREFERENCE" EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE = "android.speech.extra.ONLY_RETURN_LANGUAGE_PREFERENCE" EXTRA_LANGUAGE_DETAILS = "android.speech.extra.LANGUAGE_DETAILS" LANGUAGE_MODEL_FREE_FORM = "free_form" LANGUAGE_MODEL_WEB_SEARCH = "web_search" RESULT_AUDIO_ERROR = 1 RESULT_CLIENT_ERROR = 2 RESULT_NETWORK_ERROR = 3 RESULT_SERVER_ERROR = 4 RESULT_NO_MATCH = 5 DETAIL_META_DATA = "android.speech.DETAIL_META_DATA" def __init__(self): super().__init__() # ═══════════════════════════════════════════════════════════════ # RecognizerResultsIntent # ═══════════════════════════════════════════════════════════════ class RecognizerResultsIntent(Stub): """RecognizerResultsIntent — 识别结果 Intent 常量""" ACTION_VOICE_SEARCH_RESULTS = "android.speech.action.VOICE_SEARCH_RESULTS" EXTRA_VOICE_SEARCH_RESULT_STRINGS = "android.speech.extra.VOICE_SEARCH_RESULT_STRINGS" EXTRA_VOICE_SEARCH_RESULT_URLS = "android.speech.extra.VOICE_SEARCH_RESULT_URLS" EXTRA_VOICE_SEARCH_RESULT_HTML = "android.speech.extra.VOICE_SEARCH_RESULT_HTML" EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS = "android.speech.extra.VOICE_SEARCH_RESULT_HTML_BASE_URLS" URI_SCHEME_INLINE = "inline" def __init__(self): super().__init__()