""" Android Notification API — NotificationChannel, NotificationManager, NotificationCompat, etc. 方法签名完全对齐 Android SDK """ from __future__ import annotations import json import os import time import threading from datetime import datetime from enum import IntEnum from typing import Any, Dict, List, Optional, Tuple, Callable, Union from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) # ═══════════════════════════════════════════════════════════════ # 常量定义 # ═══════════════════════════════════════════════════════════════ # IMPORTANCE 常量 IMPORTANCE_UNSPECIFIED = -1000 IMPORTANCE_NONE = 0 IMPORTANCE_MIN = 1 IMPORTANCE_LOW = 2 IMPORTANCE_DEFAULT = 3 IMPORTANCE_HIGH = 4 IMPORTANCE_MAX = 5 # VISIBILITY 常量 VISIBILITY_PRIVATE = 0 VISIBILITY_PUBLIC = 1 VISIBILITY_SECRET = -1 # PRIORITY 常量 PRIORITY_MIN = -2 PRIORITY_LOW = -1 PRIORITY_DEFAULT = 0 PRIORITY_HIGH = 1 PRIORITY_MAX = 2 # FLAG 常量 FLAG_SHOW_LIGHTS = 0x00000001 FLAG_ONGOING_EVENT = 0x00000002 FLAG_INSISTENT = 0x00000004 FLAG_ONLY_ALERT_ONCE = 0x00000008 FLAG_AUTO_CANCEL = 0x00000010 FLAG_NO_CLEAR = 0x00000020 FLAG_FOREGROUND_SERVICE = 0x00000040 FLAG_HIGH_PRIORITY = 0x00000080 FLAG_BUBBLE = 0x00000100 FLAG_GROUP_SUMMARY = 0x00000200 FLAG_LOCAL_ONLY = 0x00000400 FLAG_CAN_COLORIZE = 0x00000800 FLAG_ALERT_ONLY_ONCE = 0x00001000 # DEFAULT 常量 DEFAULT_ALL = -1 DEFAULT_SOUND = 1 DEFAULT_VIBRATE = 2 DEFAULT_LIGHTS = 4 # STREAM 常量 (deprecated) STREAM_DEFAULT = -1 STREAM_VOICE_CALL = 0 STREAM_SYSTEM = 1 STREAM_RING = 2 STREAM_MUSIC = 3 STREAM_ALARM = 4 STREAM_NOTIFICATION = 5 STREAM_DTMF = 8 # BADGE 常量 BADGE_ICON_NONE = 0 BADGE_ICON_SMALL = 1 BADGE_ICON_LARGE = 2 # INTERRUPTION_FILTER 常量 INTERRUPTION_FILTER_UNKNOWN = 0 INTERRUPTION_FILTER_ALL = 1 INTERRUPTION_FILTER_PRIORITY = 2 INTERRUPTION_FILTER_NONE = 3 INTERRUPTION_FILTER_ALARMS = 4 # CATEGORY 常量 CATEGORY_CALL = "call" CATEGORY_ALARM = "alarm" CATEGORY_REMINDER = "reminder" CATEGORY_EVENT = "event" CATEGORY_MESSAGE = "msg" CATEGORY_EMAIL = "email" CATEGORY_SOCIAL = "social" CATEGORY_ERROR = "err" CATEGORY_PROGRESS = "progress" CATEGORY_PROMO = "promo" CATEGORY_RECOMMENDATION = "recommendation" CATEGORY_STATUS = "status" CATEGORY_SYSTEM = "sys" CATEGORY_SERVICE = "service" CATEGORY_TRANSPORT = "transport" CATEGORY_WORKOUT = "workout" CATEGORY_LOCATION_SHARING = "location_sharing" CATEGORY_STOPWATCH = "stopwatch" CATEGORY_ALERT = "alert" CATEGORY_MISSED_CALL = "missed_call" # GROUP_ALERT 常量 GROUP_ALERT_ALL = 0 GROUP_ALERT_SUMMARY = 1 GROUP_ALERT_CHILDREN = 2 # SEMANTIC_ACTION 常量 SEMANTIC_ACTION_NONE = 0 SEMANTIC_ACTION_REPLY = 1 SEMANTIC_ACTION_MARK_AS_READ = 2 SEMANTIC_ACTION_MARK_AS_IMPORTANT = 3 SEMANTIC_ACTION_DELETE = 4 SEMANTIC_ACTION_ARCHIVE = 5 SEMANTIC_ACTION_MUTE = 6 SEMANTIC_ACTION_UNMUTE = 7 SEMANTIC_ACTION_CALL = 8 SEMANTIC_ACTION_THUMBS_UP = 9 SEMANTIC_ACTION_THUMBS_DOWN = 10 # ═══════════════════════════════════════════════════════════════ # NotificationChannel # ═══════════════════════════════════════════════════════════════ class NotificationChannel(Stub): """NotificationChannel — 通知渠道""" def __init__( self, channelId: str, channelName: str, importance: int = IMPORTANCE_DEFAULT, ): super().__init__() self._id = channelId self._name = channelName self._description: Optional[str] = None self._importance = importance self._bypass_dnd = False self._lockscreen_visibility = VISIBILITY_PRIVATE self._show_badge = True self._sound: Optional[str] = None self._vibration_enabled = False self._vibration_pattern: Optional[List[int]] = None self._light_color = 0 self._light_enabled = False self._group: Optional[str] = None self._can_bubble = False self._allow_bubbles = False self._is_vibration = False self._original_importance = importance self._fbr_enabled = False self._conversation_id: Optional[str] = None self._is_conversation = False self._demoted = False self._deleted = False self._has_user_set = False self._audio_attributes = None self._can_show_badge = True self._is_important_conversation = False self._important_conversation_quota = 0 def getId(self) -> str: return self._id def getName(self) -> str: return self._name def setName(self, name: str) -> None: self._name = name def getDescription(self) -> Optional[str]: return self._description def setDescription(self, description: str) -> None: self._description = description def getImportance(self) -> int: return self._importance def setImportance(self, importance: int) -> None: self._importance = importance def canBypassDnd(self) -> bool: return self._bypass_dnd def setBypassDnd(self, bypassDnd: bool) -> None: self._bypass_dnd = bypassDnd def getLockscreenVisibility(self) -> int: return self._lockscreen_visibility def setLockscreenVisibility(self, visibility: int) -> None: self._lockscreen_visibility = visibility def canShowBadge(self) -> bool: return self._show_badge def setShowBadge(self, showBadge: bool) -> None: self._show_badge = showBadge def getSound(self) -> Optional[str]: return self._sound def setSound(self, sound: Optional[str], audioAttributes: Any = None) -> None: self._sound = sound self._audio_attributes = audioAttributes def shouldVibrate(self) -> bool: return self._vibration_enabled def enableVibration(self, vibrationPattern: Optional[List[int]] = None) -> None: self._vibration_enabled = True if vibrationPattern is not None: self._vibration_pattern = vibrationPattern def getVibrationPattern(self) -> Optional[List[int]]: return self._vibration_pattern def getLightColor(self) -> int: return self._light_color def setLightColor(self, color: int) -> None: self._light_color = color self._light_enabled = True def getGroup(self) -> Optional[str]: return self._group def setGroup(self, groupId: Optional[str]) -> None: self._group = groupId def canBubble(self) -> bool: return self._can_bubble def setAllowBubbles(self, allow: bool) -> None: self._allow_bubbles = allow def isConversation(self) -> bool: return self._is_conversation def setConversationId(self, conversationId: str, parentChannelId: str = "") -> None: self._conversation_id = conversationId self._is_conversation = True def isDeleted(self) -> bool: return self._deleted def isImportantConversation(self) -> bool: return self._is_important_conversation def toString(self) -> str: return f"NotificationChannel(id={self._id}, name={self._name}, importance={self._importance})" # ═══════════════════════════════════════════════════════════════ # NotificationChannelGroup # ═══════════════════════════════════════════════════════════════ class NotificationChannelGroup(Stub): """NotificationChannelGroup — 通知渠道组""" def __init__(self, groupId: str, groupName: str): super().__init__() self._id = groupId self._name = groupName self._description: Optional[str] = None self._channels: List[NotificationChannel] = [] self._blocked = False def getId(self) -> str: return self._id def getName(self) -> str: return self._name def getDescription(self) -> Optional[str]: return self._description def setDescription(self, description: str) -> None: self._description = description def getChannels(self) -> List[NotificationChannel]: return list(self._channels) def isBlocked(self) -> bool: return self._blocked def toString(self) -> str: return f"NotificationChannelGroup(id={self._id}, name={self._name})" # ═══════════════════════════════════════════════════════════════ # Notification.Action # ═══════════════════════════════════════════════════════════════ class NotificationAction(Stub): """Notification.Action — 通知操作""" def __init__( self, icon: Optional[int] = None, title: Optional[str] = None, pendingIntent: Any = None, ): super().__init__() self.icon = icon self.title = title self.actionIntent = pendingIntent self._extras: Optional[Any] = None self._remote_inputs: List[Any] = [] self._semantic_action = SEMANTIC_ACTION_NONE self._contextual = False self._allow_generated_replies = False self._is_authentication_required = False self._is_bubble = False def getExtras(self) -> Optional[Any]: return self._extras def getRemoteInputs(self) -> List[Any]: return list(self._remote_inputs) def getSemanticAction(self) -> int: return self._semantic_action def isContextual(self) -> bool: return self._contextual def getAllowGeneratedReplies(self) -> bool: return self._allow_generated_replies def isAuthenticationRequired(self) -> bool: return self._is_authentication_required def toString(self) -> str: return f"Notification.Action(title={self.title}, icon={self.icon})" # ═══════════════════════════════════════════════════════════════ # Notification.Style 基类 # ═══════════════════════════════════════════════════════════════ class NotificationStyle(Stub): """Notification.Style — 通知样式基类""" def __init__(self): super().__init__() self._big_content_title: Optional[str] = None self._summary_text: Optional[str] = None self._colorized = False def setBigContentTitle(self, title: str) -> "NotificationStyle": self._big_content_title = title return self def setSummaryText(self, summary: str) -> "NotificationStyle": self._summary_text = summary return self def getBigContentTitle(self) -> Optional[str]: return self._big_content_title def getSummaryText(self) -> Optional[str]: return self._summary_text class BigPictureStyle(NotificationStyle): """Notification.BigPictureStyle — 大图通知样式""" def __init__(self): super().__init__() self._big_large_icon: Optional[Any] = None self._big_picture: Optional[Any] = None self._content_description: Optional[str] = None self._show_icon = False def bigPicture(self, picture: Any) -> "BigPictureStyle": self._big_picture = picture return self def bigLargeIcon(self, icon: Any) -> "BigPictureStyle": self._big_large_icon = icon return self def setContentDescription(self, description: str) -> "BigPictureStyle": self._content_description = description return self def showBigPictureWhenCollapsed(self, show: bool) -> "BigPictureStyle": self._show_icon = show return self def getBigPicture(self) -> Optional[Any]: return self._big_picture def toString(self) -> str: return f"BigPictureStyle(title={self._big_content_title})" class BigTextStyle(NotificationStyle): """Notification.BigTextStyle — 大文本通知样式""" def __init__(self): super().__init__() self._big_text: Optional[str] = None self._lines: List[str] = [] def bigText(self, text: str) -> "BigTextStyle": self._big_text = text return self def setLines(self, lines: List[str]) -> "BigTextStyle": self._lines = list(lines) return self def getBigText(self) -> Optional[str]: return self._big_text def toString(self) -> str: return f"BigTextStyle(text_len={len(self._big_text) if self._big_text else 0})" class InboxStyle(NotificationStyle): """Notification.InboxStyle — 收件箱通知样式""" def __init__(self): super().__init__() self._lines: List[str] = [] def addLine(self, line: str) -> "InboxStyle": self._lines.append(line) return self def setLines(self, lines: List[str]) -> "InboxStyle": self._lines = list(lines) return self def getLines(self) -> List[str]: return list(self._lines) def toString(self) -> str: return f"InboxStyle(lines={len(self._lines)})" class MessagingStyle(NotificationStyle): """Notification.MessagingStyle — 消息通知样式""" class Message(Stub): """Notification.MessagingStyle.Message — 单条消息""" def __init__( self, text: str, timestamp: int, sender: Optional[str] = None, bundle: Optional[Any] = None, ): super().__init__() self._text = text self._timestamp = timestamp self._sender = sender self._bundle = bundle self._data_mime_type: Optional[str] = None self._data_uri: Optional[str] = None self._remote_input_history: List[Any] = [] self._extras: Optional[Any] = None def getText(self) -> str: return self._text def getTimestamp(self) -> int: return self._timestamp def getSender(self) -> Optional[str]: return self._sender def getDataMimeType(self) -> Optional[str]: return self._data_mime_type def getDataUri(self) -> Optional[str]: return self._data_uri def setData(self, mimeType: str, uri: str) -> None: self._data_mime_type = mimeType self._data_uri = uri def getExtras(self) -> Optional[Any]: return self._extras def getRemoteInputHistory(self) -> List[Any]: return list(self._remote_input_history) def toString(self) -> str: return f"Message(sender={self._sender}, text={self._text})" def __init__(self, user_display_name: str, conversation_title: Optional[str] = None): super().__init__() self._user_display_name = user_display_name self._conversation_title = conversation_title self._messages: List[MessagingStyle.Message] = [] self._group_conversation = False self._is_group_conversation = False def addMessage(self, message: "MessagingStyle.Message") -> "MessagingStyle": self._messages.append(message) return self def addHistoricMessage(self, message: "MessagingStyle.Message") -> "MessagingStyle": if message not in self._messages: self._messages.append(message) return self def setConversationTitle(self, title: str) -> "MessagingStyle": self._conversation_title = title return self def setGroupConversation(self, isGroup: bool) -> "MessagingStyle": self._is_group_conversation = isGroup return self def getUserDisplayName(self) -> str: return self._user_display_name def getConversationTitle(self) -> Optional[str]: return self._conversation_title def getMessages(self) -> List["MessagingStyle.Message"]: return list(self._messages) def isGroupConversation(self) -> bool: return self._is_group_conversation def toString(self) -> str: return f"MessagingStyle(user={self._user_display_name}, msgs={len(self._messages)})" class CarExtender(Stub): """Notification.CarExtender — 车载通知扩展""" class UnreadConversation(Stub): """Notification.CarExtender.UnreadConversation — 未读对话""" def __init__(self): super().__init__() self._name: Optional[str] = None self._latest_timestamp: Optional[int] = None self._messages: List[str] = [] self._remote_input: Optional[Any] = None self._participants: List[str] = [] self._pending_intent: Optional[Any] = None def getName(self) -> Optional[str]: return self._name def getLatestTimestamp(self) -> Optional[int]: return self._latest_timestamp def getMessages(self) -> List[str]: return list(self._messages) def getRemoteInput(self) -> Optional[Any]: return self._remote_input def getParticipants(self) -> List[str]: return list(self._participants) def getPendingIntent(self) -> Optional[Any]: return self._pending_intent def toString(self) -> str: return f"UnreadConversation(name={self._name})" def __init__(self): super().__init__() self._color = 0 self._large_icon: Optional[Any] = None self._unread_conversation: Optional["CarExtender.UnreadConversation"] = None def setColor(self, color: int) -> "CarExtender": self._color = color return self def getColor(self) -> int: return self._color def setLargeIcon(self, icon: Any) -> "CarExtender": self._large_icon = icon return self def getLargeIcon(self) -> Optional[Any]: return self._large_icon def setUnreadConversation( self, conversation: "CarExtender.UnreadConversation" ) -> "CarExtender": self._unread_conversation = conversation return self def getUnreadConversation(self) -> Optional["CarExtender.UnreadConversation"]: return self._unread_conversation def toString(self) -> str: return "CarExtender" # ═══════════════════════════════════════════════════════════════ # NotificationCompat # ═══════════════════════════════════════════════════════════════ class NotificationCompat(Stub): """NotificationCompat — 兼容通知构建器""" class Builder(Stub): """NotificationCompat.Builder — 通知构建器""" def __init__(self, context: Any = None, channelId: Optional[str] = None): super().__init__() self._context = context self._channel_id = channelId or "" self._content_title: Optional[str] = None self._content_text: Optional[str] = None self._content_info: Optional[str] = None self._sub_text: Optional[str] = None self._ticker_text: Optional[str] = None self._small_icon: Optional[Any] = None self._large_icon: Optional[Any] = None self._priority = PRIORITY_DEFAULT self._flags = 0 self._defaults = 0 self._when: Optional[int] = None self._color = 0 self._colorized = False self._category: Optional[str] = None self._group: Optional[str] = None self._group_summary = False self._group_alert_behavior = GROUP_ALERT_ALL self._number = 0 self._content_intent: Optional[Any] = None self._delete_intent: Optional[Any] = None self._full_screen_intent: Optional[Any] = None self._actions: List[NotificationAction] = [] self._style: Optional[NotificationStyle] = None self._extras: Dict[str, Any] = {} self._people: List[str] = [] self._uses_chronometer = False self._auto_cancel = False self._local_only = False self._ongoing = False self._only_alert_once = False self._show_when = True self._sort_key: Optional[str] = None self._public_version: Optional[Any] = None self._notification_sound: Optional[str] = None self._notification_vibrate: Optional[List[int]] = None self._notification_led_color = 0 self._notification_led_on_ms = 0 self._notification_led_off_ms = 0 self._timeout_ms: Optional[int] = None self._timeout_after_ms: Optional[int] = None self._shortcut_id: Optional[str] = None self._time: Optional[int] = None self._visibility = VISIBILITY_PRIVATE self._badge_icon_type = BADGE_ICON_NONE self._settings_text: Optional[str] = None self._time_zone: Optional[Any] = None self._contextual = False self._allow_system_generated_contextual_actions = True self._bubble_metadata: Optional[Any] = None self._is_bubble = False self._fgs_delegate: Optional[Any] = None def setChannelId(self, channelId: str) -> "NotificationCompat.Builder": self._channel_id = channelId return self def setContentTitle(self, title: str) -> "NotificationCompat.Builder": self._content_title = title return self def setContentText(self, text: str) -> "NotificationCompat.Builder": self._content_text = text return self def setSubText(self, text: str) -> "NotificationCompat.Builder": self._sub_text = text return self def setContentInfo(self, info: str) -> "NotificationCompat.Builder": self._content_info = info return self def setTicker(self, tickerText: str) -> "NotificationCompat.Builder": self._ticker_text = tickerText return self def setSmallIcon(self, icon: Any) -> "NotificationCompat.Builder": self._small_icon = icon return self def setLargeIcon(self, icon: Any) -> "NotificationCompat.Builder": self._large_icon = icon return self def setPriority(self, priority: int) -> "NotificationCompat.Builder": self._priority = priority return self def setDefaults(self, defaults: int) -> "NotificationCompat.Builder": self._defaults = defaults return self def setWhen(self, when: int) -> "NotificationCompat.Builder": self._when = when return self def setUsesChronometer(self, b: bool) -> "NotificationCompat.Builder": self._uses_chronometer = b return self def setColor(self, color: int) -> "NotificationCompat.Builder": self._color = color return self def setColorized(self, colorized: bool) -> "NotificationCompat.Builder": self._colorized = colorized return self def setCategory(self, category: str) -> "NotificationCompat.Builder": self._category = category return self def setGroup(self, groupKey: str) -> "NotificationCompat.Builder": self._group = groupKey return self def setGroupSummary(self, isGroupSummary: bool) -> "NotificationCompat.Builder": self._group_summary = isGroupSummary return self def setGroupAlertBehavior(self, behavior: int) -> "NotificationCompat.Builder": self._group_alert_behavior = behavior return self def setNumber(self, number: int) -> "NotificationCompat.Builder": self._number = number return self def setContentIntent(self, intent: Any) -> "NotificationCompat.Builder": self._content_intent = intent return self def setDeleteIntent(self, intent: Any) -> "NotificationCompat.Builder": self._delete_intent = intent return self def setFullScreenIntent(self, intent: Any, highPriority: bool) -> "NotificationCompat.Builder": self._full_screen_intent = intent if highPriority: self._flags |= FLAG_HIGH_PRIORITY return self def addAction( self, iconOrAction: Any, title: Optional[str] = None, pendingIntent: Any = None ) -> "NotificationCompat.Builder": if isinstance(iconOrAction, NotificationAction): self._actions.append(iconOrAction) elif isinstance(iconOrAction, int): self._actions.append(NotificationAction(iconOrAction, title, pendingIntent)) else: self._actions.append(NotificationAction(None, str(iconOrAction), pendingIntent)) return self def setStyle(self, style: NotificationStyle) -> "NotificationCompat.Builder": self._style = style return self def addPerson(self, uri: str) -> "NotificationCompat.Builder": self._people.append(uri) return self def setShowWhen(self, show: bool) -> "NotificationCompat.Builder": self._show_when = show return self def setLocalOnly(self, localOnly: bool) -> "NotificationCompat.Builder": self._local_only = localOnly return self def setOngoing(self, ongoing: bool) -> "NotificationCompat.Builder": self._ongoing = ongoing if ongoing: self._flags |= FLAG_ONGOING_EVENT else: self._flags &= ~FLAG_ONGOING_EVENT return self def setAutoCancel(self, autoCancel: bool) -> "NotificationCompat.Builder": self._auto_cancel = autoCancel if autoCancel: self._flags |= FLAG_AUTO_CANCEL else: self._flags &= ~FLAG_AUTO_CANCEL return self def setOnlyAlertOnce(self, onlyAlertOnce: bool) -> "NotificationCompat.Builder": self._only_alert_once = onlyAlertOnce if onlyAlertOnce: self._flags |= FLAG_ONLY_ALERT_ONCE else: self._flags &= ~FLAG_ONLY_ALERT_ONCE return self def setVisibility(self, visibility: int) -> "NotificationCompat.Builder": self._visibility = visibility return self def setBadgeIconType(self, iconType: int) -> "NotificationCompat.Builder": self._badge_icon_type = iconType return self def setSettingsText(self, text: str) -> "NotificationCompat.Builder": self._settings_text = text return self def setSortKey(self, sortKey: str) -> "NotificationCompat.Builder": self._sort_key = sortKey return self def setTimeout(self, durationMs: int) -> "NotificationCompat.Builder": self._timeout_ms = durationMs return self def setTimeoutAfter(self, durationMs: int) -> "NotificationCompat.Builder": self._timeout_after_ms = durationMs return self def setShortcutId(self, shortcutId: str) -> "NotificationCompat.Builder": self._shortcut_id = shortcutId return self def setPublicVersion(self, notification: Any) -> "NotificationCompat.Builder": self._public_version = notification return self def extend(self, extender: Any) -> "NotificationCompat.Builder": if extender: extender.extend(self) return self def setSound(self, sound: Optional[str]) -> "NotificationCompat.Builder": self._notification_sound = sound return self def setVibrate(self, pattern: Optional[List[int]]) -> "NotificationCompat.Builder": self._notification_vibrate = pattern return self def setLights(self, color: int, onMs: int, offMs: int) -> "NotificationCompat.Builder": self._notification_led_color = color self._notification_led_on_ms = onMs self._notification_led_off_ms = offMs return self def setFlag(self, flag: int, enabled: bool) -> "NotificationCompat.Builder": if enabled: self._flags |= flag else: self._flags &= ~flag return self def addExtras(self, extras: Dict[str, Any]) -> "NotificationCompat.Builder": self._extras.update(extras) return self def getExtras(self) -> Dict[str, Any]: return self._extras def build(self) -> "NotificationCompat": return NotificationCompat(self) def toString(self) -> str: return f"NotificationCompat.Builder(title={self._content_title})" def __init__(self, builder: "NotificationCompat.Builder"): super().__init__() self._channel_id = builder._channel_id self._content_title = builder._content_title self._content_text = builder._content_text self._sub_text = builder._sub_text self._priority = builder._priority self._flags = builder._flags self._defaults = builder._defaults self._when = builder._when self._small_icon = builder._small_icon self._large_icon = builder._large_icon self._actions = list(builder._actions) self._style = builder._style self._category = builder._category self._group = builder._group self._color = builder._color self._extras = dict(builder._extras) self._visibility = builder._visibility def getChannelId(self) -> Optional[str]: return self._channel_id def getContentTitle(self) -> Optional[str]: return self._content_title def getContentText(self) -> Optional[str]: return self._content_text def getSubText(self) -> Optional[str]: return self._sub_text def getPriority(self) -> int: return self._priority def getFlags(self) -> int: return self._flags def getDefaults(self) -> int: return self._defaults def getCategory(self) -> Optional[str]: return self._category def getGroup(self) -> Optional[str]: return self._group def getColor(self) -> int: return self._color def getVisibility(self) -> int: return self._visibility def getExtras(self) -> Dict[str, Any]: return dict(self._extras) def getActions(self) -> List[NotificationAction]: return list(self._actions) def getStyle(self) -> Optional[NotificationStyle]: return self._style def toString(self) -> str: return f"Notification(channel={self._channel_id}, title={self._content_title})" # ═══════════════════════════════════════════════════════════════ # Notification (简化) # ═══════════════════════════════════════════════════════════════ class Notification(Stub): """Notification — Android 通知""" Action = NotificationAction BigPictureStyle = BigPictureStyle BigTextStyle = BigTextStyle InboxStyle = InboxStyle MessagingStyle = MessagingStyle CarExtender = CarExtender Style = NotificationStyle def __init__(self): super().__init__() self._when: Optional[int] = None self._content_title: Optional[str] = None self._content_text: Optional[str] = None self._small_icon: Optional[Any] = None self._large_icon: Optional[Any] = None self._ticker_text: Optional[str] = None self._content_intent: Optional[Any] = None self._delete_intent: Optional[Any] = None self._full_screen_intent: Optional[Any] = None self._flags = 0 self._defaults = 0 self._sound: Optional[str] = None self._vibrate: Optional[List[int]] = None self._led_color = 0 self._led_on_ms = 0 self._led_off_ms = 0 self._number = 0 self._icon = 0 self._icon_level = 0 self._priority = PRIORITY_DEFAULT self._category: Optional[str] = None self._group: Optional[str] = None self._group_summary = False self._color = 0 self._visibility = VISIBILITY_PRIVATE self._extras: Dict[str, Any] = {} self._actions: List[NotificationAction] = [] def getWhen(self) -> Optional[int]: return self._when def getContentTitle(self) -> Optional[str]: return self._content_title def getContentText(self) -> Optional[str]: return self._content_text def getSmallIcon(self) -> Optional[Any]: return self._small_icon def getLargeIcon(self) -> Optional[Any]: return self._large_icon def getFlags(self) -> int: return self._flags def setFlags(self, flags: int) -> None: self._flags = flags def getDefaults(self) -> int: return self._defaults def getNumber(self) -> int: return self._number def getColor(self) -> int: return self._color def getCategory(self) -> Optional[str]: return self._category def getGroup(self) -> Optional[str]: return self._group def getPriority(self) -> int: return self._priority def getVisibility(self) -> int: return self._visibility def getExtras(self) -> Dict[str, Any]: return dict(self._extras) def getActions(self) -> List[NotificationAction]: return list(self._actions) def toString(self) -> str: return f"Notification(title={self._content_title})" # ═══════════════════════════════════════════════════════════════ # NotificationManager # ═══════════════════════════════════════════════════════════════ class NotificationManager(Stub): """NotificationManager — 通知管理器 (桌面存根)""" # ImportErrorBehavior 常量 IMPORTANCE_UNSPECIFIED = IMPORTANCE_UNSPECIFIED IMPORTANCE_NONE = IMPORTANCE_NONE IMPORTANCE_MIN = IMPORTANCE_MIN IMPORTANCE_LOW = IMPORTANCE_LOW IMPORTANCE_DEFAULT = IMPORTANCE_DEFAULT IMPORTANCE_HIGH = IMPORTANCE_HIGH IMPORTANCE_MAX = IMPORTANCE_MAX INTERRUPTION_FILTER_UNKNOWN = INTERRUPTION_FILTER_UNKNOWN INTERRUPTION_FILTER_ALL = INTERRUPTION_FILTER_ALL INTERRUPTION_FILTER_PRIORITY = INTERRUPTION_FILTER_PRIORITY INTERRUPTION_FILTER_NONE = INTERRUPTION_FILTER_NONE INTERRUPTION_FILTER_ALARMS = INTERRUPTION_FILTER_ALARMS BUBBLE_PREFERENCE_NONE = 0 BUBBLE_PREFERENCE_SELECTED = 1 BUBBLE_PREFERENCE_ALL = 2 def __init__(self, context: Any = None): super().__init__() self._context = context self._lock = threading.Lock() self._notifications: Dict[str, List[Tuple[int, Any]]] = {} self._channels: Dict[str, NotificationChannel] = {} self._channel_groups: Dict[str, NotificationChannelGroup] = {} self._interruption_filter = INTERRUPTION_FILTER_ALL self._notification_delegate: Optional[str] = None self._notification_delegate_enabled = False self._are_notifications_enabled = True self._bubble_preference = NotificationManager.BUBBLE_PREFERENCE_SELECTED self._can_post_notifications = True self._auto_bundling_enabled = True self._notification_assist: Optional[str] = None def notify(self, tag: Optional[str], id: int, notification: Any) -> None: """发送通知""" with self._lock: key = tag or "__default__" if key not in self._notifications: self._notifications[key] = [] self._notifications[key].append((id, notification)) def cancel(self, tag: Optional[str], id: int) -> None: """取消指定通知""" with self._lock: key = tag or "__default__" if key in self._notifications: self._notifications[key] = [ (nid, n) for nid, n in self._notifications[key] if nid != id ] def cancelAll(self) -> None: """取消所有通知""" with self._lock: self._notifications.clear() def getActiveNotifications(self) -> List[Any]: """获取活动通知列表""" with self._lock: result = [] for entries in self._notifications.values(): for _, notification in entries: result.append(notification) return result def createNotificationChannel(self, channel: NotificationChannel) -> None: """创建通知渠道""" with self._lock: self._channels[channel.getId()] = channel def createNotificationChannelGroup(self, group: NotificationChannelGroup) -> None: """创建通知渠道组""" with self._lock: self._channel_groups[group.getId()] = group def createNotificationChannels(self, channels: List[NotificationChannel]) -> None: """批量创建通知渠道""" with self._lock: for ch in channels: self._channels[ch.getId()] = ch def createNotificationChannelGroups(self, groups: List[NotificationChannelGroup]) -> None: """批量创建通知渠道组""" with self._lock: for g in groups: self._channel_groups[g.getId()] = g def getNotificationChannel(self, channelId: str) -> Optional[NotificationChannel]: """获取通知渠道""" with self._lock: return self._channels.get(channelId) def getNotificationChannels(self) -> List[NotificationChannel]: """获取所有通知渠道""" with self._lock: return list(self._channels.values()) def getNotificationChannelGroups(self) -> List[NotificationChannelGroup]: """获取所有通知渠道组""" with self._lock: return list(self._channel_groups.values()) def deleteNotificationChannel(self, channelId: str) -> None: """删除通知渠道""" with self._lock: if channelId in self._channels: channel = self._channels.pop(channelId) channel._deleted = True def getImportance(self) -> int: """获取当前通知重要性""" return IMPORTANCE_DEFAULT def areNotificationsEnabled(self) -> bool: """检查通知是否启用""" return self._are_notifications_enabled def isNotificationPolicyAccessGranted(self) -> bool: """检查是否授予通知策略访问权限""" return True def getCurrentInterruptionFilter(self) -> int: """获取当前中断过滤器""" return self._interruption_filter def setInterruptionFilter(self, filterType: int) -> None: """设置中断过滤器""" self._interruption_filter = filterType def getNotificationDelegate(self) -> Optional[str]: """获取通知代理""" return self._notification_delegate def isNotificationListenerAccessGranted(self, listener: Any) -> bool: """检查是否授予通知监听访问权限""" return True def matchesCallFilter(self, incomingAddress: Any) -> bool: """检查是否匹配来电过滤""" return True def getBubblePreference(self) -> int: """获取气泡偏好""" return self._bubble_preference def canNotifyAsPackage(self, pkg: str) -> bool: """检查能否以指定包名发送通知""" return True def setNotificationDelegate(self, delegate: str) -> None: """设置通知代理""" self._notification_delegate = delegate def areBubblesAllowed(self) -> bool: """检查是否允许气泡""" return True def getActiveNotificationCount(self) -> int: """获取活动通知数量""" with self._lock: count = 0 for entries in self._notifications.values(): count += len(entries) return count def isAutoBundlingEnabled(self) -> bool: """检查自动捆绑是否启用""" return self._auto_bundling_enabled def setAutoBundlingEnabled(self, enabled: bool) -> None: """设置自动捆绑""" self._auto_bundling_enabled = enabled def getNotificationAssist(self) -> Optional[str]: """获取通知助手""" return self._notification_assist def getConsolidatedNotificationPolicy(self) -> Optional[Any]: """获取合并通知策略""" return None def toString(self) -> str: with self._lock: return ( f"NotificationManager(channels={len(self._channels)}, " f"groups={len(self._channel_groups)}, " f"active_notifications={self.getActiveNotificationCount()})" ) # ═══════════════════════════════════════════════════════════════ # NotificationManager.Policy # ═══════════════════════════════════════════════════════════════ class NotificationManagerPolicy(Stub): """NotificationManager.Policy — 通知策略""" PRIORITY_CATEGORY_UNKNOWN = 0 PRIORITY_CATEGORY_CALLS = 1 PRIORITY_CATEGORY_MESSAGES = 2 PRIORITY_CATEGORY_CONVERSATIONS = 3 PRIORITY_CATEGORY_REMINDERS = 4 PRIORITY_CATEGORY_EVENTS = 5 PRIORITY_CATEGORY_ALARMS = 6 PRIORITY_CATEGORY_MEDIA = 7 PRIORITY_CATEGORY_SYSTEM = 8 PRIORITY_CATEGORY_ALERTS = 9 PRIORITY_SENDERS_ANY = 0 PRIORITY_SENDERS_CONTACTS = 1 PRIORITY_SENDERS_STARRED = 2 SUPPRESSED_EFFECT_SCREEN_OFF = 1 SUPPRESSED_EFFECT_SCREEN_ON = 2 SUPPRESSED_EFFECT_FULL_SCREEN_INTENT = 4 SUPPRESSED_EFFECT_AMBIENT = 8 SUPPRESSED_EFFECT_PEEK = 16 SUPPRESSED_EFFECT_STATUS_BAR = 32 SUPPRESSED_EFFECT_BADGE = 64 SUPPRESSED_EFFECT_BANNER = 128 SUPPRESSED_EFFECT_LIGHTS = 256 def __init__( self, priorityCategories: int = 0, priorityCallSenders: int = PRIORITY_SENDERS_ANY, priorityMessageSenders: int = PRIORITY_SENDERS_ANY, suppressedEffects: int = 0, ): super().__init__() self.priorityCategories = priorityCategories self.priorityCallSenders = priorityCallSenders self.priorityMessageSenders = priorityMessageSenders self.suppressedEffects = suppressedEffects def toString(self) -> str: return ( f"NotificationManager.Policy(" f"priorityCategories={self.priorityCategories}, " f"priorityCallSenders={self.priorityCallSenders}, " f"priorityMessageSenders={self.priorityMessageSenders})" )