feat: 新增 42 个 Android API 模块
新增模块覆盖: 系统层 (14): system, security, print, opengl, renderscript, transition, test, service_notification, service_controls, service_quicksettings, service_wallpaper, service_autofill, service_dreams, service_vr 应用层 (13): app_admin, app_backup, app_job, app_usage, app_role, app_people, appwidget, companion, credentials, mtp, sip, telecom, speech 硬件媒体层 (15): hardware_display, hardware_fingerprint, hardware_usb, hardware_input, media_audiofx, media_browse, media_session, media_tv, media_midi, media_projection, uwb, se, view_autofill, view_textclassifier, view_translation 总计 94 个模块,75,342 行代码
This commit is contained in:
1 parent
8ad62be068
commit
506f9ac725
43 files changed
+16704
-23
No files matched your search
@@ -0,0 +1,370 @@
|
||||
"""
|
||||
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__()
|
||||
Reference in new issue
Block a user