- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
744 lines
24 KiB
Python
744 lines
24 KiB
Python
"""
|
|
Android View Accessibility 扩展组件
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
import threading
|
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from ..java.lang import RuntimeException
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 无障碍事件常量
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
TYPE_VIEW_CLICKED = 0x00000001
|
|
TYPE_VIEW_LONG_CLICKED = 0x00000002
|
|
TYPE_VIEW_SELECTED = 0x00000004
|
|
TYPE_VIEW_FOCUSED = 0x00000008
|
|
TYPE_VIEW_TEXT_CHANGED = 0x00000010
|
|
TYPE_WINDOW_STATE_CHANGED = 0x00000020
|
|
TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040
|
|
TYPE_VIEW_HOVER_ENTER = 0x00000080
|
|
TYPE_VIEW_HOVER_EXIT = 0x00000100
|
|
TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200
|
|
TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400
|
|
TYPE_WINDOW_CONTENT_CHANGED = 0x00000800
|
|
TYPE_VIEW_SCROLLED = 0x00001000
|
|
TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000
|
|
TYPE_ANNOUNCEMENT = 0x00004000
|
|
TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000
|
|
TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000
|
|
TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000
|
|
TYPE_GESTURE_DETECTION_START = 0x00040000
|
|
TYPE_GESTURE_DETECTION_END = 0x00080000
|
|
TYPE_TOUCH_INTERACTION_START = 0x00100000
|
|
TYPE_TOUCH_INTERACTION_END = 0x00200000
|
|
TYPE_WINDOWS_CHANGED = 0x00400000
|
|
TYPE_VIEW_CONTEXT_CLICKED = 0x00800000
|
|
TYPE_ASSIST_READING_CONTEXT = 0x01000000
|
|
|
|
CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000001
|
|
CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 0x00000002
|
|
CONTENT_CHANGE_TYPE_SUBTREE = 0x00000004
|
|
CONTENT_CHANGE_TYPE_TEXT = 0x00000008
|
|
CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000010
|
|
|
|
WINDOWS_CHANGE_ADDED = 0x00000001
|
|
WINDOWS_CHANGE_REMOVED = 0x00000002
|
|
WINDOWS_CHANGE_TITLE = 0x00000004
|
|
WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 0x00000008
|
|
WINDOWS_CHANGE_ACTIVE = 0x00000010
|
|
WINDOWS_CHANGE_PARENT = 0x00000020
|
|
WINDOWS_CHANGE_CHILDREN = 0x00000040
|
|
WINDOWS_CHANGE_BOUNDS = 0x00000080
|
|
WINDOWS_CHANGE_LAYER = 0x00000100
|
|
|
|
WINDOW_TYPE_ACCESSIBILITY_OVERLAY = 4
|
|
WINDOW_TYPE_APPLICATION = 1
|
|
WINDOW_TYPE_INPUT_METHOD = 2
|
|
WINDOW_TYPE_SPLIT_SCREEN_DIVIDER = 5
|
|
WINDOW_TYPE_SYSTEM = 3
|
|
|
|
FLAG_REPORT_VIEW_IDS = 0x10
|
|
FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x80
|
|
FLAG_REQUEST_FILTER_KEY_EVENTS = 0x20
|
|
FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x40
|
|
FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x08
|
|
FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x02
|
|
FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x100
|
|
|
|
CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1
|
|
CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2
|
|
CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4
|
|
CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 8
|
|
|
|
CAPTIONING_TYPE_UNKNOWN = -1
|
|
CAPTIONING_TYPE_FEATURE = 0
|
|
CAPTIONING_TYPE_COUNTRY = 1
|
|
CAPTIONING_TYPE_SPOKEN = 2
|
|
CAPTIONING_TYPE_UNKNOWN_CHARACTER = 3
|
|
CAPTIONING_TYPE_MUSIC = 4
|
|
CAPTIONING_TYPE_SFX = 5
|
|
CAPTIONING_TYPE_VOICE = 6
|
|
|
|
CAPTIONING_PRESET_INVALID = -1
|
|
CAPTIONING_PRESET_CUSTOM = 0
|
|
CAPTIONING_PRESET_WHITE_ON_BLACK = 1
|
|
CAPTIONING_PRESET_BLACK_ON_WHITE = 2
|
|
CAPTIONING_PRESET_YELLOW_ON_BLACK = 3
|
|
CAPTIONING_PRESET_YELLOW_ON_BLUE = 4
|
|
CAPTIONING_PRESET_CUSTOM_BLACK_ON_WHITE = 5
|
|
CAPTIONING_PRESET_CUSTOM_WHITE_ON_BLACK = 6
|
|
CAPTIONING_PRESET_CUSTOM_YELLOW_ON_BLACK = 7
|
|
CAPTIONING_PRESET_CUSTOM_YELLOW_ON_BLUE = 8
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AccessibilityEvent
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AccessibilityRecord(Stub):
|
|
"""AccessibilityRecord — 无障碍记录"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._source_view: Optional[Any] = None
|
|
self._source_node_id: int = -1
|
|
self._source_window_id: int = -1
|
|
self._event_time: int = 0
|
|
self._package_name: Optional[str] = None
|
|
self._class_name: Optional[str] = None
|
|
self._text: List[str] = []
|
|
self._content_description: Optional[str] = None
|
|
self._item_count: int = -1
|
|
self._current_item_index: int = -1
|
|
self._from_index: int = -1
|
|
self._to_index: int = -1
|
|
self._scrollable: bool = False
|
|
self._password: bool = False
|
|
self._checked: bool = False
|
|
self._enabled: bool = True
|
|
self._clickable: bool = False
|
|
self._focusable: bool = False
|
|
self._focused: bool = False
|
|
self._long_clickable: bool = False
|
|
self._selected: bool = False
|
|
self._pass_through: bool = False
|
|
self._before_text: Optional[str] = None
|
|
self._removed_count: int = 0
|
|
self._added_count: int = 0
|
|
self._max_scroll_x: int = -1
|
|
self._max_scroll_y: int = -1
|
|
self._scroll_x: int = -1
|
|
self._scroll_y: int = -1
|
|
|
|
def setSource(self, view: Any) -> None:
|
|
self._source_view = view
|
|
|
|
def getSource(self) -> Optional[Any]:
|
|
return self._source_view
|
|
|
|
def setSourceNodeId(self, node_id: int) -> None:
|
|
self._source_node_id = node_id
|
|
|
|
def getSourceNodeId(self) -> int:
|
|
return self._source_node_id
|
|
|
|
def setWindowId(self, window_id: int) -> None:
|
|
self._source_window_id = window_id
|
|
|
|
def getWindowId(self) -> int:
|
|
return self._source_window_id
|
|
|
|
def setEventTime(self, time: int) -> None:
|
|
self._event_time = time
|
|
|
|
def getEventTime(self) -> int:
|
|
return self._event_time if self._event_time else int(time.time() * 1000)
|
|
|
|
def setPackageName(self, name: str) -> None:
|
|
self._package_name = name
|
|
|
|
def getPackageName(self) -> Optional[str]:
|
|
return self._package_name
|
|
|
|
def setClassName(self, name: str) -> None:
|
|
self._class_name = name
|
|
|
|
def getClassName(self) -> Optional[str]:
|
|
return self._class_name
|
|
|
|
def setText(self, text: List[str]) -> None:
|
|
self._text = list(text)
|
|
|
|
def getText(self) -> List[str]:
|
|
return list(self._text)
|
|
|
|
def setContentDescription(self, desc: str) -> None:
|
|
self._content_description = desc
|
|
|
|
def getContentDescription(self) -> Optional[str]:
|
|
return self._content_description
|
|
|
|
def setItemCount(self, count: int) -> None:
|
|
self._item_count = count
|
|
|
|
def getItemCount(self) -> int:
|
|
return self._item_count
|
|
|
|
def setCurrentItemIndex(self, index: int) -> None:
|
|
self._current_item_index = index
|
|
|
|
def getCurrentItemIndex(self) -> int:
|
|
return self._current_item_index
|
|
|
|
def setFromIndex(self, index: int) -> None:
|
|
self._from_index = index
|
|
|
|
def getFromIndex(self) -> int:
|
|
return self._from_index
|
|
|
|
def setToIndex(self, index: int) -> None:
|
|
self._to_index = index
|
|
|
|
def getToIndex(self) -> int:
|
|
return self._to_index
|
|
|
|
def setScrollable(self, scrollable: bool) -> None:
|
|
self._scrollable = scrollable
|
|
|
|
def isScrollable(self) -> bool:
|
|
return self._scrollable
|
|
|
|
def setPassword(self, password: bool) -> None:
|
|
self._password = password
|
|
|
|
def isPassword(self) -> bool:
|
|
return self._password
|
|
|
|
def setChecked(self, checked: bool) -> None:
|
|
self._checked = checked
|
|
|
|
def isChecked(self) -> bool:
|
|
return self._checked
|
|
|
|
def setEnabled(self, enabled: bool) -> None:
|
|
self._enabled = enabled
|
|
|
|
def isEnabled(self) -> bool:
|
|
return self._enabled
|
|
|
|
def setClickable(self, clickable: bool) -> None:
|
|
self._clickable = clickable
|
|
|
|
def isClickable(self) -> bool:
|
|
return self._clickable
|
|
|
|
def setFocusable(self, focusable: bool) -> None:
|
|
self._focusable = focusable
|
|
|
|
def isFocusable(self) -> bool:
|
|
return self._focusable
|
|
|
|
def setFocused(self, focused: bool) -> None:
|
|
self._focused = focused
|
|
|
|
def isFocused(self) -> bool:
|
|
return self._focused
|
|
|
|
def setLongClickable(self, long_clickable: bool) -> None:
|
|
self._long_clickable = long_clickable
|
|
|
|
def isLongClickable(self) -> bool:
|
|
return self._long_clickable
|
|
|
|
def setSelected(self, selected: bool) -> None:
|
|
self._selected = selected
|
|
|
|
def isSelected(self) -> bool:
|
|
return self._selected
|
|
|
|
def setBeforeText(self, text: str) -> None:
|
|
self._before_text = text
|
|
|
|
def getBeforeText(self) -> Optional[str]:
|
|
return self._before_text
|
|
|
|
def setRemovedCount(self, count: int) -> None:
|
|
self._removed_count = count
|
|
|
|
def getRemovedCount(self) -> int:
|
|
return self._removed_count
|
|
|
|
def setAddedCount(self, count: int) -> None:
|
|
self._added_count = count
|
|
|
|
def getAddedCount(self) -> int:
|
|
return self._added_count
|
|
|
|
def setMaxScrollX(self, max_x: int) -> None:
|
|
self._max_scroll_x = max_x
|
|
|
|
def getMaxScrollX(self) -> int:
|
|
return self._max_scroll_x
|
|
|
|
def setMaxScrollY(self, max_y: int) -> None:
|
|
self._max_scroll_y = max_y
|
|
|
|
def getMaxScrollY(self) -> int:
|
|
return self._max_scroll_y
|
|
|
|
def setScrollX(self, x: int) -> None:
|
|
self._scroll_x = x
|
|
|
|
def getScrollX(self) -> int:
|
|
return self._scroll_x
|
|
|
|
def setScrollY(self, y: int) -> None:
|
|
self._scroll_y = y
|
|
|
|
def getScrollY(self) -> int:
|
|
return self._scroll_y
|
|
|
|
def toString(self) -> str:
|
|
return (f"AccessibilityRecord(class={self._class_name}, "
|
|
f"text={self._text})")
|
|
|
|
|
|
class AccessibilityEvent(AccessibilityRecord):
|
|
"""AccessibilityEvent — 无障碍事件"""
|
|
|
|
INVALID_POSITION = -1
|
|
MAX_TEXT_LENGTH = 500
|
|
|
|
def __init__(self, event_type: int = 0):
|
|
super().__init__()
|
|
self._event_type = event_type
|
|
self._event_type_int = event_type
|
|
self._movement_granularity: int = 0
|
|
self._action: int = 0
|
|
self._content_change_types: int = 0
|
|
self._window_changes: int = 0
|
|
|
|
@staticmethod
|
|
def obtain(event_type: int = 0) -> "AccessibilityEvent":
|
|
return AccessibilityEvent(event_type)
|
|
|
|
@staticmethod
|
|
def obtain(event: "AccessibilityEvent") -> "AccessibilityEvent":
|
|
e = AccessibilityEvent(event.getEventType())
|
|
return e
|
|
|
|
def getEventType(self) -> int:
|
|
return self._event_type
|
|
|
|
def setEventType(self, event_type: int) -> None:
|
|
self._event_type = event_type
|
|
|
|
def setMovementGranularity(self, granularity: int) -> None:
|
|
self._movement_granularity = granularity
|
|
|
|
def getMovementGranularity(self) -> int:
|
|
return self._movement_granularity
|
|
|
|
def setAction(self, action: int) -> None:
|
|
self._action = action
|
|
|
|
def getAction(self) -> int:
|
|
return self._action
|
|
|
|
def setContentChangeTypes(self, types: int) -> None:
|
|
self._content_change_types = types
|
|
|
|
def getContentChangeTypes(self) -> int:
|
|
return self._content_change_types
|
|
|
|
def setWindowChanges(self, changes: int) -> None:
|
|
self._window_changes = changes
|
|
|
|
def getWindowChanges(self) -> int:
|
|
return self._window_changes
|
|
|
|
def recycle(self) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"AccessibilityEvent(type={self._event_type})"
|
|
|
|
|
|
class AccessibilityWindowInfo(Stub):
|
|
"""AccessibilityWindowInfo — 无障碍窗口信息"""
|
|
|
|
TYPE_ACCESSIBILITY_OVERLAY = WINDOW_TYPE_ACCESSIBILITY_OVERLAY
|
|
TYPE_APPLICATION = WINDOW_TYPE_APPLICATION
|
|
TYPE_INPUT_METHOD = WINDOW_TYPE_INPUT_METHOD
|
|
TYPE_SPLIT_SCREEN_DIVIDER = WINDOW_TYPE_SPLIT_SCREEN_DIVIDER
|
|
TYPE_SYSTEM = WINDOW_TYPE_SYSTEM
|
|
|
|
UNDEFINED = -1
|
|
ACTIVE = 0
|
|
INACTIVE = 1
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._type: int = self.TYPE_APPLICATION
|
|
self._id: int = -1
|
|
self._layer: int = 0
|
|
self._is_active = False
|
|
self._is_focused = False
|
|
self._is_accessibility_focused = False
|
|
self._title: Optional[str] = None
|
|
self._root: Optional[Any] = None
|
|
self._parent: Optional["AccessibilityWindowInfo"] = None
|
|
self._bounds: Tuple[int, int, int, int] = (0, 0, 0, 0)
|
|
self._anchor: Optional[Any] = None
|
|
self._picture_in_picture = False
|
|
self._first_child: Optional["AccessibilityWindowInfo"] = None
|
|
self._last_child: Optional["AccessibilityWindowInfo"] = None
|
|
self._child_count: int = 0
|
|
|
|
def getType(self) -> int:
|
|
return self._type
|
|
|
|
def setType(self, type_val: int) -> None:
|
|
self._type = type_val
|
|
|
|
def getId(self) -> int:
|
|
return self._id
|
|
|
|
def setId(self, id_val: int) -> None:
|
|
self._id = id_val
|
|
|
|
def setLayer(self, layer: int) -> None:
|
|
self._layer = layer
|
|
|
|
def getLayer(self) -> int:
|
|
return self._layer
|
|
|
|
def isActive(self) -> bool:
|
|
return self._is_active
|
|
|
|
def setActive(self, active: bool) -> None:
|
|
self._is_active = active
|
|
|
|
def isFocused(self) -> bool:
|
|
return self._is_focused
|
|
|
|
def setFocused(self, focused: bool) -> None:
|
|
self._is_focused = focused
|
|
|
|
def isAccessibilityFocused(self) -> bool:
|
|
return self._is_accessibility_focused
|
|
|
|
def setAccessibilityFocused(self, focused: bool) -> None:
|
|
self._is_accessibility_focused = focused
|
|
|
|
def getTitle(self) -> Optional[str]:
|
|
return self._title
|
|
|
|
def setTitle(self, title: str) -> None:
|
|
self._title = title
|
|
|
|
def setBoundsInScreen(self, bounds: Tuple[int, int, int, int]) -> None:
|
|
self._bounds = bounds
|
|
|
|
def getBoundsInScreen(self) -> Tuple[int, int, int, int]:
|
|
return self._bounds
|
|
|
|
def setAnchorId(self, anchor: Any) -> None:
|
|
self._anchor = anchor
|
|
|
|
def getAnchorId(self) -> Optional[Any]:
|
|
return self._anchor
|
|
|
|
def isInPictureInPictureMode(self) -> bool:
|
|
return self._picture_in_picture
|
|
|
|
def setPictureInPictureMode(self, pip: bool) -> None:
|
|
self._picture_in_picture = pip
|
|
|
|
def getRoot(self) -> Optional[Any]:
|
|
return self._root
|
|
|
|
def setRoot(self, root: Any) -> None:
|
|
self._root = root
|
|
|
|
def getParent(self) -> Optional["AccessibilityWindowInfo"]:
|
|
return self._parent
|
|
|
|
def getChild(self, index: int) -> Optional["AccessibilityWindowInfo"]:
|
|
if index == 0:
|
|
return self._first_child
|
|
return None
|
|
|
|
def getChildCount(self) -> int:
|
|
return self._child_count
|
|
|
|
@staticmethod
|
|
def obtain() -> "AccessibilityWindowInfo":
|
|
return AccessibilityWindowInfo()
|
|
|
|
@staticmethod
|
|
def obtain(info: "AccessibilityWindowInfo") -> "AccessibilityWindowInfo":
|
|
return AccessibilityWindowInfo()
|
|
|
|
def recycle(self) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
types = {1: "APPLICATION", 2: "INPUT_METHOD", 3: "SYSTEM", 4: "OVERLAY"}
|
|
return (f"AccessibilityWindowInfo(type={types.get(self._type, 'UNKNOWN')}, "
|
|
f"id={self._id})")
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AccessibilityManager 扩展
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AccessibilityManager(Stub):
|
|
"""AccessibilityManager — 无障碍管理器扩展"""
|
|
|
|
FLAG_REPORT_VIEW_IDS = FLAG_REPORT_VIEW_IDS
|
|
FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY
|
|
FLAG_REQUEST_FILTER_KEY_EVENTS = FLAG_REQUEST_FILTER_KEY_EVENTS
|
|
FLAG_REQUEST_TOUCH_EXPLORATION_MODE = FLAG_REQUEST_TOUCH_EXPLORATION_MODE
|
|
FLAG_RETRIEVE_INTERACTIVE_WINDOWS = FLAG_RETRIEVE_INTERACTIVE_WINDOWS
|
|
FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
|
|
FLAG_REQUEST_ACCESSIBILITY_BUTTON = FLAG_REQUEST_ACCESSIBILITY_BUTTON
|
|
|
|
class AccessibilityStateChangeListener(Stub):
|
|
"""AccessibilityManager.AccessibilityStateChangeListener"""
|
|
def onAccessibilityStateChanged(self, enabled: bool) -> None:
|
|
pass
|
|
|
|
class TouchExplorationStateChangeListener(Stub):
|
|
"""AccessibilityManager.TouchExplorationStateChangeListener"""
|
|
def onTouchExplorationStateChanged(self, enabled: bool) -> None:
|
|
pass
|
|
|
|
class HighTextContrastChangeListener(Stub):
|
|
def onHighTextContrastStateChanged(self, enabled: bool) -> None:
|
|
pass
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._enabled = False
|
|
self._touch_exploration_enabled = False
|
|
self._high_text_contrast_enabled = False
|
|
self._state_listeners: List[AccessibilityStateChangeListener] = []
|
|
self._touch_listeners: List[TouchExplorationStateChangeListener] = []
|
|
self._contrast_listeners: List[Any] = []
|
|
self._accessibility_button_available = False
|
|
|
|
def isEnabled(self) -> bool:
|
|
return self._enabled
|
|
|
|
def setEnabled(self, enabled: bool) -> None:
|
|
old = self._enabled
|
|
self._enabled = enabled
|
|
if old != enabled:
|
|
for listener in list(self._state_listeners):
|
|
listener.onAccessibilityStateChanged(enabled)
|
|
|
|
def isTouchExplorationEnabled(self) -> bool:
|
|
return self._touch_exploration_enabled
|
|
|
|
def setTouchExplorationEnabled(self, enabled: bool) -> None:
|
|
old = self._touch_exploration_enabled
|
|
self._touch_exploration_enabled = enabled
|
|
if old != enabled:
|
|
for listener in list(self._touch_listeners):
|
|
listener.onTouchExplorationStateChanged(enabled)
|
|
|
|
def isHighTextContrastEnabled(self) -> bool:
|
|
return self._high_text_contrast_enabled
|
|
|
|
def addAccessibilityStateChangeListener(self, listener: AccessibilityStateChangeListener) -> None:
|
|
if listener not in self._state_listeners:
|
|
self._state_listeners.append(listener)
|
|
|
|
def removeAccessibilityStateChangeListener(self, listener: AccessibilityStateChangeListener) -> None:
|
|
if listener in self._state_listeners:
|
|
self._state_listeners.remove(listener)
|
|
|
|
def addTouchExplorationStateChangeListener(self, listener: TouchExplorationStateChangeListener) -> None:
|
|
if listener not in self._touch_listeners:
|
|
self._touch_listeners.append(listener)
|
|
|
|
def removeTouchExplorationStateChangeListener(self, listener: TouchExplorationStateChangeListener) -> None:
|
|
if listener in self._touch_listeners:
|
|
self._touch_listeners.remove(listener)
|
|
|
|
def addHighTextContrastStateChangeListener(self, listener: Any) -> None:
|
|
if listener not in self._contrast_listeners:
|
|
self._contrast_listeners.append(listener)
|
|
|
|
def removeHighTextContrastStateChangeListener(self, listener: Any) -> None:
|
|
if listener in self._contrast_listeners:
|
|
self._contrast_listeners.remove(listener)
|
|
|
|
def setAccessibilityButtonAvailable(self, available: bool) -> None:
|
|
self._accessibility_button_available = available
|
|
|
|
def isAccessibilityButtonAvailable(self) -> bool:
|
|
return self._accessibility_button_available
|
|
|
|
def sendAccessibilityEvent(self, event: AccessibilityEvent) -> None:
|
|
pass
|
|
|
|
def interrupt(self) -> None:
|
|
pass
|
|
|
|
def getInstalledAccessibilityServiceList(self) -> List[Any]:
|
|
return []
|
|
|
|
def getEnabledAccessibilityServiceList(self) -> List[Any]:
|
|
return []
|
|
|
|
def toString(self) -> str:
|
|
return (f"AccessibilityManager(enabled={self._enabled}, "
|
|
f"touchExploration={self._touch_exploration_enabled})")
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# CaptioningManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class CaptioningManager(Stub):
|
|
"""CaptioningManager — 字幕管理"""
|
|
|
|
CAPTIONING_TYPE_UNKNOWN = CAPTIONING_TYPE_UNKNOWN
|
|
CAPTIONING_TYPE_FEATURE = CAPTIONING_TYPE_FEATURE
|
|
CAPTIONING_TYPE_COUNTRY = CAPTIONING_TYPE_COUNTRY
|
|
CAPTIONING_TYPE_SPOKEN = CAPTIONING_TYPE_SPOKEN
|
|
CAPTIONING_TYPE_UNKNOWN_CHARACTER = CAPTIONING_TYPE_UNKNOWN_CHARACTER
|
|
CAPTIONING_TYPE_MUSIC = CAPTIONING_TYPE_MUSIC
|
|
CAPTIONING_TYPE_SFX = CAPTIONING_TYPE_SFX
|
|
CAPTIONING_TYPE_VOICE = CAPTIONING_TYPE_VOICE
|
|
|
|
class CaptionStyle(Stub):
|
|
"""CaptioningManager.CaptionStyle — 字幕风格"""
|
|
|
|
EDGE_TYPE_NONE = 0
|
|
EDGE_TYPE_OUTLINE = 1
|
|
EDGE_TYPE_DROP_SHADOW = 2
|
|
EDGE_TYPE_RAISED = 3
|
|
EDGE_TYPE_DEPRESSED = 4
|
|
|
|
PRESET_CUSTOM = CAPTIONING_PRESET_CUSTOM
|
|
PRESET_WHITE_ON_BLACK = CAPTIONING_PRESET_WHITE_ON_BLACK
|
|
PRESET_BLACK_ON_WHITE = CAPTIONING_PRESET_BLACK_ON_WHITE
|
|
PRESET_YELLOW_ON_BLACK = CAPTIONING_PRESET_YELLOW_ON_BLACK
|
|
PRESET_YELLOW_ON_BLUE = CAPTIONING_PRESET_YELLOW_ON_BLUE
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._foreground_color: int = 0xFFFFFFFF
|
|
self._background_color: int = 0xFF000000
|
|
self._edge_color: int = 0xFF000000
|
|
self._edge_type: int = self.EDGE_TYPE_NONE
|
|
self._window_color: int = 0xFF000000
|
|
self._foreground_size: int = 1
|
|
self._preset: int = CAPTIONING_PRESET_WHITE_ON_BLACK
|
|
|
|
def getForegroundColor(self) -> int:
|
|
return self._foreground_color
|
|
|
|
def getBackgroundColor(self) -> int:
|
|
return self._background_color
|
|
|
|
def getEdgeColor(self) -> int:
|
|
return self._edge_color
|
|
|
|
def getEdgeType(self) -> int:
|
|
return self._edge_type
|
|
|
|
def getWindowColor(self) -> int:
|
|
return self._window_color
|
|
|
|
def getForegroundSize(self) -> int:
|
|
return self._foreground_size
|
|
|
|
def getPreset(self) -> int:
|
|
return self._preset
|
|
|
|
def hasBackgroundColor(self) -> bool:
|
|
return (self._background_color >> 24) > 0
|
|
|
|
def hasForegroundColor(self) -> bool:
|
|
return (self._foreground_color >> 24) > 0
|
|
|
|
def hasEdgeType(self) -> bool:
|
|
return self._edge_type != self.EDGE_TYPE_NONE
|
|
|
|
def hasWindowColor(self) -> bool:
|
|
return (self._window_color >> 24) > 0
|
|
|
|
@staticmethod
|
|
def getCustomStyle(style_id: int) -> "CaptioningManager.CaptionStyle":
|
|
return CaptioningManager.CaptionStyle()
|
|
|
|
@staticmethod
|
|
def getPresetStyle(preset: int) -> "CaptioningManager.CaptionStyle":
|
|
return CaptioningManager.CaptionStyle()
|
|
|
|
def applyStyle(self, style: "CaptioningManager.CaptionStyle") -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"CaptionStyle(preset={self._preset})"
|
|
|
|
class CaptioningChangeListener(Stub):
|
|
"""CaptioningManager.CaptioningChangeListener"""
|
|
|
|
def onEnabledChanged(self, enabled: bool) -> None:
|
|
pass
|
|
|
|
def onUserStyleChanged(self, style: "CaptioningManager.CaptionStyle") -> None:
|
|
pass
|
|
|
|
def onLocaleChanged(self, locale: Any) -> None:
|
|
pass
|
|
|
|
def onFontScaleChanged(self, scale: float) -> None:
|
|
pass
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._enabled = False
|
|
self._user_style: Optional[CaptioningManager.CaptionStyle] = None
|
|
self._font_scale: float = 1.0
|
|
self._locale: Optional[Any] = None
|
|
self._listeners: List[CaptioningManager.CaptioningChangeListener] = []
|
|
|
|
def isEnabled(self) -> bool:
|
|
return self._enabled
|
|
|
|
def getFontScale(self) -> float:
|
|
return self._font_scale
|
|
|
|
def getLocale(self) -> Optional[Any]:
|
|
return self._locale
|
|
|
|
def getUserStyle(self) -> CaptionStyle:
|
|
return self._user_style or CaptioningManager.CaptionStyle()
|
|
|
|
def addCaptioningChangeListener(self, listener: CaptioningChangeListener) -> None:
|
|
if listener not in self._listeners:
|
|
self._listeners.append(listener)
|
|
|
|
def removeCaptioningChangeListener(self, listener: CaptioningChangeListener) -> None:
|
|
if listener in self._listeners:
|
|
self._listeners.remove(listener)
|
|
|
|
def toString(self) -> str:
|
|
return f"CaptioningManager(enabled={self._enabled})"
|
|
|
|
|
|
IllegalArgumentException = type("IllegalStateException", (RuntimeException,), {}) |