feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python

52 个模块覆盖 Android + Java + org.json 标准库
This commit is contained in:
shuiyu1123 committed 2026-06-24 11:16:16 +00:00
commit bfe27fdc08
104 files changed
+58750

No files matched your search

+186
View File
@@ -0,0 +1,186 @@
"""
Android-pyApi 核心基础设施
"""
import os
import sys
import platform
import tempfile
import json
import hashlib
import random
import time
from typing import Any, Dict, List, Optional, Callable
class AndroidOnlyError(Exception):
"""当调用仅 Android 可用的 API 时抛出"""
pass
class Stub:
"""
通用 Android API 存根基类。
子类可以覆盖具体方法实现真实逻辑;
未覆盖的方法调用会返回合理默认值。
"""
_android_only = False
def __init__(self, *args, **kwargs):
pass
def __getattr__(self, name: str):
if name.startswith("_"):
raise AttributeError(name)
def _stub_method(*args, **kwargs):
if self._android_only:
raise AndroidOnlyError(
f"{self.__class__.__name__}.{name}() 仅在 Android 设备上可用"
)
return None
return _stub_method
def toString(self) -> str:
return f"{self.__class__.__name__}@{hex(id(self))}"
def equals(self, other) -> bool:
return self is other
def hashCode(self) -> int:
return hash(self) & 0x7FFFFFFF
def getClass(self) -> type:
return self.__class__
# ═══════════════════════════════════════════════════════════════
# 全局路径和环境
# ═══════════════════════════════════════════════════════════════
_package_name = "com.ai.assistance.operit"
_sdcard_root = os.path.join(os.path.expanduser("~"), "Android-compat", "sdcard")
_app_data_dir = os.path.join(os.path.expanduser("~"), "Android-compat", "app-data")
def _ensure_dirs():
dirs = [
_sdcard_root,
os.path.join(_sdcard_root, "Download"),
os.path.join(_sdcard_root, "DCIM"),
os.path.join(_sdcard_root, "DCIM", "Screenshots"),
os.path.join(_sdcard_root, "Documents"),
os.path.join(_sdcard_root, "Music"),
os.path.join(_sdcard_root, "Movies"),
os.path.join(_sdcard_root, "Pictures"),
os.path.join(_sdcard_root, "Android", "data"),
os.path.join(_sdcard_root, "Android", "data", _package_name, "files"),
os.path.join(_sdcard_root, "Android", "data", _package_name, "cache"),
_app_data_dir,
os.path.join(_app_data_dir, "files"),
os.path.join(_app_data_dir, "cache"),
os.path.join(_app_data_dir, "shared_prefs"),
]
for d in dirs:
os.makedirs(d, exist_ok=True)
_ensure_dirs()
def resolve_android_path(path: str) -> str:
"""将 Android 路径解析为桌面路径"""
if path.startswith("/sdcard"):
return os.path.join(_sdcard_root, path[7:].lstrip("/"))
if path.startswith("/data/data/"):
return os.path.join(_app_data_dir, path[11:].lstrip("/"))
if path.startswith("content://"):
# 简单解析 content URI
from urllib.parse import urlparse
parsed = urlparse(path)
return parsed.path or path
if path.startswith("file://"):
from urllib.parse import unquote
return unquote(path[7:])
return path
def to_android_path(desktop_path: str) -> str:
"""将桌面路径映射回 Android 路径"""
if desktop_path.startswith(_sdcard_root):
rel = os.path.relpath(desktop_path, _sdcard_root)
return f"/sdcard/{rel}"
if desktop_path.startswith(_app_data_dir):
rel = os.path.relpath(desktop_path, _app_data_dir)
return f"/data/data/{_package_name}/{rel}"
return desktop_path
# ═══════════════════════════════════════════════════════════════
# 全局 Context 单例
# ═══════════════════════════════════════════════════════════════
class _GlobalContext:
"""全局应用上下文占位符,在 android.content 模块中被替换为真实 Context"""
@property
def packageName(self):
return _package_name
def getPackageName(self):
return _package_name
def getFilesDir(self):
return os.path.join(_app_data_dir, "files")
def getCacheDir(self):
return os.path.join(_app_data_dir, "cache")
def getExternalFilesDir(self, type_=None):
base = os.path.join(_sdcard_root, "Android", "data", _package_name, "files")
if type_:
base = os.path.join(base, type_)
os.makedirs(base, exist_ok=True)
return base
def getExternalStorageDirectory(self):
return _sdcard_root
def getSystemService(self, name):
return None # 由具体模块填充
android_context = _GlobalContext()
def get_context():
"""获取全局 Android Context"""
return android_context
# ═══════════════════════════════════════════════════════════════
# 可选依赖检测
# ═══════════════════════════════════════════════════════════════
def _check_optional(name: str) -> bool:
"""检查可选依赖是否可用"""
try:
__import__(name)
return True
except ImportError:
return False
HAS_PIL = _check_optional("PIL")
HAS_REQUESTS = _check_optional("requests")
HAS_HTTPX = _check_optional("httpx")
HAS_PYAUTOGUI = _check_optional("pyautogui")
HAS_SCREENINFO = _check_optional("screeninfo")
HAS_PSUTIL = _check_optional("psutil")
HAS_PYMUPDF = _check_optional("fitz")
HAS_PDF2IMAGE = _check_optional("pdf2image")
HAS_CRYPTOGRAPHY = _check_optional("cryptography")
HAS_PYPERCLIP = _check_optional("pyperclip")
HAS_JPYPE = _check_optional("jpype")