Files
Android-pyApi/android_pyapi/android/app.py
T
shuiyu1123 bfe27fdc08 feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python
52 个模块覆盖 Android + Java + org.json 标准库
2026-06-24 11:16:16 +00:00

2001 lines
64 KiB
Python

"""
Android App 组件 — Activity, Service, Intent, Notification 等
方法签名完全对齐 Android SDK
"""
import json
import os
import time
import re
import sys
import threading
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple, Callable, Union
from urllib.parse import urlparse, urlunparse
from .._core import (
Stub, AndroidOnlyError, android_context,
resolve_android_path, to_android_path,
_sdcard_root, _app_data_dir, _package_name,
)
# ═══════════════════════════════════════════════════════════════
# Intent
# ═══════════════════════════════════════════════════════════════
class Intent(Stub):
"""Android Intent — 组件间消息传递"""
# Action 常量
ACTION_MAIN = "android.intent.action.MAIN"
ACTION_VIEW = "android.intent.action.VIEW"
ACTION_EDIT = "android.intent.action.EDIT"
ACTION_SEND = "android.intent.action.SEND"
ACTION_CALL = "android.intent.action.CALL"
ACTION_DIAL = "android.intent.action.DIAL"
ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH"
ACTION_PICK = "android.intent.action.PICK"
ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT"
ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE"
ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"
ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED"
ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED"
ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW"
ACTION_BATTERY_OKAY = "android.intent.action.BATTERY_OKAY"
ACTION_TIME_TICK = "android.intent.action.TIME_TICK"
ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED"
ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON"
ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF"
ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE_CHANGED"
# Flag 常量
FLAG_ACTIVITY_NEW_TASK = 0x10000000
FLAG_ACTIVITY_CLEAR_TOP = 0x04000000
FLAG_ACTIVITY_SINGLE_TOP = 0x20000000
FLAG_ACTIVITY_NO_HISTORY = 0x40000000
FLAG_FROM_BACKGROUND = 0x00004000
FLAG_RECEIVER_FOREGROUND = 0x10000000
FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020
# Category 常量
CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER"
CATEGORY_DEFAULT = "android.intent.category.DEFAULT"
CATEGORY_HOME = "android.intent.category.HOME"
CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE"
CATEGORY_OPENABLE = "android.intent.category.OPENABLE"
def __init__(self, action: Optional[str] = None, uri: Optional[str] = None):
super().__init__()
self._action = action
self._uri = uri
self._data_str = None
self._type = None
self._extras: Dict[str, Any] = {}
self._flags = 0
self._categories: List[str] = []
self._package = None
self._component: Optional[Tuple[str, str]] = None # (pkg, cls)
self._clip_data = None
def setClass(self, package_context: Any, cls: type) -> "Intent":
self._package = package_context.packageName if hasattr(package_context, 'packageName') else _package_name
self._component = (self._package, cls.__name__ if isinstance(cls, type) else str(cls))
return self
def setAction(self, action: str) -> "Intent":
self._action = action
return self
def getAction(self) -> Optional[str]:
return self._action
def setData(self, uri: str) -> "Intent":
self._data_str = uri
return self
def getData(self) -> Optional[str]:
return self._data_str
def setType(self, type_: str) -> "Intent":
self._type = type_
return self
def getType(self) -> Optional[str]:
return self._type
def setDataAndType(self, uri: str, type_: str) -> "Intent":
self._data_str = uri
self._type = type_
return self
def putExtra(self, name: str, value: Any) -> "Intent":
self._extras[name] = value
return self
def getStringExtra(self, name: str) -> Optional[str]:
return self._extras.get(name)
def getIntExtra(self, name: str, default: int = 0) -> int:
return self._extras.get(name, default)
def getBooleanExtra(self, name: str, default: bool = False) -> bool:
return self._extras.get(name, default)
def getLongExtra(self, name: str, default: int = 0) -> int:
return self._extras.get(name, default)
def getFloatExtra(self, name: str, default: float = 0.0) -> float:
return self._extras.get(name, default)
def getDoubleExtra(self, name: str, default: float = 0.0) -> float:
return self._extras.get(name, default)
def getSerializableExtra(self, name: str):
return self._extras.get(name)
def getIntegerArrayListExtra(self, name: str) -> Optional[List[int]]:
return self._extras.get(name)
def getStringArrayListExtra(self, name: str) -> Optional[List[str]]:
return self._extras.get(name)
def getExtras(self) -> Dict[str, Any]:
return self._extras
def hasExtra(self, name: str) -> bool:
return name in self._extras
def removeExtra(self, name: str):
self._extras.pop(name, None)
def addCategory(self, category: str) -> "Intent":
if category not in self._categories:
self._categories.append(category)
return self
def getCategories(self) -> Optional[List[str]]:
return self._categories if self._categories else None
def hasCategory(self, category: str) -> bool:
return category in self._categories
def setFlags(self, flags: int) -> "Intent":
self._flags = flags
return self
def getFlags(self) -> int:
return self._flags
def addFlags(self, flags: int) -> "Intent":
self._flags |= flags
return self
def setPackage(self, package_name: str) -> "Intent":
self._package = package_name
return self
def getPackage(self) -> Optional[str]:
return self._package
def setClassName(self, package_name: str, class_name: str) -> "Intent":
self._component = (package_name, class_name)
return self
def resolveActivity(self, pm) -> Optional["ComponentName"]:
from .content import ComponentName
if self._component:
return ComponentName(self._component[0], self._component[1])
return None
def createChooser(self, title: str) -> "Intent":
"""Create a chooser intent"""
return self
def toURI(self) -> str:
return str(self._uri or self._data_str or "")
def toString(self) -> str:
return (
f"Intent {{ act={self._action} "
f"pkg={self._package} "
f"cmp={self._component} "
f"hasExtras={bool(self._extras)} }}"
)
def clone(self) -> "Intent":
cloned = Intent(self._action, self._uri)
cloned._data_str = self._data_str
cloned._type = self._type
cloned._extras = dict(self._extras)
cloned._flags = self._flags
cloned._categories = list(self._categories)
cloned._package = self._package
cloned._component = self._component
return cloned
def fillIn(self, other: "Intent", flags: int = 0) -> int:
filled = 0
if other._action and not self._action:
self._action = other._action; filled |= 1
if other._data_str and not self._data_str:
self._data_str = other._data_str; filled |= 2
if other._type and not self._type:
self._type = other._type; filled |= 4
if other._categories:
for c in other._categories:
if c not in self._categories:
self._categories.append(c)
filled |= 8
return filled
def filterEquals(self, other: "Intent") -> bool:
return (
self._action == other._action
and self._data_str == other._data_str
and self._type == other._type
and self._package == other._package
and self._component == other._component
)
def filterHashCode(self) -> int:
return hash((self._action, self._data_str, self._type, self._package, self._component)) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# ComponentName (forward reference)
# ═══════════════════════════════════════════════════════════════
class ComponentName(Stub):
"""Identifies a specific component class within a package"""
def __init__(self, pkg: str, cls: str):
super().__init__()
self._package = pkg
self._classname = cls
def getPackageName(self) -> str:
return self._package
def getClassName(self) -> str:
return self._classname
def getShortClassName(self) -> str:
return self._classname.split(".")[-1] if "." in self._classname else self._classname
def flattenToString(self) -> str:
return f"{self._package}/{self._classname}"
def flattenToShortString(self) -> str:
return f"{self._package}/{self.getShortClassName()}"
@staticmethod
def unflattenFromString(str_: str) -> Optional["ComponentName"]:
if "/" in str_:
parts = str_.split("/", 1)
return ComponentName(parts[0], parts[1])
return None
def toString(self) -> str:
return f"ComponentInfo{{{self._package}/{self._classname}}}"
def __repr__(self):
return self.toString()
# ═══════════════════════════════════════════════════════════════
# PendingIntent
# ═══════════════════════════════════════════════════════════════
class PendingIntent(Stub):
"""A description of an Intent and target action to perform with it"""
FLAG_ONE_SHOT = 1 << 30
FLAG_NO_CREATE = 1 << 29
FLAG_CANCEL_CURRENT = 1 << 28
FLAG_UPDATE_CURRENT = 1 << 27
FLAG_IMMUTABLE = 1 << 26
_pending_intents: Dict[int, "PendingIntent"] = {}
_next_id = 1000
def __init__(self, intent: Intent, request_code: int, flags: int):
super().__init__()
self._intent = intent
self._request_code = request_code
self._flags = flags
self._id = PendingIntent._next_id
PendingIntent._next_id += 1
PendingIntent._pending_intents[self._id] = self
@staticmethod
def getActivity(context, request_code: int, intent: Intent, flags: int) -> "PendingIntent":
pi = PendingIntent(intent, request_code, flags)
pi._type = "activity"
return pi
@staticmethod
def getBroadcast(context, request_code: int, intent: Intent, flags: int) -> "PendingIntent":
pi = PendingIntent(intent, request_code, flags)
pi._type = "broadcast"
return pi
@staticmethod
def getService(context, request_code: int, intent: Intent, flags: int) -> "PendingIntent":
pi = PendingIntent(intent, request_code, flags)
pi._type = "service"
return pi
@staticmethod
def getActivities(context, request_code: int, intents: List[Intent], flags: int) -> "PendingIntent":
pi = PendingIntent(intents[0] if intents else Intent(), request_code, flags)
pi._type = "activities"
pi._intents = intents
return pi
def send(self):
"""Simulate sending the pending intent"""
pass
def cancel(self):
PendingIntent._pending_intents.pop(self._id, None)
def getIntent(self) -> Intent:
return self._intent
def getTargetPackage(self) -> str:
return self._intent.getPackage() or ""
def toString(self) -> str:
return f"PendingIntent{{{hex(id(self))}}}"
# ═══════════════════════════════════════════════════════════════
# AlarmManager
# ═══════════════════════════════════════════════════════════════
class AlarmManager(Stub):
"""AlarmManager — 调度定时操作"""
RTC_WAKEUP = 0
RTC = 1
ELAPSED_REALTIME = 3
ELAPSED_REALTIME_WAKEUP = 2
INTERVAL_FIFTEEN_MINUTES = 900000
INTERVAL_HALF_HOUR = 1800000
INTERVAL_HOUR = 3600000
INTERVAL_DAY = 86400000
def __init__(self):
super().__init__()
self._alarms: Dict[int, Dict] = {}
def set(self, type_: int, trigger_at_ms: int, operation: PendingIntent):
self._alarms[id(operation)] = {
"type": type_,
"trigger_at": trigger_at_ms,
"operation": operation,
"repeating": False,
}
def setRepeating(self, type_: int, trigger_at_ms: int, interval_ms: int, operation: PendingIntent):
self._alarms[id(operation)] = {
"type": type_,
"trigger_at": trigger_at_ms,
"interval": interval_ms,
"operation": operation,
"repeating": True,
}
def setExact(self, type_: int, trigger_at_ms: int, operation: PendingIntent):
self.set(type_, trigger_at_ms, operation)
def setAndAllowWhileIdle(self, type_: int, trigger_at_ms: int, operation: PendingIntent):
self.set(type_, trigger_at_ms, operation)
def setExactAndAllowWhileIdle(self, type_: int, trigger_at_ms: int, operation: PendingIntent):
self.set(type_, trigger_at_ms, operation)
def cancel(self, operation: PendingIntent):
self._alarms.pop(id(operation), None)
def getNextAlarmClock(self):
return None
# ═══════════════════════════════════════════════════════════════
# NotificationChannel
# ═══════════════════════════════════════════════════════════════
class NotificationChannel(Stub):
"""Notification channel for Android O+"""
IMPORTANCE_NONE = 0
IMPORTANCE_MIN = 1
IMPORTANCE_LOW = 2
IMPORTANCE_DEFAULT = 3
IMPORTANCE_HIGH = 4
IMPORTANCE_MAX = 5
IMPORTANCE_UNSPECIFIED = -1000
def __init__(self, channel_id: str, name: str, importance: int):
super().__init__()
self._id = channel_id
self._name = name
self._importance = importance
self._description = ""
self._enabled = True
self._show_badge = True
self._sound = None
self._lights = False
self._vibration = True
self._bypass_dnd = False
self._lockscreen_visibility = 0
self._group = None
self._can_bubble = False
def getId(self) -> str:
return self._id
def getName(self) -> str:
return self._name
def getImportance(self) -> int:
return self._importance
def setDescription(self, description: str):
self._description = description
def getDescription(self) -> str:
return self._description
def setShowBadge(self, show_badge: bool):
self._show_badge = show_badge
def canShowBadge(self) -> bool:
return self._show_badge
def enableLights(self, lights: bool):
self._lights = lights
def shouldShowLights(self) -> bool:
return self._lights
def enableVibration(self, vibration: bool):
self._vibration = vibration
def shouldVibrate(self) -> bool:
return self._vibration
def setBypassDnd(self, bypass_dnd: bool):
self._bypass_dnd = bypass_dnd
def canBypassDnd(self) -> bool:
return self._bypass_dnd
def setSound(self, sound: Any, audio_attributes: Any = None):
self._sound = sound
def getSound(self):
return self._sound
def setGroup(self, group_id: str):
self._group = group_id
def getGroup(self) -> Optional[str]:
return self._group
def setLockScreenVisibility(self, visibility: int):
self._lockscreen_visibility = visibility
def getLockScreenVisibility(self) -> int:
return self._lockscreen_visibility
def toString(self) -> str:
return f"NotificationChannel(id={self._id}, name={self._name}, importance={self._importance})"
class NotificationChannelGroup(Stub):
"""Group of notification channels"""
def __init__(self, group_id: str, name: str):
super().__init__()
self._id = group_id
self._name = name
self._channels: List[NotificationChannel] = []
def getId(self) -> str:
return self._id
def getName(self) -> str:
return self._name
def getChannels(self) -> List[NotificationChannel]:
return list(self._channels)
# ═══════════════════════════════════════════════════════════════
# Notification
# ═══════════════════════════════════════════════════════════════
class Notification(Stub):
"""Android Notification"""
DEFAULT_ALL = -1
DEFAULT_SOUND = 1
DEFAULT_VIBRATE = 2
DEFAULT_LIGHTS = 4
EXTRA_TITLE = "android.title"
EXTRA_TEXT = "android.text"
EXTRA_SUB_TEXT = "android.subText"
EXTRA_INFO_TEXT = "android.infoText"
EXTRA_SUMMARY_TEXT = "android.summaryText"
EXTRA_CHANNEL_ID = "android.intent.extra.CHANNEL_ID"
EXTRA_BIG_TEXT = "android.bigText"
EXTRA_PICTURE = "android.picture"
PRIORITY_MIN = -2
PRIORITY_LOW = -1
PRIORITY_DEFAULT = 0
PRIORITY_HIGH = 1
PRIORITY_MAX = 2
VISIBILITY_PRIVATE = 0
VISIBILITY_PUBLIC = 1
VISIBILITY_SECRET = -1
class Builder(Stub):
"""Notification builder pattern"""
def __init__(self, context, channel_id: Optional[str] = None):
super().__init__()
self._context = context
self._channel_id = channel_id or ""
self._title = ""
self._text = ""
self._sub_text = ""
self._info_text = ""
self._summary_text = ""
self._big_text = ""
self._small_icon = 0
self._large_icon = None
self._color = 0
self._priority = Notification.PRIORITY_DEFAULT
self._defaults = 0
self._auto_cancel = False
self._ongoing = False
self._when = 0
self._number = 0
self._content_intent = None
self._delete_intent = None
self._full_screen_intent = None
self._ticker = ""
self._visibility = Notification.VISIBILITY_PRIVATE
self._category = ""
self._group = ""
self._group_summary = False
self._public_version = None
self._extras: Dict[str, Any] = {}
self._actions: List[Dict] = []
self._style = None
self._badge_icon_type = 0
self._settings_text = None
self._uses_channel_defaults = False
def setChannelId(self, channel_id: str) -> "Notification.Builder":
self._channel_id = channel_id
return self
def setContentTitle(self, title: str) -> "Notification.Builder":
self._title = title
return self
def setContentText(self, text: str) -> "Notification.Builder":
self._text = text
return self
def setSubText(self, text: str) -> "Notification.Builder":
self._sub_text = text
return self
def setContentInfo(self, info: str) -> "Notification.Builder":
self._info_text = info
return self
def setSummaryText(self, text: str) -> "Notification.Builder":
self._summary_text = text
return self
def setSmallIcon(self, icon: int) -> "Notification.Builder":
self._small_icon = icon
return self
def setLargeIcon(self, icon: Any) -> "Notification.Builder":
self._large_icon = icon
return self
def setColor(self, color: int) -> "Notification.Builder":
self._color = color
return self
def setPriority(self, priority: int) -> "Notification.Builder":
self._priority = priority
return self
def setDefaults(self, defaults: int) -> "Notification.Builder":
self._defaults = defaults
return self
def setAutoCancel(self, auto_cancel: bool) -> "Notification.Builder":
self._auto_cancel = auto_cancel
return self
def setOngoing(self, ongoing: bool) -> "Notification.Builder":
self._ongoing = ongoing
return self
def setWhen(self, when: int) -> "Notification.Builder":
self._when = when
return self
def setNumber(self, number: int) -> "Notification.Builder":
self._number = number
return self
def setContentIntent(self, intent: PendingIntent) -> "Notification.Builder":
self._content_intent = intent
return self
def setDeleteIntent(self, intent: PendingIntent) -> "Notification.Builder":
self._delete_intent = intent
return self
def setFullScreenIntent(self, intent: PendingIntent, high_priority: bool) -> "Notification.Builder":
self._full_screen_intent = intent
return self
def setTicker(self, ticker: str) -> "Notification.Builder":
self._ticker = ticker
return self
def setVisibility(self, visibility: int) -> "Notification.Builder":
self._visibility = visibility
return self
def setCategory(self, category: str) -> "Notification.Builder":
self._category = category
return self
def setGroup(self, group: str) -> "Notification.Builder":
self._group = group
return self
def setGroupSummary(self, is_group_summary: bool) -> "Notification.Builder":
self._group_summary = is_group_summary
return self
def setPublicVersion(self, notification: "Notification") -> "Notification.Builder":
self._public_version = notification
return self
def addAction(self, icon: int, title: str, intent: PendingIntent) -> "Notification.Builder":
self._actions.append({"icon": icon, "title": title, "intent": intent})
return self
def setStyle(self, style: Any) -> "Notification.Builder":
self._style = style
return self
def setBadgeIconType(self, icon_type: int) -> "Notification.Builder":
self._badge_icon_type = icon_type
return self
def setSettingsText(self, text: str) -> "Notification.Builder":
self._settings_text = text
return self
def addExtras(self, extras: Dict[str, Any]) -> "Notification.Builder":
if extras:
self._extras.update(extras)
return self
def extend(self, builder: Any) -> "Notification.Builder":
return self
def build(self) -> "Notification":
n = Notification()
n._channel_id = self._channel_id
n._title = self._title
n._text = self._text
n._sub_text = self._sub_text
n._info_text = self._info_text
n._summary_text = self._summary_text
n._big_text = self._big_text
n._small_icon = self._small_icon
n._large_icon = self._large_icon
n._color = self._color
n._priority = self._priority
n._defaults = self._defaults
n._auto_cancel = self._auto_cancel
n._ongoing = self._ongoing
n._when = self._when or int(time.time() * 1000)
n._number = self._number
n._content_intent = self._content_intent
n._delete_intent = self._delete_intent
n._full_screen_intent = self._full_screen_intent
n._ticker = self._ticker
n._visibility = self._visibility
n._category = self._category
n._group = self._group
n._group_summary = self._group_summary
n._public_version = self._public_version
n._actions = list(self._actions)
n._style = self._style
n._extras = dict(self._extras)
return n
def __init__(self):
super().__init__()
self._channel_id = ""
self._title = ""
self._text = ""
self._sub_text = ""
self._info_text = ""
self._summary_text = ""
self._big_text = ""
self._small_icon = 0
self._large_icon = None
self._color = 0
self._priority = self.PRIORITY_DEFAULT
self._defaults = 0
self._auto_cancel = False
self._ongoing = False
self._when = 0
self._number = 0
self._content_intent = None
self._delete_intent = None
self._full_screen_intent = None
self._ticker = ""
self._visibility = self.VISIBILITY_PRIVATE
self._category = ""
self._group = ""
self._group_summary = False
self._public_version = None
self._extras: Dict[str, Any] = {}
self._actions: List[Dict] = []
self._style = None
def getChannelId(self) -> str:
return self._channel_id
def toString(self) -> str:
return f"Notification(channel={self._channel_id}, title={self._title})"
class NotificationCompat(Stub):
"""NotificationCompat — 兼容版本"""
class Builder(Stub):
def __init__(self, context, channel_id: Optional[str] = None):
super().__init__()
self._builder = Notification.Builder(context, channel_id)
def setContentTitle(self, title: str) -> "NotificationCompat.Builder":
self._builder.setContentTitle(title)
return self
def setContentText(self, text: str) -> "NotificationCompat.Builder":
self._builder.setContentText(text)
return self
def setSmallIcon(self, icon: int) -> "NotificationCompat.Builder":
self._builder.setSmallIcon(icon)
return self
def setPriority(self, priority: int) -> "NotificationCompat.Builder":
self._builder.setPriority(priority)
return self
def setAutoCancel(self, auto_cancel: bool) -> "NotificationCompat.Builder":
self._builder.setAutoCancel(auto_cancel)
return self
def setContentIntent(self, intent: PendingIntent) -> "NotificationCompat.Builder":
self._builder.setContentIntent(intent)
return self
def setDefaults(self, defaults: int) -> "NotificationCompat.Builder":
self._builder.setDefaults(defaults)
return self
def build(self) -> Notification:
return self._builder.build()
# ═══════════════════════════════════════════════════════════════
# NotificationManager
# ═══════════════════════════════════════════════════════════════
class NotificationManager(Stub):
"""NotificationManager — 发送通知"""
IMPORTANCE_NONE = 0
IMPORTANCE_MIN = 1
IMPORTANCE_LOW = 2
IMPORTANCE_DEFAULT = 3
IMPORTANCE_HIGH = 4
IMPORTANCE_MAX = 5
IMPORTANCE_UNSPECIFIED = -1000
def __init__(self):
super().__init__()
self._notifications: Dict[int, Notification] = {}
self._channels: Dict[str, NotificationChannel] = {}
self._groups: Dict[str, NotificationChannelGroup] = {}
self._notification_id_counter = 0
def notify(self, id_: int, notification: Notification):
self._notifications[id_] = notification
sys.stderr.write(
f"[NotificationManager] notify id={id_}: "
f"title={notification._title} text={notification._text}\n"
)
def notifyAsPackage(self, package_name: str, tag: Optional[str], id_: int, notification: Notification):
self.notify(id_, notification)
def cancel(self, id_: int):
self._notifications.pop(id_, None)
def cancelAll(self):
self._notifications.clear()
def cancelAsPackage(self, package_name: str, tag: Optional[str], id_: int):
self.cancel(id_)
def createNotificationChannel(self, channel: NotificationChannel):
self._channels[channel.getId()] = channel
sys.stderr.write(
f"[NotificationManager] create channel: {channel.getId()}\n"
)
def createNotificationChannels(self, channels: List[NotificationChannel]):
for c in channels:
self.createNotificationChannel(c)
def getNotificationChannel(self, channel_id: str) -> Optional[NotificationChannel]:
return self._channels.get(channel_id)
def getNotificationChannels(self) -> List[NotificationChannel]:
return list(self._channels.values())
def deleteNotificationChannel(self, channel_id: str):
self._channels.pop(channel_id, None)
def createNotificationChannelGroup(self, group: NotificationChannelGroup):
self._groups[group.getId()] = group
def getNotificationChannelGroups(self) -> List[NotificationChannelGroup]:
return list(self._groups.values())
def getActiveNotifications(self) -> List[Notification]:
return list(self._notifications.values())
def areNotificationsEnabled(self) -> bool:
return True
def isNotificationPolicyAccessGranted(self) -> bool:
return True
def matchesCallFilter(self, address: Any) -> bool:
return True
def toString(self) -> str:
return f"NotificationManager(notifications={len(self._notifications)})"
# ═══════════════════════════════════════════════════════════════
# Dialog / AlertDialog / ProgressDialog / DatePickerDialog / TimePickerDialog
# ═══════════════════════════════════════════════════════════════
class Dialog(Stub):
"""Base dialog class"""
def __init__(self, context, theme_res_id: int = 0):
super().__init__()
self._context = context
self._theme_res_id = theme_res_id
self._showing = False
self._cancelable = True
self._on_cancel_listener = None
self._on_dismiss_listener = None
self._on_show_listener = None
self._title = ""
self._window = None
def show(self):
self._showing = True
sys.stderr.write(f"[Dialog] show: {self.__class__.__name__}\n")
def dismiss(self):
self._showing = False
sys.stderr.write(f"[Dialog] dismiss: {self.__class__.__name__}\n")
def isShowing(self) -> bool:
return self._showing
def cancel(self):
self.dismiss()
if self._on_cancel_listener:
self._on_cancel_listener.onCancel(self)
def setCancelable(self, flag: bool):
self._cancelable = flag
def setCanceledOnTouchOutside(self, cancel: bool):
pass
def setTitle(self, title: str):
self._title = title
def getContext(self):
return self._context
def setOnCancelListener(self, listener):
self._on_cancel_listener = listener
def setOnDismissListener(self, listener):
self._on_dismiss_listener = listener
def setOnShowListener(self, listener):
self._on_show_listener = listener
def getWindow(self):
return self._window
def findViewById(self, id_: int):
return None
def onBackPressed(self):
if self._cancelable:
self.cancel()
class AlertDialog(Dialog):
"""Alert dialog with builder pattern"""
BUTTON_POSITIVE = -1
BUTTON_NEGATIVE = -2
BUTTON_NEUTRAL = -3
def __init__(self, context, theme_res_id: int = 0):
super().__init__(context, theme_res_id)
self._message = ""
self._buttons: Dict[int, Dict] = {}
self._items: List[str] = []
self._single_choice_items = None
self._multi_choice_items = None
self._selected_index = -1
self._selected_indices: List[int] = []
self._view = None
self._icon = 0
self._custom_title = None
class Builder(Stub):
"""AlertDialog builder"""
def __init__(self, context, theme_res_id: int = 0):
super().__init__()
self._context = context
self._theme_res_id = theme_res_id
self._title = ""
self._message = ""
self._positive_text = ""
self._positive_listener = None
self._negative_text = ""
self._negative_listener = None
self._neutral_text = ""
self._neutral_listener = None
self._cancelable = True
self._on_cancel_listener = None
self._items: List[str] = []
self._on_item_click_listener = None
self._single_choice_items = None
self._single_choice_selected = -1
self._single_choice_listener = None
self._multi_choice_items = None
self._multi_choice_selected = None
self._multi_choice_listener = None
self._icon = 0
self._view = None
self._custom_title_view = None
def setTitle(self, title: str) -> "AlertDialog.Builder":
self._title = title
return self
def setMessage(self, message: str) -> "AlertDialog.Builder":
self._message = message
return self
def setPositiveButton(self, text: str, listener=None) -> "AlertDialog.Builder":
self._positive_text = text
self._positive_listener = listener
return self
def setNegativeButton(self, text: str, listener=None) -> "AlertDialog.Builder":
self._negative_text = text
self._negative_listener = listener
return self
def setNeutralButton(self, text: str, listener=None) -> "AlertDialog.Builder":
self._neutral_text = text
self._neutral_listener = listener
return self
def setCancelable(self, cancelable: bool) -> "AlertDialog.Builder":
self._cancelable = cancelable
return self
def setOnCancelListener(self, listener) -> "AlertDialog.Builder":
self._on_cancel_listener = listener
return self
def setItems(self, items: List[str], listener=None) -> "AlertDialog.Builder":
self._items = list(items)
self._on_item_click_listener = listener
return self
def setSingleChoiceItems(self, items: List[str], checked_item: int, listener=None) -> "AlertDialog.Builder":
self._single_choice_items = list(items)
self._single_choice_selected = checked_item
self._single_choice_listener = listener
return self
def setMultiChoiceItems(self, items: List[str], checked_items: List[bool], listener=None) -> "AlertDialog.Builder":
self._multi_choice_items = list(items)
self._multi_choice_selected = checked_items or []
self._multi_choice_listener = listener
return self
def setIcon(self, icon: int) -> "AlertDialog.Builder":
self._icon = icon
return self
def setView(self, view: Any) -> "AlertDialog.Builder":
self._view = view
return self
def setCustomTitle(self, view: Any) -> "AlertDialog.Builder":
self._custom_title_view = view
return self
def create(self) -> "AlertDialog":
dialog = AlertDialog(self._context, self._theme_res_id)
dialog._title = self._title
dialog._message = self._message
dialog._cancelable = self._cancelable
dialog._icon = self._icon
dialog._view = self._view
if self._positive_text:
dialog._buttons[AlertDialog.BUTTON_POSITIVE] = {
"text": self._positive_text,
"listener": self._positive_listener,
}
if self._negative_text:
dialog._buttons[AlertDialog.BUTTON_NEGATIVE] = {
"text": self._negative_text,
"listener": self._negative_listener,
}
if self._neutral_text:
dialog._buttons[AlertDialog.BUTTON_NEUTRAL] = {
"text": self._neutral_text,
"listener": self._neutral_listener,
}
dialog._items = list(self._items)
dialog._single_choice_items = self._single_choice_items
dialog._multi_choice_items = self._multi_choice_items
return dialog
def show(self) -> "AlertDialog":
dialog = self.create()
dialog.show()
return dialog
class ProgressDialog(AlertDialog):
"""Progress dialog with a progress bar"""
STYLE_SPINNER = 0
STYLE_HORIZONTAL = 1
def __init__(self, context, theme_res_id: int = 0):
super().__init__(context, theme_res_id)
self._progress_style = ProgressDialog.STYLE_SPINNER
self._progress = 0
self._max = 100
self._indeterminate = True
self._progress_number_format = "%d/%d"
self._progress_percent_format = "%d%%"
def setProgressStyle(self, style: int):
self._progress_style = style
def setProgress(self, value: int):
self._progress = value
def getProgress(self) -> int:
return self._progress
def setMax(self, max_: int):
self._max = max_
def getMax(self) -> int:
return self._max
def setIndeterminate(self, indeterminate: bool):
self._indeterminate = indeterminate
def isIndeterminate(self) -> bool:
return self._indeterminate
def incrementProgressBy(self, diff: int):
self._progress = min(self._max, max(0, self._progress + diff))
@staticmethod
def show(context, title: str, message: str, indeterminate: bool = True, cancelable: bool = False) -> "ProgressDialog":
dialog = ProgressDialog(context)
dialog.setTitle(title)
dialog._message = message
dialog._indeterminate = indeterminate
dialog.setCancelable(cancelable)
dialog.show()
return dialog
class DatePickerDialog(AlertDialog):
"""Date picker dialog"""
def __init__(self, context, listener=None, year: int = 2024, month: int = 0, day_of_month: int = 1, theme_res_id: int = 0):
super().__init__(context, theme_res_id)
self._listener = listener
self._year = year
self._month = month
self._day_of_month = day_of_month
self._date_picker = None
def getDatePicker(self):
return self._date_picker
def updateDate(self, year: int, month: int, day_of_month: int):
self._year = year
self._month = month
self._day_of_month = day_of_month
def onDateChanged(self, view, year: int, month: int, day: int):
self._year = year
self._month = month
self._day_of_month = day
class OnDateSetListener:
def onDateSet(self, view, year: int, month: int, day_of_month: int):
pass
class TimePickerDialog(AlertDialog):
"""Time picker dialog"""
def __init__(self, context, listener=None, hour_of_day: int = 12, minute: int = 0, is24_hour_view: bool = True, theme_res_id: int = 0):
super().__init__(context, theme_res_id)
self._listener = listener
self._hour_of_day = hour_of_day
self._minute = minute
self._is24_hour_view = is24_hour_view
class OnTimeSetListener:
def onTimeSet(self, view, hour_of_day: int, minute: int):
pass
# ═══════════════════════════════════════════════════════════════
# Fragment / FragmentManager / FragmentTransaction
# ═══════════════════════════════════════════════════════════════
class Fragment(Stub):
"""Fragment — UI 片段"""
def __init__(self):
super().__init__()
self._arguments: Optional[Bundle] = None
self._activity = None
self._view = None
self._fragment_manager = None
self._state = 0
self._tag = None
self._id = -1
self._container_id = -1
self._menu = True
self._retain_instance = False
self._target_fragment = None
self._target_request_code = -1
self._user_visible_hint = True
def setArguments(self, args: "Bundle"):
self._arguments = args
def getArguments(self) -> Optional["Bundle"]:
return self._arguments
def getActivity(self):
return self._activity
def getContext(self):
return self._activity
def getFragmentManager(self) -> Optional["FragmentManager"]:
return self._fragment_manager
def getView(self):
return self._view
def getResources(self):
if self._activity:
return getattr(self._activity, 'getResources', lambda: None)()
return None
def getString(self, res_id: int, *args) -> str:
return str(res_id)
def getTag(self) -> Optional[str]:
return self._tag
def setId(self, id_: int):
self._id = id_
def getId(self) -> int:
return self._id
def onAttach(self, context):
pass
def onCreate(self, savedInstanceState: Optional["Bundle"] = None):
pass
def onCreateView(self, inflater, container, savedInstanceState):
return None
def onViewCreated(self, view, savedInstanceState: Optional["Bundle"] = None):
pass
def onStart(self):
pass
def onResume(self):
pass
def onPause(self):
pass
def onStop(self):
pass
def onDestroyView(self):
pass
def onDestroy(self):
pass
def onDetach(self):
pass
def onActivityCreated(self, savedInstanceState: Optional["Bundle"] = None):
pass
def onSaveInstanceState(self, out_state: "Bundle"):
pass
def onViewStateRestored(self, savedInstanceState: Optional["Bundle"] = None):
pass
def isAdded(self) -> bool:
return self._activity is not None
def isDetached(self) -> bool:
return self._activity is None
def isVisible(self) -> bool:
return False
def isRemoving(self) -> bool:
return False
def isInLayout(self) -> bool:
return False
def isResumed(self) -> bool:
return self._state >= 7
def setHasOptionsMenu(self, has_menu: bool):
self._menu = has_menu
def setRetainInstance(self, retain: bool):
self._retain_instance = retain
def getRetainInstance(self) -> bool:
return self._retain_instance
def setTargetFragment(self, fragment: "Fragment", request_code: int):
self._target_fragment = fragment
self._target_request_code = request_code
def getTargetFragment(self) -> Optional["Fragment"]:
return self._target_fragment
def getTargetRequestCode(self) -> int:
return self._target_request_code
def setUserVisibleHint(self, is_visible_to_user: bool):
self._user_visible_hint = is_visible_to_user
def getUserVisibleHint(self) -> bool:
return self._user_visible_hint
def registerForContextMenu(self, view):
pass
def unregisterForContextMenu(self, view):
pass
class FragmentTransaction(Stub):
"""FragmentTransaction — 管理 Fragment 事务"""
TRANSIT_ENTER_MASK = 0x1000
TRANSIT_EXIT_MASK = 0x2000
TRANSIT_FRAGMENT_FADE = 0x1001
TRANSIT_FRAGMENT_OPEN = 0x1003
TRANSIT_FRAGMENT_CLOSE = 0x1004
TRANSIT_NONE = 0
TRANSIT_UNSET = -1
def __init__(self):
super().__init__()
self._ops: List[Dict] = []
self._transition = FragmentTransaction.TRANSIT_NONE
self._transition_style = 0
self._allow_state_loss = False
self._commit_allowing_state_loss = False
def add(self, container_view_id: int, fragment: Fragment, tag: Optional[str] = None) -> "FragmentTransaction":
self._ops.append({"type": "add", "id": container_view_id, "fragment": fragment, "tag": tag})
return self
def replace(self, container_view_id: int, fragment: Fragment, tag: Optional[str] = None) -> "FragmentTransaction":
self._ops.append({"type": "replace", "id": container_view_id, "fragment": fragment, "tag": tag})
return self
def remove(self, fragment: Fragment) -> "FragmentTransaction":
self._ops.append({"type": "remove", "fragment": fragment})
return self
def hide(self, fragment: Fragment) -> "FragmentTransaction":
self._ops.append({"type": "hide", "fragment": fragment})
return self
def show(self, fragment: Fragment) -> "FragmentTransaction":
self._ops.append({"type": "show", "fragment": fragment})
return self
def detach(self, fragment: Fragment) -> "FragmentTransaction":
self._ops.append({"type": "detach", "fragment": fragment})
return self
def attach(self, fragment: Fragment) -> "FragmentTransaction":
self._ops.append({"type": "attach", "fragment": fragment})
return self
def addToBackStack(self, name: Optional[str] = None) -> "FragmentTransaction":
self._ops.append({"type": "addToBackStack", "name": name})
return self
def setTransition(self, transit: int) -> "FragmentTransaction":
self._transition = transit
return self
def setTransitionStyle(self, style: int) -> "FragmentTransaction":
self._transition_style = style
return self
def setCustomAnimations(self, enter: int, exit: int, pop_enter: int = 0, pop_exit: int = 0) -> "FragmentTransaction":
return self
def disallowAddToBackStack(self) -> "FragmentTransaction":
return self
def setBreadCrumbShortTitle(self, title: str) -> "FragmentTransaction":
return self
def setBreadCrumbTitle(self, title: str) -> "FragmentTransaction":
return self
def commit(self) -> int:
return 0
def commitAllowingStateLoss(self) -> int:
return 0
def commitNow(self) -> int:
return 0
def commitNowAllowingStateLoss(self) -> int:
return 0
def isAddToBackStackAllowed(self) -> bool:
return True
class FragmentManager(Stub):
"""FragmentManager — Fragment 管理器"""
POP_BACK_STACK_INCLUSIVE = 1
def __init__(self):
super().__init__()
self._fragments: Dict[str, Fragment] = {}
self._back_stack: List[Dict] = []
def beginTransaction(self) -> FragmentTransaction:
return FragmentTransaction()
def findFragmentById(self, id_: int) -> Optional[Fragment]:
for f in self._fragments.values():
if f.getId() == id_:
return f
return None
def findFragmentByTag(self, tag: str) -> Optional[Fragment]:
return self._fragments.get(tag)
def popBackStack(self):
if self._back_stack:
self._back_stack.pop()
def popBackStackImmediate(self, name: str, flags: int) -> bool:
return True
def getBackStackEntryCount(self) -> int:
return len(self._back_stack)
def getFragment(self, bundle: "Bundle", key: str) -> Optional[Fragment]:
return None
def getFragments(self) -> List[Fragment]:
return list(self._fragments.values())
def saveFragmentInstanceState(self, fragment: Fragment):
return None
def isDestroyed(self) -> bool:
return False
def isStateSaved(self) -> bool:
return False
def putFragment(self, bundle: "Bundle", key: str, fragment: Fragment):
pass
def executePendingTransactions(self) -> bool:
return True
def clearFragmentResult(self, request_key: str):
pass
def setFragmentResult(self, request_key: str, result: "Bundle"):
pass
def setFragmentResultListener(self, lifecycle: Any, listener: Any):
pass
def registerFragmentLifecycleCallbacks(self, cb: Any, recursive: bool):
pass
def unregisterFragmentLifecycleCallbacks(self, cb: Any):
pass
# ═══════════════════════════════════════════════════════════════
# Activity
# ═══════════════════════════════════════════════════════════════
class Activity(Stub):
"""Activity — 应用界面入口"""
# 结果码
RESULT_OK = -1
RESULT_CANCELED = 0
RESULT_FIRST_USER = 1
def __init__(self):
super().__init__()
self._created = False
self._started = False
self._resumed = False
self._destroyed = False
self._intent: Optional[Intent] = None
self._callbacks: Dict[int, Tuple[int, Intent]] = {}
self._fragment_manager = FragmentManager()
self._application = None
self._title = ""
self._request_code_counter = 0
def onCreate(self, savedInstanceState: Optional["Bundle"] = None):
self._created = True
sys.stderr.write(f"[Activity] onCreate: {self.__class__.__name__}\n")
def onStart(self):
self._started = True
sys.stderr.write(f"[Activity] onStart: {self.__class__.__name__}\n")
def onResume(self):
self._resumed = True
sys.stderr.write(f"[Activity] onResume: {self.__class__.__name__}\n")
def onPause(self):
self._resumed = False
sys.stderr.write(f"[Activity] onPause: {self.__class__.__name__}\n")
def onStop(self):
self._started = False
sys.stderr.write(f"[Activity] onStop: {self.__class__.__name__}\n")
def onDestroy(self):
self._destroyed = True
self._created = False
sys.stderr.write(f"[Activity] onDestroy: {self.__class__.__name__}\n")
def onRestart(self):
sys.stderr.write(f"[Activity] onRestart: {self.__class__.__name__}\n")
def onBackPressed(self):
sys.stderr.write("[Activity] onBackPressed\n")
def onSaveInstanceState(self, out_state: "Bundle"):
pass
def onRestoreInstanceState(self, savedInstanceState: "Bundle"):
pass
def onNewIntent(self, intent: Intent):
self._intent = intent
def onActivityResult(self, request_code: int, result_code: int, data: Optional[Intent]):
pass
def onRequestPermissionsResult(self, request_code: int, permissions: List[str], grant_results: List[int]):
pass
def setContentView(self, layout_res_id: int):
sys.stderr.write(f"[Activity] setContentView: {layout_res_id}\n")
def findViewById(self, id_: int) -> Any:
return None
def startActivity(self, intent: Intent):
sys.stderr.write(
f"[Activity] startActivity: action={intent.getAction()} "
f"pkg={intent.getPackage()}\n"
)
def startActivityForResult(self, intent: Intent, request_code: int, options: Optional["Bundle"] = None):
sys.stderr.write(
f"[Activity] startActivityForResult: code={request_code} "
f"action={intent.getAction()}\n"
)
def setResult(self, result_code: int, data: Optional[Intent] = None):
sys.stderr.write(f"[Activity] setResult: code={result_code}\n")
def finish(self):
sys.stderr.write(f"[Activity] finish: {self.__class__.__name__}\n")
self.onPause()
self.onStop()
self.onDestroy()
def finishActivity(self, request_code: int):
pass
def getIntent(self) -> Optional[Intent]:
return self._intent
def setIntent(self, intent: Intent):
self._intent = intent
def getString(self, res_id: int, *args) -> str:
return str(res_id)
def getResources(self):
return None
def getApplication(self):
return self._application
def getFragmentManager(self) -> FragmentManager:
return self._fragment_manager
def getSupportFragmentManager(self) -> FragmentManager:
return self._fragment_manager
def getPackageManager(self):
from .content_pm import PackageManager
return PackageManager()
def getPackageName(self) -> str:
return _package_name
def getContentResolver(self):
from .content import ContentResolver
return ContentResolver()
def getSystemService(self, name: str):
return android_context.getSystemService(name)
def isFinishing(self) -> bool:
return self._destroyed
def isDestroyed(self) -> bool:
return self._destroyed
def recreate(self):
self.onDestroy()
self.onCreate(None)
self.onStart()
self.onResume()
def getPreferences(self, mode: int):
from .content import SharedPreferences
return SharedPreferences(_package_name + "_preferences")
def getSharedPreferences(self, name: str, mode: int):
from .content import SharedPreferences
return SharedPreferences(name)
def getApplicationContext(self):
return android_context
def getBaseContext(self):
return android_context
def getCallingActivity(self) -> Optional[ComponentName]:
return None
def getCallingPackage(self) -> Optional[str]:
return None
def getTaskId(self) -> int:
return 1
def hasWindowFocus(self) -> bool:
return True
def isInMultiWindowMode(self) -> bool:
return False
def isInPictureInPictureMode(self) -> bool:
return False
def moveTaskToBack(self, non_root: bool) -> bool:
return True
def onLowMemory(self):
pass
def onTrimMemory(self, level: int):
pass
def onConfigurationChanged(self, config):
pass
def onMultiWindowModeChanged(self, is_in_multi_window_mode: bool, new_config):
pass
def onPictureInPictureModeChanged(self, is_in_pip_mode: bool, new_config):
pass
# ═══════════════════════════════════════════════════════════════
# Service
# ═══════════════════════════════════════════════════════════════
class Service(Stub):
"""Service — 后台服务"""
START_CONTINUATION_MASK = 0xF
START_FLAG_REDELIVERY = 1
START_FLAG_RETRY = 2
START_NOT_STICKY = 2
START_REDELIVER_INTENT = 3
START_STICKY = 1
START_STICKY_COMPATIBILITY = 0
STOP_FOREGROUND_DETACH = 1
STOP_FOREGROUND_REMOVE = 2
def __init__(self):
super().__init__()
self._started = False
def onCreate(self):
self._started = True
sys.stderr.write(f"[Service] onCreate: {self.__class__.__name__}\n")
def onStartCommand(self, intent: Optional[Intent], flags: int, start_id: int) -> int:
return Service.START_NOT_STICKY
def onBind(self, intent: Intent):
return None
def onUnbind(self, intent: Intent) -> bool:
return False
def onRebind(self, intent: Intent):
pass
def onDestroy(self):
self._started = False
sys.stderr.write(f"[Service] onDestroy: {self.__class__.__name__}\n")
def stopSelf(self):
self.onDestroy()
def stopSelfResult(self, start_id: int) -> bool:
self.onDestroy()
return True
def startForeground(self, id_: int, notification: Notification):
pass
def stopForeground(self, flags: int):
pass
def getApplication(self):
return None
def getClass(self):
return self.__class__
# ═══════════════════════════════════════════════════════════════
# Application
# ═══════════════════════════════════════════════════════════════
class Application(Stub):
"""Application — 应用级别上下文"""
def __init__(self):
super().__init__()
self._activity_lifecycle_callbacks: List = []
self._on_low_memory_listeners: List = []
self._on_trim_memory_listeners: List = []
def onCreate(self):
sys.stderr.write(f"[Application] onCreate: {self.__class__.__name__}\n")
def onTerminate(self):
pass
def onConfigurationChanged(self, new_config):
pass
def onLowMemory(self):
pass
def onTrimMemory(self, level: int):
pass
def registerActivityLifecycleCallbacks(self, callback):
self._activity_lifecycle_callbacks.append(callback)
def unregisterActivityLifecycleCallbacks(self, callback):
try:
self._activity_lifecycle_callbacks.remove(callback)
except ValueError:
pass
def getApplicationContext(self):
return android_context
def getPackageManager(self):
from .content_pm import PackageManager
return PackageManager()
def getContentResolver(self):
from .content import ContentResolver
return ContentResolver()
def getSystemService(self, name: str):
return android_context.getSystemService(name)
def getSharedPreferences(self, name: str, mode: int):
from .content import SharedPreferences
return SharedPreferences(name)
def getFilesDir(self):
return os.path.join(_app_data_dir, "files")
def getCacheDir(self):
return os.path.join(_app_data_dir, "cache")
def getBaseContext(self):
return android_context
# ═══════════════════════════════════════════════════════════════
# ActivityManager
# ═══════════════════════════════════════════════════════════════
class ActivityManager(Stub):
"""ActivityManager — 管理 Activity 运行状态"""
RECENT_IGNORE_UNAVAILABLE = 0x02
RECENT_WITH_EXCLUDED = 0x01
MOVE_TASK_WITH_HOME = 0x01
MOVE_TASK_NO_USER_ACTION = 0x02
class RunningAppProcessInfo(Stub):
"""Information about a running process"""
IMPORTANCE_FOREGROUND = 100
IMPORTANCE_VISIBLE = 200
IMPORTANCE_SERVICE = 300
IMPORTANCE_BACKGROUND = 400
IMPORTANCE_EMPTY = 500
IMPORTANCE_FOREGROUND_SERVICE = 125
IMPORTANCE_TOP_SLEEPING = 150
IMPORTANCE_CACHED = 400
IMPORTANCE_GONE = 1000
def __init__(self):
super().__init__()
self.processName = ""
self.pid = 0
self.uid = 0
self.importance = self.IMPORTANCE_FOREGROUND
self.lru = 0
self.importanceReasonCode = 0
self.importanceReasonPid = 0
self.importanceReasonComponent = None
self.pkgList: List[str] = []
class AppTask(Stub):
"""Represents a task managed by ActivityManager"""
def finishAndRemoveTask(self):
pass
def getTaskInfo(self):
return None
def moveToFront(self):
pass
def setExcludeFromRecents(self, exclude: bool):
pass
class MemoryInfo(Stub):
"""Memory information"""
def __init__(self):
super().__init__()
self.availMem = 0
self.totalMem = 0
self.threshold = 0
self.lowMemory = False
def __init__(self):
super().__init__()
self._memory_info = self.MemoryInfo()
def getMemoryInfo(self) -> "ActivityManager.MemoryInfo":
return self._memory_info
def getRunningAppProcesses(self) -> Optional[List["ActivityManager.RunningAppProcessInfo"]]:
return []
def killBackgroundProcesses(self, package_name: str):
pass
def clearApplicationUserData(self) -> bool:
return True
def getRecentTasks(self, max_num: int, flags: int) -> List:
return []
def getAppTasks(self) -> List["ActivityManager.AppTask"]:
return []
def moveTaskToFront(self, task_id: int, flags: int):
pass
def isBackgroundRestricted(self) -> bool:
return False
def isLowRamDevice(self) -> bool:
return False
def getLauncherLargeIconSize(self) -> int:
return 48
# ═══════════════════════════════════════════════════════════════
# TaskStackBuilder
# ═══════════════════════════════════════════════════════════════
class TaskStackBuilder(Stub):
"""Builder for synthetic back stack"""
def __init__(self, context):
super().__init__()
self._context = context
self._intents: List[Intent] = []
@staticmethod
def create(context) -> "TaskStackBuilder":
return TaskStackBuilder(context)
def addNextIntent(self, intent: Intent) -> "TaskStackBuilder":
self._intents.append(intent)
return self
def addNextIntentWithParentStack(self, intent: Intent) -> "TaskStackBuilder":
self._intents.append(intent)
return self
def addParentStack(self, activity_cls: type) -> "TaskStackBuilder":
return self
def startActivities(self, options: Optional["Bundle"] = None):
for intent in self._intents:
sys.stderr.write(f"[TaskStackBuilder] start activity: {intent}\n")
def startActivitiesIfNeeded(self, options: Optional["Bundle"] = None):
self.startActivities(options)
def getIntent(self, request_code: int) -> Optional[Intent]:
if self._intents:
return self._intents[-1]
return None
def editIntentAt(self, index: int) -> Optional[Intent]:
if 0 <= index < len(self._intents):
return self._intents[index]
return None
def getIntentCount(self) -> int:
return len(self._intents)
# ═══════════════════════════════════════════════════════════════
# Bundle (forward reference for Fragment uses)
# ═══════════════════════════════════════════════════════════════
from .os import Bundle
# ═══════════════════════════════════════════════════════════════
# __all__
# ═══════════════════════════════════════════════════════════════
__all__ = [
"Intent",
"ComponentName",
"PendingIntent",
"AlarmManager",
"Notification",
"NotificationChannel",
"NotificationChannelGroup",
"NotificationManager",
"NotificationCompat",
"Dialog",
"AlertDialog",
"ProgressDialog",
"DatePickerDialog",
"TimePickerDialog",
"Fragment",
"FragmentManager",
"FragmentTransaction",
"Activity",
"Service",
"Application",
"ActivityManager",
"TaskStackBuilder",
]