""" Android VoiceInteractor API — VoiceInteractor, Request, Prompt, etc. 方法签名完全对齐 Android SDK """ from __future__ import annotations import uuid from typing import Any, Dict, List, Optional, Tuple, Callable from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) # ═══════════════════════════════════════════════════════════════ # VoiceInteractor # ═══════════════════════════════════════════════════════════════ class VoiceInteractor(Stub): """VoiceInteractor — 语音交互器 (桌面存根)""" # 结果码 RESULT_CANCELED = 0 RESULT_SUCCESS = -1 RESULT_TIMEOUT = -2 RESULT_ERROR = -3 RESULT_NO_MATCH = -4 RESULT_SKIPPED = -5 RESULT_ABORTED = -6 RESULT_UNSUPPORTED = -7 RESULT_BUSY = -8 RESULT_NOT_FOUND = -9 # 语音活动状态 SPEECH_ACTIVITY_UNKNOWN = 0 SPEECH_ACTIVITY_STARTING = 1 SPEECH_ACTIVITY_STARTED = 2 SPEECH_ACTIVITY_STOPPING = 3 SPEECH_ACTIVITY_STOPPED = 4 SPEECH_ACTIVITY_IN_PROGRESS = 5 SPEECH_ACTIVITY_INTERRUPTED = 6 SPEECH_ACTIVITY_TIMED_OUT = 7 SPEECH_ACTIVITY_COMPLETED = 8 SPEECH_ACTIVITY_ERROR = 9 def __init__(self, context: Any = None): super().__init__() self._context = context self._requests: Dict[str, "VoiceInteractor.Request"] = {} self._active_request: Optional["VoiceInteractor.Request"] = None self._speech_activity = VoiceInteractor.SPEECH_ACTIVITY_UNKNOWN self._available = True self._supported_actions: List[str] = [] self._voice_activity_callback: Optional[Callable] = None self._interaction_callback: Optional[Callable] = None self._voice_interaction_service: Optional[Any] = None self._voice_interaction_session: Optional[Any] = None self._system_voice_interaction = False def isVoiceInteraction(self) -> bool: return True def isVoiceInteractionRoot(self) -> bool: return True def notifyVoiceActivity(self, state: int) -> None: self._speech_activity = state if self._voice_activity_callback: self._voice_activity_callback(state) def startVoiceActivity(self, voiceInteractionSession: Any) -> None: pass def setVoiceActivityCallback(self, callback: Callable) -> None: self._voice_activity_callback = callback def getVoiceActivityState(self) -> int: return self._speech_activity def submitRequest(self, request: "VoiceInteractor.Request") -> None: self._submitRequest(request) def submitRequest(self, request: "VoiceInteractor.Request", callback: Any) -> None: request._callback = callback self._submitRequest(request) def _submitRequest(self, request: "VoiceInteractor.Request") -> None: request_id = str(uuid.uuid4()) request._request_id = request_id self._requests[request_id] = request self._active_request = request if request._callback: req = request # 模拟回调 def getActiveRequest(self) -> Optional["VoiceInteractor.Request"]: return self._active_request def cancelRequest(self, request: "VoiceInteractor.Request") -> None: if request._request_id in self._requests: del self._requests[request._request_id] if self._active_request is request: self._active_request = None def cancelRequests(self, requestClass: type = None) -> None: if requestClass: to_remove = [ rid for rid, req in self._requests.items() if isinstance(req, requestClass) ] for rid in to_remove: del self._requests[rid] else: self._requests.clear() if self._active_request and (not requestClass or isinstance(self._active_request, requestClass)): self._active_request = None def getCurrentRequest(self) -> Optional["VoiceInteractor.Request"]: return self._active_request def areNotificationsSupported(self, supportedActions: List[str]) -> bool: return True def startConfirmation(self, prompt: "VoiceInteractor.Prompt", callback: Any) -> None: request = VoiceInteractor.ConfirmationRequest(prompt, None) request._callback = callback self._submitRequest(request) def startPickOption(self, prompts: List["VoiceInteractor.Prompt"], options: List[Any], callback: Any) -> None: request = VoiceInteractor.PickOptionRequest(prompts, options, None) request._callback = callback self._submitRequest(request) def startCommand(self, command: str, callback: Any) -> None: request = VoiceInteractor.CommandRequest(command, None) request._callback = callback self._submitRequest(request) def startCompleteVoice(self, prompt: "VoiceInteractor.Prompt", callback: Any) -> None: request = VoiceInteractor.CompleteVoiceRequest(prompt, None) request._callback = callback self._submitRequest(request) def startAbortVoice(self, prompt: "VoiceInteractor.Prompt", callback: Any) -> None: request = VoiceInteractor.AbortVoiceRequest(prompt, None) request._callback = callback self._submitRequest(request) def getPackageName(self) -> str: return "com.android.voiceinteractor" def getVoiceInteractorService(self) -> Optional[Any]: return self._voice_interaction_service def destroy(self) -> None: self._requests.clear() self._active_request = None self._available = False def toString(self) -> str: return f"VoiceInteractor(active={self._active_request is not None}, requests={len(self._requests)})" # ═══════════════════════════════════════════════════════════ # VoiceInteractor.Request # ═══════════════════════════════════════════════════════════ class Request(Stub): """VoiceInteractor.Request — 请求基类""" def __init__(self): super().__init__() self._request_id: Optional[str] = None self._context: Optional[Any] = None self._callback: Optional[Any] = None self._cancelled = False self._result: Optional[Any] = None self._timeout_ms: Optional[int] = None self._start_time: Optional[float] = None self._activity: Optional[Any] = None self._interactor: Optional["VoiceInteractor"] = None def getRequestId(self) -> Optional[str]: return self._request_id def getActivity(self) -> Optional[Any]: return self._activity def onActivityResult(self, requestCode: int, resultCode: int, data: Any) -> None: pass def onCancel(self) -> None: self._cancelled = True if self._callback and hasattr(self._callback, "onCancel"): self._callback.onCancel(self) def onTimeout(self) -> None: if self._callback and hasattr(self._callback, "onTimeout"): self._callback.onTimeout(self) def isCancelled(self) -> bool: return self._cancelled def getResult(self) -> Optional[Any]: return self._result def cancel(self) -> None: self._cancelled = True def toString(self) -> str: return f"VoiceInteractor.Request(id={self._request_id})" # ═══════════════════════════════════════════════════════════ # VoiceInteractor.Prompt # ═══════════════════════════════════════════════════════════ class Prompt(Stub): """VoiceInteractor.Prompt — 语音提示""" def __init__(self, prompt: Any): super().__init__() if isinstance(prompt, str): self._voice_prompts: List[str] = [prompt] self._visual_prompt: Optional[str] = prompt elif isinstance(prompt, list): self._voice_prompts = list(prompt) self._visual_prompt = prompt[0] if prompt else None elif isinstance(prompt, tuple): self._voice_prompts = [str(p) for p in prompt] self._visual_prompt = str(prompt[0]) if prompt else None else: self._voice_prompts = [str(prompt)] self._visual_prompt = str(prompt) self._count = len(self._voice_prompts) def getVoicePromptAt(self, index: int) -> Optional[str]: if 0 <= index < self._count: return self._voice_prompts[index] return None def getVisualPrompt(self) -> Optional[str]: return self._visual_prompt def countVoicePrompts(self) -> int: return self._count def toString(self) -> str: return f"VoiceInteractor.Prompt(voice_prompts={self._count})" # ═══════════════════════════════════════════════════════════ # VoiceInteractor.CompleteVoiceRequest # ═══════════════════════════════════════════════════════════ class CompleteVoiceRequest(Request): """VoiceInteractor.CompleteVoiceRequest — 完成语音请求""" def __init__(self, prompt: "VoiceInteractor.Prompt", bundle: Any = None): super().__init__() self._prompt = prompt self._bundle = bundle self._result_code = VoiceInteractor.RESULT_SUCCESS self._result_data: Optional[Any] = None def getPrompt(self) -> Optional["VoiceInteractor.Prompt"]: return self._prompt def getBundle(self) -> Optional[Any]: return self._bundle def setResult(self, resultCode: int, result: Any) -> None: self._result_code = resultCode self._result_data = result def toString(self) -> str: return f"CompleteVoiceRequest(prompt={self._prompt})" # ═══════════════════════════════════════════════════════════ # VoiceInteractor.AbortVoiceRequest # ═══════════════════════════════════════════════════════════ class AbortVoiceRequest(Request): """VoiceInteractor.AbortVoiceRequest — 中止语音请求""" def __init__(self, prompt: "VoiceInteractor.Prompt", bundle: Any = None): super().__init__() self._prompt = prompt self._bundle = bundle self._result_code = VoiceInteractor.RESULT_ABORTED self._reason: Optional[str] = None def getPrompt(self) -> Optional["VoiceInteractor.Prompt"]: return self._prompt def getBundle(self) -> Optional[Any]: return self._bundle def getReason(self) -> Optional[str]: return self._reason def setAbortReason(self, reason: str) -> None: self._reason = reason def toString(self) -> str: return f"AbortVoiceRequest(prompt={self._prompt}, reason={self._reason})" # ═══════════════════════════════════════════════════════════ # VoiceInteractor.CommandRequest # ═══════════════════════════════════════════════════════════ class CommandRequest(Request): """VoiceInteractor.CommandRequest — 命令请求""" def __init__(self, command: str, bundle: Any = None): super().__init__() self._command = command self._bundle = bundle self._result_code = VoiceInteractor.RESULT_SUCCESS self._result_data: Optional[Any] = None def getCommand(self) -> str: return self._command def getBundle(self) -> Optional[Any]: return self._bundle def setResult(self, resultCode: int, result: Any) -> None: self._result_code = resultCode self._result_data = result def getResultCode(self) -> int: return self._result_code def getResultData(self) -> Optional[Any]: return self._result_data def onCommandResult(self, isCompleted: bool, result: Any) -> None: if self._callback and hasattr(self._callback, "onCommandResult"): self._callback.onCommandResult(isCompleted, result) def toString(self) -> str: return f"CommandRequest(command={self._command})" # ═══════════════════════════════════════════════════════════ # VoiceInteractor.PickOptionRequest # ═══════════════════════════════════════════════════════════ class PickOptionRequest(Request): """VoiceInteractor.PickOptionRequest — 选项选择请求""" class Option(Stub): """PickOptionRequest.Option — 选项""" def __init__(self, label: str, index: int = -1): super().__init__() self._label = label self._index = index self._synonyms: List[str] = [] self._extras: Optional[Any] = None self._is_selected = False def getLabel(self) -> str: return self._label def getIndex(self) -> int: return self._index def setIndex(self, index: int) -> None: self._index = index def addSynonym(self, synonym: str) -> None: self._synonyms.append(synonym) def getSynonyms(self) -> List[str]: return list(self._synonyms) def setExtras(self, extras: Any) -> None: self._extras = extras def getExtras(self) -> Optional[Any]: return self._extras def isSelected(self) -> bool: return self._is_selected def toString(self) -> str: return f"Option(label={self._label}, index={self._index})" def __init__(self, prompts: Any, options: List[Any], bundle: Any = None): super().__init__() if isinstance(prompts, VoiceInteractor.Prompt): self._prompts = [prompts] elif isinstance(prompts, list): self._prompts = prompts else: self._prompts = [VoiceInteractor.Prompt(str(prompts))] self._options = options self._bundle = bundle self._selected_option: Optional[Any] = None self._result_code = VoiceInteractor.RESULT_SUCCESS def getPrompts(self) -> List["VoiceInteractor.Prompt"]: return list(self._prompts) def getOptions(self) -> List[Any]: return list(self._options) def getBundle(self) -> Optional[Any]: return self._bundle def getSelectedOption(self) -> Optional[Any]: return self._selected_option def setPickOptionResult(self, option: Any, result: Any) -> None: self._selected_option = option self._result_data = result self._result_code = VoiceInteractor.RESULT_SUCCESS def onPickOptionResult(self, completed: bool, option: Any, result: Any) -> None: if completed: self._selected_option = option if self._callback and hasattr(self._callback, "onPickOptionResult"): self._callback.onPickOptionResult(completed, option, result) def toString(self) -> str: return f"PickOptionRequest(options={len(self._options)})" # ═══════════════════════════════════════════════════════════ # VoiceInteractor.ConfirmationRequest # ═══════════════════════════════════════════════════════════ class ConfirmationRequest(Request): """VoiceInteractor.ConfirmationRequest — 确认请求""" def __init__(self, prompt: "VoiceInteractor.Prompt", bundle: Any = None): super().__init__() self._prompt = prompt self._bundle = bundle self._confirmed = False self._result_code = VoiceInteractor.RESULT_SUCCESS self._result_data: Optional[Any] = None def getPrompt(self) -> Optional["VoiceInteractor.Prompt"]: return self._prompt def getBundle(self) -> Optional[Any]: return self._bundle def isConfirmed(self) -> bool: return self._confirmed def setConfirmationResult(self, confirmed: bool, result: Any) -> None: self._confirmed = confirmed self._result_data = result self._result_code = VoiceInteractor.RESULT_SUCCESS if confirmed else VoiceInteractor.RESULT_CANCELED def onConfirmationResult(self, confirmed: bool, result: Any) -> None: self._confirmed = confirmed if self._callback and hasattr(self._callback, "onConfirmationResult"): self._callback.onConfirmationResult(confirmed, result) def toString(self) -> str: return f"ConfirmationRequest(confirmed={self._confirmed})" # ═══════════════════════════════════════════════════════════════ # VoiceInteractor 扩展功能 # ═══════════════════════════════════════════════════════════════ class VoiceInteractorResult(Stub): """VoiceInteractor.Result — 语音交互结果""" def __init__(self, resultCode: int = VoiceInteractor.RESULT_SUCCESS, resultData: Any = None): super().__init__() self._result_code = resultCode self._result_data = resultData self._timed_out = False self._cancelled = False self._error_message: Optional[str] = None def getResultCode(self) -> int: return self._result_code def getResultData(self) -> Optional[Any]: return self._result_data def getErrorMessage(self) -> Optional[str]: return self._error_message def isTimedOut(self) -> bool: return self._timed_out def isCancelled(self) -> bool: return self._cancelled def isSuccess(self) -> bool: return self._result_code == VoiceInteractor.RESULT_SUCCESS def toString(self) -> str: return f"VoiceInteractorResult(code={self._result_code})" class VoiceInteractorCallback(Stub): """VoiceInteractor.Callback — 语音交互回调基类""" def __init__(self): super().__init__() def onRequestSuccess(self, request: VoiceInteractor.Request) -> None: pass def onRequestFailure(self, request: VoiceInteractor.Request) -> None: pass def onRequestCancelled(self, request: VoiceInteractor.Request) -> None: pass def onRequestTimeout(self, request: VoiceInteractor.Request) -> None: pass def toString(self) -> str: return "VoiceInteractor.Callback" class VoiceInteractorNotification(Stub): """VoiceInteractor.Notifications — 语音交互通知支持""" def __init__(self): super().__init__() self._supported_actions: List[str] = [] self._notification_channel_id: Optional[str] = None self._notification_title: Optional[str] = None self._notification_text: Optional[str] = None def getSupportedActions(self) -> List[str]: return list(self._supported_actions) def isActionSupported(self, action: str) -> bool: return action in self._supported_actions def setNotificationChannel(self, channelId: str) -> None: self._notification_channel_id = channelId def getNotificationChannel(self) -> Optional[str]: return self._notification_channel_id def toString(self) -> str: return f"VoiceInteractorNotifications(actions={len(self._supported_actions)})" class VoiceInteractorSession(Stub): """VoiceInteractor.Session — 语音交互会话""" def __init__(self, interactor: "VoiceInteractor"): super().__init__() self._interactor = interactor self._session_id = str(uuid.uuid4()) self._active = False self._start_time = time.time() self._requests: List[VoiceInteractor.Request] = [] self._current_prompt: Optional[VoiceInteractor.Prompt] = None self._state = VoiceInteractor.SPEECH_ACTIVITY_UNKNOWN def getSessionId(self) -> str: return self._session_id def isActive(self) -> bool: return self._active def start(self) -> None: self._active = True self._state = VoiceInteractor.SPEECH_ACTIVITY_STARTING def stop(self) -> None: self._active = False self._state = VoiceInteractor.SPEECH_ACTIVITY_STOPPED def getDuration(self) -> float: if self._active: return time.time() - self._start_time return 0.0 def getState(self) -> int: return self._state def getRequestCount(self) -> int: return len(self._requests) def toString(self) -> str: return f"VoiceInteractorSession(active={self._active}, state={self._state})"