feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python
52 个模块覆盖 Android + Java + org.json 标准库
This commit is contained in:
commit
bfe27fdc08
104 files changed
+58750
No files matched your search
@@ -0,0 +1,801 @@
|
||||
"""
|
||||
Android PackageManager 组件 — PackageManager, PackageInfo, ApplicationInfo 等
|
||||
方法签名完全对齐 Android SDK
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from typing import Any, Dict, List, Optional, Set
|
||||
|
||||
from .._core import (
|
||||
Stub, AndroidOnlyError, android_context,
|
||||
resolve_android_path, to_android_path,
|
||||
_sdcard_root, _app_data_dir, _package_name,
|
||||
)
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 数据存储路径
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
_PACKAGE_DATA_DIR = os.path.join(_app_data_dir, "package_data")
|
||||
os.makedirs(_PACKAGE_DATA_DIR, exist_ok=True)
|
||||
|
||||
_DEFAULT_PACKAGE_INFO_PATH = os.path.join(_PACKAGE_DATA_DIR, f"{_package_name}.json")
|
||||
|
||||
|
||||
def _get_default_package_info() -> Dict[str, Any]:
|
||||
"""获取默认包信息"""
|
||||
return {
|
||||
"packageName": _package_name,
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": 1,
|
||||
"applicationInfo": {
|
||||
"name": _package_name,
|
||||
"packageName": _package_name,
|
||||
"className": f"{_package_name}.MainApplication",
|
||||
"icon": 0,
|
||||
"targetSdkVersion": 34,
|
||||
"sourceDir": os.path.join(_app_data_dir, "base.apk"),
|
||||
"dataDir": _app_data_dir,
|
||||
"enabled": True,
|
||||
"flags": 0,
|
||||
"theme": 0,
|
||||
"labelRes": 0,
|
||||
"descriptionRes": 0,
|
||||
"logo": 0,
|
||||
"banner": 0,
|
||||
"processName": _package_name,
|
||||
"uid": 10001,
|
||||
"manageSpaceActivityName": "",
|
||||
"taskAffinity": "",
|
||||
"permission": "",
|
||||
},
|
||||
"activities": [],
|
||||
"services": [],
|
||||
"receivers": [],
|
||||
"providers": [],
|
||||
"permissions": [],
|
||||
"requestedPermissions": [
|
||||
"android.permission.INTERNET",
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
],
|
||||
"features": {
|
||||
"android.hardware.camera": True,
|
||||
"android.hardware.wifi": True,
|
||||
"android.hardware.bluetooth": True,
|
||||
"android.hardware.location": True,
|
||||
"android.hardware.sensor.accelerometer": True,
|
||||
"android.hardware.sensor.gyroscope": True,
|
||||
"android.hardware.touchscreen": True,
|
||||
"android.hardware.microphone": True,
|
||||
"android.hardware.nfc": False,
|
||||
"android.hardware.telephony": True,
|
||||
"android.software.picture_in_picture": True,
|
||||
"android.hardware.usb.host": False,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# PackageItemInfo (基类)
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class PackageItemInfo(Stub):
|
||||
"""PackageItemInfo — 包条目信息基类"""
|
||||
|
||||
def __init__(self, data: Optional[Dict[str, Any]] = None):
|
||||
super().__init__()
|
||||
data = data or {}
|
||||
self.name = data.get("name", "")
|
||||
self.packageName = data.get("packageName", "")
|
||||
self.labelRes = data.get("labelRes", 0)
|
||||
self.nonLocalizedLabel = data.get("nonLocalizedLabel", None)
|
||||
self.icon = data.get("icon", 0)
|
||||
self.banner = data.get("banner", 0)
|
||||
self.logo = data.get("logo", 0)
|
||||
|
||||
def loadLabel(self, pm: "PackageManager") -> str:
|
||||
return self.nonLocalizedLabel or self.name.split(".")[-1] if self.name else ""
|
||||
|
||||
def loadIcon(self, pm: "PackageManager") -> Any:
|
||||
return None
|
||||
|
||||
def loadLogo(self, pm: "PackageManager") -> Any:
|
||||
return None
|
||||
|
||||
def loadBanner(self, pm: "PackageManager") -> Any:
|
||||
return None
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"{self.__class__.__name__}({self.packageName}:{self.name})"
|
||||
|
||||
|
||||
class ComponentInfo(PackageItemInfo):
|
||||
"""ComponentInfo — 组件信息基类"""
|
||||
|
||||
def __init__(self, data: Optional[Dict[str, Any]] = None):
|
||||
super().__init__(data)
|
||||
data = data or {}
|
||||
self.processName = data.get("processName", self.packageName)
|
||||
self.splitName = data.get("splitName", None)
|
||||
self.enabled = data.get("enabled", True)
|
||||
self.exported = data.get("exported", False)
|
||||
self.directBootAware = data.get("directBootAware", False)
|
||||
|
||||
def getComponentName(self) -> Any:
|
||||
from .content import ComponentName
|
||||
return ComponentName(self.packageName, self.name)
|
||||
|
||||
def isEnabled(self) -> bool:
|
||||
return self.enabled
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# ApplicationInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class ApplicationInfo(ComponentInfo):
|
||||
"""ApplicationInfo — 应用信息"""
|
||||
|
||||
FLAG_SYSTEM = 1
|
||||
FLAG_DEBUGGABLE = 2
|
||||
FLAG_HAS_CODE = 4
|
||||
FLAG_ALLOW_CLEAR_USER_DATA = 0x00400000
|
||||
FLAG_ALLOW_BACKUP = 0x00008000
|
||||
FLAG_EXTERNAL_STORAGE = 0x00100000
|
||||
FLAG_LARGE_HEAP = 0x00100000
|
||||
FLAG_MULTIPROCESS = 0x00010000
|
||||
FLAG_TEST_ONLY = 0x00000100
|
||||
FLAG_STOPPED = 0x00200000
|
||||
FLAG_RESTART_ON_UPGRADE = 0x00000020
|
||||
|
||||
def __init__(self, data: Optional[Dict[str, Any]] = None):
|
||||
super().__init__(data)
|
||||
data = data or {}
|
||||
self.taskAffinity = data.get("taskAffinity", "")
|
||||
self.permission = data.get("permission", "")
|
||||
self.processName = data.get("processName", self.packageName)
|
||||
self.className = data.get("className", "")
|
||||
self.descriptionRes = data.get("descriptionRes", 0)
|
||||
self.theme = data.get("theme", 0)
|
||||
self.flags = data.get("flags", 0)
|
||||
self.sourceDir = data.get("sourceDir", "")
|
||||
self.publicSourceDir = data.get("publicSourceDir", self.sourceDir)
|
||||
self.dataDir = data.get("dataDir", "")
|
||||
self.nativeLibraryDir = data.get("nativeLibraryDir", "")
|
||||
self.metaData = data.get("metaData", None)
|
||||
self.manageSpaceActivityName = data.get("manageSpaceActivityName", "")
|
||||
self.targetSdkVersion = data.get("targetSdkVersion", 34)
|
||||
self.uid = data.get("uid", 10001)
|
||||
self.backupAgentName = data.get("backupAgentName", "")
|
||||
self.enabled = data.get("enabled", True)
|
||||
|
||||
def loadDescription(self, pm: "PackageManager") -> Optional[str]:
|
||||
return None
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"ApplicationInfo({self.packageName}, targetSdk={self.targetSdkVersion})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# ActivityInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class ActivityInfo(ComponentInfo):
|
||||
"""ActivityInfo — Activity 组件信息"""
|
||||
|
||||
CONFIG_MCC = 0x0001
|
||||
CONFIG_MNC = 0x0002
|
||||
CONFIG_LOCALE = 0x0004
|
||||
CONFIG_TOUCHSCREEN = 0x0008
|
||||
CONFIG_KEYBOARD = 0x0010
|
||||
CONFIG_KEYBOARD_HIDDEN = 0x0020
|
||||
CONFIG_NAVIGATION = 0x0040
|
||||
CONFIG_ORIENTATION = 0x0080
|
||||
CONFIG_SCREEN_LAYOUT = 0x0100
|
||||
CONFIG_UI_MODE = 0x0200
|
||||
CONFIG_SCREEN_SIZE = 0x0400
|
||||
CONFIG_SMALLEST_SCREEN_SIZE = 0x0800
|
||||
CONFIG_DENSITY = 0x1000
|
||||
CONFIG_LAYOUT_DIRECTION = 0x2000
|
||||
CONFIG_COLOR_MODE = 0x4000
|
||||
|
||||
LAUNCH_MULTIPLE = 0
|
||||
LAUNCH_SINGLE_TOP = 1
|
||||
LAUNCH_SINGLE_TASK = 2
|
||||
LAUNCH_SINGLE_INSTANCE = 3
|
||||
LAUNCH_SINGLE_INSTANCE_PER_TASK = 4
|
||||
|
||||
SCREEN_ORIENTATION_UNSPECIFIED = -1
|
||||
SCREEN_ORIENTATION_LANDSCAPE = 0
|
||||
SCREEN_ORIENTATION_PORTRAIT = 1
|
||||
SCREEN_ORIENTATION_USER = 2
|
||||
SCREEN_ORIENTATION_BEHIND = 3
|
||||
SCREEN_ORIENTATION_SENSOR = 4
|
||||
SCREEN_ORIENTATION_NOSENSOR = 5
|
||||
SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6
|
||||
SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7
|
||||
SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8
|
||||
SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9
|
||||
SCREEN_ORIENTATION_FULL_SENSOR = 10
|
||||
SCREEN_ORIENTATION_USER_LANDSCAPE = 11
|
||||
SCREEN_ORIENTATION_USER_PORTRAIT = 12
|
||||
SCREEN_ORIENTATION_FULL_USER = 13
|
||||
SCREEN_ORIENTATION_LOCKED = 14
|
||||
|
||||
def __init__(self, data: Optional[Dict[str, Any]] = None):
|
||||
super().__init__(data)
|
||||
data = data or {}
|
||||
self.launchMode = data.get("launchMode", self.LAUNCH_MULTIPLE)
|
||||
self.screenOrientation = data.get("screenOrientation", self.SCREEN_ORIENTATION_UNSPECIFIED)
|
||||
self.configChanges = data.get("configChanges", 0)
|
||||
self.softInputMode = data.get("softInputMode", 0)
|
||||
self.theme = data.get("theme", 0)
|
||||
self.parentActivityName = data.get("parentActivityName", "")
|
||||
self.permission = data.get("permission", "")
|
||||
self.taskAffinity = data.get("taskAffinity", "")
|
||||
self.targetActivity = data.get("targetActivity", "")
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"ActivityInfo({self.name}, launchMode={self.launchMode})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# ServiceInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class ServiceInfo(ComponentInfo):
|
||||
"""ServiceInfo — Service 组件信息"""
|
||||
|
||||
FLAG_STOP_WITH_TASK = 0x01
|
||||
FLAG_ISOLATED_PROCESS = 0x02
|
||||
FLAG_EXTERNAL_SERVICE = 0x04
|
||||
FLAG_SINGLE_USER = 0x40000000
|
||||
FLAG_USE_APP_OP = 0x08
|
||||
|
||||
def __init__(self, data: Optional[Dict[str, Any]] = None):
|
||||
super().__init__(data)
|
||||
data = data or {}
|
||||
self.flags = data.get("flags", 0)
|
||||
self.permission = data.get("permission", "")
|
||||
self.foregroundServiceType = data.get("foregroundServiceType", 0)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"ServiceInfo({self.name})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# ProviderInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class ProviderInfo(ComponentInfo):
|
||||
"""ProviderInfo — ContentProvider 组件信息"""
|
||||
|
||||
def __init__(self, data: Optional[Dict[str, Any]] = None):
|
||||
super().__init__(data)
|
||||
data = data or {}
|
||||
self.authority = data.get("authority", "")
|
||||
self.readPermission = data.get("readPermission", "")
|
||||
self.writePermission = data.get("writePermission", "")
|
||||
self.grantUriPermissions = data.get("grantUriPermissions", False)
|
||||
self.multiprocess = data.get("multiprocess", False)
|
||||
self.initOrder = data.get("initOrder", 0)
|
||||
self.flags = data.get("flags", 0)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"ProviderInfo({self.name}, authority={self.authority})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# PermissionInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class PermissionInfo(PackageItemInfo):
|
||||
"""PermissionInfo — 权限信息"""
|
||||
|
||||
PROTECTION_NORMAL = 0
|
||||
PROTECTION_DANGEROUS = 1
|
||||
PROTECTION_SIGNATURE = 2
|
||||
PROTECTION_SIGNATURE_OR_SYSTEM = 3
|
||||
PROTECTION_INTERNAL = 4
|
||||
|
||||
FLAG_COSTS_MONEY = 0x01
|
||||
FLAG_HARDWARE_RESTRICTED = 0x04
|
||||
FLAG_IMMUTABLY_RESTRICTED = 0x08
|
||||
FLAG_INSTALLED = 0x10
|
||||
|
||||
def __init__(self, data: Optional[Dict[str, Any]] = None):
|
||||
super().__init__(data)
|
||||
data = data or {}
|
||||
self.group = data.get("group", "")
|
||||
self.descriptionRes = data.get("descriptionRes", 0)
|
||||
self.protectionLevel = data.get("protectionLevel", self.PROTECTION_NORMAL)
|
||||
self.flags = data.get("flags", 0)
|
||||
|
||||
def loadDescription(self, pm: "PackageManager") -> Optional[str]:
|
||||
return None
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"PermissionInfo({self.name}, protectionLevel={self.protectionLevel})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# ResolveInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class ResolveInfo(Stub):
|
||||
"""ResolveInfo — 解析意图的结果"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.activityInfo: Optional[ActivityInfo] = None
|
||||
self.serviceInfo: Optional[ServiceInfo] = None
|
||||
self.providerInfo: Optional[ProviderInfo] = None
|
||||
self.filter: Optional[Any] = None
|
||||
self.priority = 0
|
||||
self.match = 0
|
||||
self.preferredOrder = 0
|
||||
self.isDefault = False
|
||||
self.labelRes = 0
|
||||
self.nonLocalizedLabel = None
|
||||
self.icon = 0
|
||||
self.resolvePackageName = ""
|
||||
self.specificIndex = -1
|
||||
self.system = False
|
||||
|
||||
def loadLabel(self, pm: "PackageManager") -> str:
|
||||
if self.activityInfo:
|
||||
return self.activityInfo.name.split(".")[-1]
|
||||
if self.serviceInfo:
|
||||
return self.serviceInfo.name.split(".")[-1]
|
||||
return ""
|
||||
|
||||
def loadIcon(self, pm: "PackageManager"):
|
||||
return None
|
||||
|
||||
def getIconResource(self) -> int:
|
||||
return self.icon
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"ResolveInfo(priority={self.priority})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# PackageInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class PackageInfo(Stub):
|
||||
"""PackageInfo — 包信息"""
|
||||
|
||||
INSTALL_LOCATION_AUTO = 0
|
||||
INSTALL_LOCATION_INTERNAL_ONLY = 1
|
||||
INSTALL_LOCATION_PREFER_EXTERNAL = 2
|
||||
REQUESTED_PERMISSION_REQUIRED = 0x00100000
|
||||
REQUESTED_PERMISSION_GRANTED = 0x01000000
|
||||
REQUESTED_PERMISSION_DENIED = 0x02000000
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.packageName = ""
|
||||
self.versionName = ""
|
||||
self.versionCode = 0
|
||||
self.applicationInfo: Optional[ApplicationInfo] = None
|
||||
self.activities: List[ActivityInfo] = []
|
||||
self.services: List[ServiceInfo] = []
|
||||
self.receivers: List[ActivityInfo] = []
|
||||
self.providers: List[ProviderInfo] = []
|
||||
self.permissions: List[PermissionInfo] = []
|
||||
self.requestedPermissions: List[str] = []
|
||||
self.requestedPermissionsFlags: List[int] = []
|
||||
self.sharedUserId = ""
|
||||
self.sharedUserLabel = 0
|
||||
self.firstInstallTime = 0
|
||||
self.lastUpdateTime = 0
|
||||
self.gids: List[int] = []
|
||||
self.installLocation = self.INSTALL_LOCATION_AUTO
|
||||
self.configPreferences: List = []
|
||||
self.featureGroups: List = []
|
||||
self.packageName_ = ""
|
||||
|
||||
def toString(self) -> str:
|
||||
return (f"PackageInfo({self.packageName} v{self.versionName} "
|
||||
f"code={self.versionCode})")
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Signature
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class Signature(Stub):
|
||||
"""Signature — APK 签名"""
|
||||
|
||||
def __init__(self, signature: str = ""):
|
||||
super().__init__()
|
||||
self._signature = signature
|
||||
|
||||
def toCharsString(self) -> str:
|
||||
return self._signature
|
||||
|
||||
def toByteArray(self) -> bytes:
|
||||
return self._signature.encode("utf-8") if self._signature else b""
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
if isinstance(other, Signature):
|
||||
return self._signature == other._signature
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash(self._signature) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return self._signature[:64] if len(self._signature) > 64 else self._signature
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# PackageStats
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class PackageStats(Stub):
|
||||
"""PackageStats — 包存储统计"""
|
||||
|
||||
def __init__(self, package_name: str = ""):
|
||||
super().__init__()
|
||||
self.packageName = package_name
|
||||
self.codeSize = 0
|
||||
self.dataSize = 0
|
||||
self.cacheSize = 0
|
||||
self.externalCodeSize = 0
|
||||
self.externalDataSize = 0
|
||||
self.externalCacheSize = 0
|
||||
self.externalMediaSize = 0
|
||||
self.externalObbSize = 0
|
||||
|
||||
def toString(self) -> str:
|
||||
return (f"PackageStats({self.packageName}, "
|
||||
f"code={self.codeSize}, data={self.dataSize})")
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# PackageManager
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class PackageManager(Stub):
|
||||
"""PackageManager — 包管理器"""
|
||||
|
||||
# Flag 常量
|
||||
GET_ACTIVITIES = 1
|
||||
GET_CONFIGURATIONS = 2
|
||||
GET_GIDS = 4
|
||||
GET_INSTRUMENTATION = 8
|
||||
GET_INTENT_FILTERS = 16
|
||||
GET_META_DATA = 128
|
||||
GET_PERMISSIONS = 4096
|
||||
GET_PROVIDERS = 8
|
||||
GET_RECEIVERS = 4
|
||||
GET_SERVICES = 2
|
||||
GET_SHARED_LIBRARY_FILES = 32
|
||||
GET_SIGNATURES = 64
|
||||
GET_UNINSTALLED_PACKAGES = 512
|
||||
GET_URI_PERMISSION_PATTERNS = 256
|
||||
MATCH_ALL = 0x10000
|
||||
MATCH_DISABLED_COMPONENTS = 0x200
|
||||
MATCH_DISABLED_UNTIL_USED_COMPONENTS = 0x8000
|
||||
MATCH_DEFAULT_ONLY = 0x10000
|
||||
MATCH_SYSTEM_ONLY = 0x800000
|
||||
MATCH_UNINSTALLED_PACKAGES = 0x2000000
|
||||
PERMISSION_DENIED = -1
|
||||
PERMISSION_GRANTED = 0
|
||||
|
||||
# 特性常量
|
||||
FEATURE_CAMERA = "android.hardware.camera"
|
||||
FEATURE_CAMERA_AUTOFOCUS = "android.hardware.camera.autofocus"
|
||||
FEATURE_CAMERA_FLASH = "android.hardware.camera.flash"
|
||||
FEATURE_CAMERA_FRONT = "android.hardware.camera.front"
|
||||
FEATURE_LOCATION = "android.hardware.location"
|
||||
FEATURE_LOCATION_GPS = "android.hardware.location.gps"
|
||||
FEATURE_LOCATION_NETWORK = "android.hardware.location.network"
|
||||
FEATURE_MICROPHONE = "android.hardware.microphone"
|
||||
FEATURE_NFC = "android.hardware.nfc"
|
||||
FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer"
|
||||
FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer"
|
||||
FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass"
|
||||
FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope"
|
||||
FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light"
|
||||
FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity"
|
||||
FEATURE_TELEPHONY = "android.hardware.telephony"
|
||||
FEATURE_TOUCHSCREEN = "android.hardware.touchscreen"
|
||||
FEATURE_USB_HOST = "android.hardware.usb.host"
|
||||
FEATURE_WIFI = "android.hardware.wifi"
|
||||
FEATURE_BLUETOOTH = "android.hardware.bluetooth"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._packages: Dict[str, Dict[str, Any]] = {}
|
||||
self._load_packages()
|
||||
|
||||
def _load_packages(self):
|
||||
"""从 JSON 文件加载包信息"""
|
||||
try:
|
||||
if os.path.exists(_DEFAULT_PACKAGE_INFO_PATH):
|
||||
with open(_DEFAULT_PACKAGE_INFO_PATH, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
if data.get("packageName"):
|
||||
self._packages[data["packageName"]] = data
|
||||
else:
|
||||
# 创建默认信息
|
||||
default_info = _get_default_package_info()
|
||||
self._packages[_package_name] = default_info
|
||||
os.makedirs(os.path.dirname(_DEFAULT_PACKAGE_INFO_PATH), exist_ok=True)
|
||||
with open(_DEFAULT_PACKAGE_INFO_PATH, "w", encoding="utf-8") as f:
|
||||
json.dump(default_info, f, indent=2, ensure_ascii=False)
|
||||
except (json.JSONDecodeError, OSError):
|
||||
self._packages[_package_name] = _get_default_package_info()
|
||||
|
||||
def _make_app_info(self, data: Dict) -> ApplicationInfo:
|
||||
ai_data = data.get("applicationInfo", data)
|
||||
return ApplicationInfo(ai_data)
|
||||
|
||||
def _make_activity_info(self, data: Dict) -> ActivityInfo:
|
||||
return ActivityInfo(data)
|
||||
|
||||
def _make_service_info(self, data: Dict) -> ServiceInfo:
|
||||
return ServiceInfo(data)
|
||||
|
||||
def _make_provider_info(self, data: Dict) -> ProviderInfo:
|
||||
return ProviderInfo(data)
|
||||
|
||||
def getPackageInfo(self, package_name: str, flags: int) -> Optional[PackageInfo]:
|
||||
if package_name not in self._packages:
|
||||
return None
|
||||
raw = self._packages[package_name]
|
||||
pi = PackageInfo()
|
||||
pi.packageName = raw.get("packageName", package_name)
|
||||
pi.versionName = raw.get("versionName", "1.0.0")
|
||||
pi.versionCode = raw.get("versionCode", 1)
|
||||
pi.applicationInfo = self._make_app_info(raw)
|
||||
|
||||
if flags & self.GET_ACTIVITIES:
|
||||
pi.activities = [self._make_activity_info(a) for a in raw.get("activities", [])]
|
||||
if flags & self.GET_SERVICES:
|
||||
pi.services = [self._make_service_info(s) for s in raw.get("services", [])]
|
||||
if flags & self.GET_RECEIVERS:
|
||||
pi.receivers = [self._make_activity_info(r) for r in raw.get("receivers", [])]
|
||||
if flags & self.GET_PROVIDERS:
|
||||
pi.providers = [self._make_provider_info(p) for p in raw.get("providers", [])]
|
||||
if flags & self.GET_PERMISSIONS:
|
||||
pi.permissions = [PermissionInfo(p) for p in raw.get("permissions", [])]
|
||||
|
||||
pi.requestedPermissions = raw.get("requestedPermissions", [])
|
||||
return pi
|
||||
|
||||
def getApplicationInfo(self, package_name: str, flags: int) -> Optional[ApplicationInfo]:
|
||||
if package_name not in self._packages:
|
||||
return None
|
||||
return self._make_app_info(self._packages[package_name])
|
||||
|
||||
def getActivityInfo(self, component: Any, flags: int) -> Optional[ActivityInfo]:
|
||||
cn = component
|
||||
pkg = getattr(cn, "getPackageName", lambda: "")()
|
||||
cls = getattr(cn, "getClassName", lambda: "")()
|
||||
if pkg in self._packages:
|
||||
for a in self._packages[pkg].get("activities", []):
|
||||
if a.get("name") == cls:
|
||||
return ActivityInfo(a)
|
||||
return ActivityInfo({"name": cls, "packageName": pkg})
|
||||
|
||||
def getServiceInfo(self, component: Any, flags: int) -> Optional[ServiceInfo]:
|
||||
cn = component
|
||||
pkg = getattr(cn, "getPackageName", lambda: "")()
|
||||
cls = getattr(cn, "getClassName", lambda: "")()
|
||||
if pkg in self._packages:
|
||||
for s in self._packages[pkg].get("services", []):
|
||||
if s.get("name") == cls:
|
||||
return ServiceInfo(s)
|
||||
return ServiceInfo({"name": cls, "packageName": pkg})
|
||||
|
||||
def getInstalledPackages(self, flags: int) -> List[PackageInfo]:
|
||||
result = []
|
||||
for pkg_name in self._packages:
|
||||
pi = self.getPackageInfo(pkg_name, flags)
|
||||
if pi:
|
||||
result.append(pi)
|
||||
return result
|
||||
|
||||
def getInstalledApplications(self, flags: int) -> List[ApplicationInfo]:
|
||||
result = []
|
||||
for pkg_name in self._packages:
|
||||
ai = self.getApplicationInfo(pkg_name, flags)
|
||||
if ai:
|
||||
result.append(ai)
|
||||
return result
|
||||
|
||||
def queryIntentActivities(self, intent: Any, flags: int) -> List[ResolveInfo]:
|
||||
"""查询匹配 Intent 的 Activity 列表"""
|
||||
results = []
|
||||
action = getattr(intent, "getAction", lambda: None)()
|
||||
for pkg_name, raw in self._packages.items():
|
||||
for a in raw.get("activities", []):
|
||||
ri = ResolveInfo()
|
||||
ri.activityInfo = ActivityInfo(a)
|
||||
ri.priority = 0
|
||||
ri.match = 0
|
||||
results.append(ri)
|
||||
return results
|
||||
|
||||
def queryBroadcastReceivers(self, intent: Any, flags: int) -> List[ResolveInfo]:
|
||||
results = []
|
||||
for pkg_name, raw in self._packages.items():
|
||||
for r in raw.get("receivers", []):
|
||||
ri = ResolveInfo()
|
||||
ri.activityInfo = ActivityInfo(r)
|
||||
results.append(ri)
|
||||
return results
|
||||
|
||||
def queryIntentServices(self, intent: Any, flags: int) -> List[ResolveInfo]:
|
||||
results = []
|
||||
for pkg_name, raw in self._packages.items():
|
||||
for s in raw.get("services", []):
|
||||
ri = ResolveInfo()
|
||||
ri.serviceInfo = ServiceInfo(s)
|
||||
results.append(ri)
|
||||
return results
|
||||
|
||||
def queryIntentContentProviders(self, intent: Any, flags: int) -> List[ResolveInfo]:
|
||||
results = []
|
||||
for pkg_name, raw in self._packages.items():
|
||||
for p in raw.get("providers", []):
|
||||
ri = ResolveInfo()
|
||||
ri.providerInfo = ProviderInfo(p)
|
||||
results.append(ri)
|
||||
return results
|
||||
|
||||
def resolveActivity(self, intent: Any, flags: int) -> Optional[ResolveInfo]:
|
||||
activities = self.queryIntentActivities(intent, flags)
|
||||
return activities[0] if activities else None
|
||||
|
||||
def resolveService(self, intent: Any, flags: int) -> Optional[ResolveInfo]:
|
||||
services = self.queryIntentServices(intent, flags)
|
||||
return services[0] if services else None
|
||||
|
||||
def checkPermission(self, permission: str, package_name: str) -> int:
|
||||
if package_name in self._packages:
|
||||
perms = self._packages[package_name].get("requestedPermissions", [])
|
||||
if permission in perms:
|
||||
return self.PERMISSION_GRANTED
|
||||
return self.PERMISSION_DENIED if permission else self.PERMISSION_GRANTED
|
||||
|
||||
def getPermissionInfo(self, name: str, flags: int) -> Optional[PermissionInfo]:
|
||||
return PermissionInfo({"name": name, "packageName": "android"})
|
||||
|
||||
def getDefaultActivityIcon(self) -> Any:
|
||||
return None
|
||||
|
||||
def getApplicationLabel(self, info: ApplicationInfo) -> str:
|
||||
return info.name.split(".")[-1] if info.name else ""
|
||||
|
||||
def getApplicationIcon(self, package_name: str) -> Any:
|
||||
return None
|
||||
|
||||
def hasSystemFeature(self, feature: str) -> bool:
|
||||
for pkg_name, raw in self._packages.items():
|
||||
features = raw.get("features", {})
|
||||
if feature in features:
|
||||
return features[feature]
|
||||
return False
|
||||
|
||||
def getLaunchIntentForPackage(self, package_name: str) -> Any:
|
||||
from .app import Intent
|
||||
if package_name in self._packages:
|
||||
intent = Intent(Intent.ACTION_MAIN)
|
||||
intent.setPackage(package_name)
|
||||
return intent
|
||||
return None
|
||||
|
||||
def getLeanbackLaunchIntentForPackage(self, package_name: str) -> Any:
|
||||
return self.getLaunchIntentForPackage(package_name)
|
||||
|
||||
def getPackageSizeInfo(self, package_name: str, observer: Any):
|
||||
pass
|
||||
|
||||
def getPackageGids(self, package_name: str) -> Optional[List[int]]:
|
||||
return []
|
||||
|
||||
def getPackageUid(self, package_name: str, flags: int) -> int:
|
||||
return 10001
|
||||
|
||||
def getNameForUid(self, uid: int) -> Optional[str]:
|
||||
return _package_name
|
||||
|
||||
def getPackagesForUid(self, uid: int) -> Optional[List[str]]:
|
||||
return [_package_name]
|
||||
|
||||
def getResourcesForActivity(self, component: Any) -> Any:
|
||||
return None
|
||||
|
||||
def getResourcesForApplication(self, app_info: ApplicationInfo) -> Any:
|
||||
return None
|
||||
|
||||
def isSafeMode(self) -> bool:
|
||||
return False
|
||||
|
||||
def addPackageToPreferred(self, package_name: str):
|
||||
pass
|
||||
|
||||
def removePackageFromPreferred(self, package_name: str):
|
||||
pass
|
||||
|
||||
def getPreferredPackages(self, flags: int) -> List[PackageInfo]:
|
||||
return []
|
||||
|
||||
def setApplicationEnabledSetting(self, package_name: str, new_state: int, flags: int):
|
||||
pass
|
||||
|
||||
def getApplicationEnabledSetting(self, package_name: str) -> int:
|
||||
return 0
|
||||
|
||||
def getComponentEnabledSetting(self, component_name: Any) -> int:
|
||||
return 1
|
||||
|
||||
def setComponentEnabledSetting(self, component_name: Any, new_state: int, flags: int):
|
||||
pass
|
||||
|
||||
def clearInstantAppCookie(self):
|
||||
pass
|
||||
|
||||
def getInstantAppCookie(self) -> bytes:
|
||||
return b""
|
||||
|
||||
def getInstantAppCookieMaxSize(self) -> int:
|
||||
return 4096
|
||||
|
||||
def getMimeGroup(self, mime_group: str) -> List[str]:
|
||||
return []
|
||||
|
||||
def isInstantApp(self) -> bool:
|
||||
return False
|
||||
|
||||
def isInstantAppPackageName(self, package_name: str) -> bool:
|
||||
return False
|
||||
|
||||
def getSyntheticAppDetailsActivityEnabled(self, package_name: str) -> int:
|
||||
return 1
|
||||
|
||||
def setSyntheticAppDetailsActivityEnabled(self, package_name: str, enabled: int):
|
||||
pass
|
||||
|
||||
def canRequestPackageInstalls(self) -> bool:
|
||||
return True
|
||||
|
||||
def currentToCanonicalPackageNames(self, names: List[str]) -> List[str]:
|
||||
return list(names)
|
||||
|
||||
def canonicalToCurrentPackageNames(self, names: List[str]) -> List[str]:
|
||||
return list(names)
|
||||
|
||||
def getInstallerPackageName(self, package_name: str) -> Optional[str]:
|
||||
return None
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"PackageManager(packages={len(self._packages)})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# __all__
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
__all__ = [
|
||||
"PackageManager",
|
||||
"PackageInfo",
|
||||
"ApplicationInfo",
|
||||
"ActivityInfo",
|
||||
"ServiceInfo",
|
||||
"ProviderInfo",
|
||||
"PermissionInfo",
|
||||
"ResolveInfo",
|
||||
"PackageItemInfo",
|
||||
"ComponentInfo",
|
||||
"Signature",
|
||||
"PackageStats",
|
||||
]
|
||||
Reference in new issue
Block a user