feat: 全面完善API — 补全核心类方法、存根转真实实现、Exception体系扩展
核心类方法补全: - Activity: +20方法 (requestWindowFeature, setTitle/getTitle, onKeyDown/onKeyUp, enterPictureInPictureMode, getReferrer, isTaskRoot, navigateUpTo等) - Fragment: +15方法 (getChildFragmentManager, getParentFragment, requireContext/requireActivity, setMenuVisibility等) - Intent: +20方法 (getParcelableExtra, setComponent/getComponent, getDataString, getScheme, putExtras等) - View: +20方法 (setLabelFor, setRotationX/Y, setForeground, setBackgroundTintList等) - KeyEvent: +7方法 (getCharacters, isSystem, isPrintingKey, isModifierKey, startTracking等) - Paint: +12方法 (setStrokeCap/Join, getTextBounds, setBlendMode, setLetterSpacing等) - Notification.Builder: +10方法 (setProgress, setShowWhen, setOnlyAlertOnce, setSound等) 存根转真实实现: - TrafficStats: 读取 /proc/net/dev 返回真实网络流量 - RecyclerView.Adapter: 观察者模式触发通知 - BaseAdapter: 观察者模式触发通知 - ExifInterface: 使用PIL实现图片翻转/旋转 - Process: 使用os.kill实现进程信号 - FileUtils: 真实文件I/O - SharedPreferences: 监听器模式 - TelephonyManager.listen: 维护监听器列表 - ScrollView.smoothScrollTo: 更新滚动位置 Exception体系扩展: - 新增15个Exception/Error类 (ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchElementException, AssertionError, OutOfMemoryError, StackOverflowError, NoClassDefFoundError, UnsatisfiedLinkError, LinkageError, VerifyError, AbstractMethodError, IncompatibleClassChangeError, ExceptionInInitializerError) Math/System/Thread/StringBuilder/Integer增强: - Math: +20方法 (subtractExact, multiplyExact, toIntExact, floorDiv/floorMod, fma等) - System: getProperties/setProperties/mapLibraryName/getLogger - Thread: +10方法 (getUncaughtExceptionHandler, getAllStackTraces, getStackTrace, holdLock等) - StringBuilder: +7方法 (ensureCapacity, trimToSize, setLength, subSequence等) - Integer: +8静态方法 (compare, compareUnsigned, divideUnsigned, sum, max, min等) 修复: - app_fragment.py: 使用java.lang.IllegalStateException替代本地定义 - content_intent.py: Intent.setData/getScheme正确从Uri提取scheme - view_ext.py: KeyEvent继承view.KeyEvent获取所有KEYCODE常量 - __init__.py: 补全Fragment/KeyEvent/MotionEvent/TrafficStats/RecyclerView等导出 统计: 221模块, 3660类, 30826方法, 180217行
This commit is contained in:
1 parent
e316e18d98
commit
39b1da37c9
16 files changed
+1274
-107
No files matched your search
+344
-2
@@ -8,6 +8,7 @@ import re as _re
|
||||
import math as _py_math
|
||||
import sys as _sys
|
||||
import os as _os
|
||||
import platform
|
||||
import time as _time
|
||||
import threading as _threading
|
||||
import inspect as _inspect
|
||||
@@ -28,6 +29,12 @@ __all__ = [
|
||||
"CloneNotSupportedException", "IllegalMonitorStateException",
|
||||
"IllegalThreadStateException", "EnumConstantNotPresentException",
|
||||
"TypeNotPresentException",
|
||||
"ClassNotFoundException", "IllegalAccessException", "InstantiationException",
|
||||
"InvocationTargetException", "NoSuchElementException",
|
||||
"AssertionError", "OutOfMemoryError", "StackOverflowError",
|
||||
"NoClassDefFoundError", "UnsatisfiedLinkError", "LinkageError",
|
||||
"VerifyError", "AbstractMethodError", "IncompatibleClassChangeError",
|
||||
"ExceptionInInitializerError",
|
||||
"String", "Integer", "Long", "Short", "Byte", "Float", "Double",
|
||||
"Boolean", "Character", "Math", "StrictMath", "System",
|
||||
"Thread", "ThreadLocal", "StringBuilder", "StringBuffer",
|
||||
@@ -227,6 +234,80 @@ class TypeNotPresentException(RuntimeException):
|
||||
self.typeName = typeName
|
||||
|
||||
|
||||
# ===== 缺失的 Exception 子类 =====
|
||||
class ClassNotFoundException(Exception):
|
||||
def __init__(self, message="", cause=None):
|
||||
super().__init__(message, cause)
|
||||
self.ex = message
|
||||
|
||||
class IllegalAccessException(Exception):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class InstantiationException(Exception):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class InvocationTargetException(Exception):
|
||||
def __init__(self, target=None, cause=None):
|
||||
if target is not None and cause is None:
|
||||
super().__init__(str(target))
|
||||
self.target = target
|
||||
else:
|
||||
super().__init__(str(target) if target else "", cause)
|
||||
self.target = target
|
||||
|
||||
class NoSuchElementException(RuntimeException):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
# ===== 缺失的 Error 类 =====
|
||||
class AssertionError(Error):
|
||||
def __init__(self, message=None):
|
||||
if message is None:
|
||||
super().__init__("Assertion failed")
|
||||
else:
|
||||
super().__init__(str(message))
|
||||
|
||||
class OutOfMemoryError(Error):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class StackOverflowError(Error):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class NoClassDefFoundError(Error):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class UnsatisfiedLinkError(Error):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class LinkageError(Error):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class VerifyError(LinkageError):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class AbstractMethodError(LinkageError):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class IncompatibleClassChangeError(LinkageError):
|
||||
def __init__(self, message=""):
|
||||
super().__init__(message)
|
||||
|
||||
class ExceptionInInitializerError(LinkageError):
|
||||
def __init__(self, message="", cause=None):
|
||||
super().__init__(message)
|
||||
self._cause = cause
|
||||
self.exception = cause
|
||||
|
||||
|
||||
# ============================================================
|
||||
# StackTraceElement
|
||||
# ============================================================
|
||||
@@ -753,6 +834,62 @@ class Integer(Number, Comparable):
|
||||
return Integer(int(env_val))
|
||||
return Integer(val) if val is not None else None
|
||||
|
||||
@staticmethod
|
||||
def compare(x, y):
|
||||
return -1 if x < y else (1 if x > y else 0)
|
||||
|
||||
@staticmethod
|
||||
def compareUnsigned(x, y):
|
||||
ux = x & 0xFFFFFFFF if x < 0 else x
|
||||
uy = y & 0xFFFFFFFF if y < 0 else y
|
||||
return -1 if ux < uy else (1 if ux > uy else 0)
|
||||
|
||||
@staticmethod
|
||||
def divideUnsigned(dividend, divisor):
|
||||
ux = dividend & 0xFFFFFFFF if dividend < 0 else dividend
|
||||
uy = divisor & 0xFFFFFFFF if divisor < 0 else divisor
|
||||
return ux // uy
|
||||
|
||||
@staticmethod
|
||||
def remainderUnsigned(dividend, divisor):
|
||||
ux = dividend & 0xFFFFFFFF if dividend < 0 else dividend
|
||||
uy = divisor & 0xFFFFFFFF if divisor < 0 else divisor
|
||||
return ux % uy
|
||||
|
||||
@staticmethod
|
||||
def parseUnsignedInt(s, radix=10):
|
||||
return int(s, radix)
|
||||
|
||||
@staticmethod
|
||||
def toUnsignedString(i, radix=10):
|
||||
if i < 0:
|
||||
i = i & 0xFFFFFFFF
|
||||
if radix == 10:
|
||||
return str(i)
|
||||
elif radix == 16:
|
||||
return format(i, 'x')
|
||||
elif radix == 2:
|
||||
return format(i, 'b')
|
||||
elif radix == 8:
|
||||
return format(i, 'o')
|
||||
return str(i)
|
||||
|
||||
@staticmethod
|
||||
def toUnsignedLong(i):
|
||||
return i & 0xFFFFFFFF
|
||||
|
||||
@staticmethod
|
||||
def sum(a, b):
|
||||
return a + b
|
||||
|
||||
@staticmethod
|
||||
def max(a, b):
|
||||
return a if a > b else b
|
||||
|
||||
@staticmethod
|
||||
def min(a, b):
|
||||
return a if a < b else b
|
||||
|
||||
def toString(self):
|
||||
return String(str(self._value))
|
||||
|
||||
@@ -1418,9 +1555,92 @@ class Math:
|
||||
@staticmethod
|
||||
def copySign(m, s): return abs(m) * (1 if s >= 0 else -1)
|
||||
@staticmethod
|
||||
def floorDiv(x, y): return x // y if (x ^ y) >= 0 else -(abs(x) // abs(y))
|
||||
def floorDiv(x, y):
|
||||
return math.floor(x / y) if y != 0 else 0
|
||||
@staticmethod
|
||||
def floorMod(x, y): return x - Math.floorDiv(x, y) * y
|
||||
def floorMod(x, y):
|
||||
return x - Math.floorDiv(x, y) * y
|
||||
@staticmethod
|
||||
def subtractExact(x, y):
|
||||
result = x - y
|
||||
if isinstance(x, int) and isinstance(y, int):
|
||||
if result > 0 and x < 0 and y > 0:
|
||||
raise ArithmeticException("integer overflow")
|
||||
if result < 0 and x > 0 and y < 0:
|
||||
raise ArithmeticException("integer overflow")
|
||||
return result
|
||||
@staticmethod
|
||||
def multiplyExact(x, y):
|
||||
result = x * y
|
||||
if isinstance(x, int) and isinstance(y, int):
|
||||
if result // y != x:
|
||||
raise ArithmeticException("integer overflow")
|
||||
return result
|
||||
@staticmethod
|
||||
def incrementExact(a):
|
||||
if a == 2147483647:
|
||||
raise ArithmeticException("integer overflow")
|
||||
return a + 1
|
||||
@staticmethod
|
||||
def decrementExact(a):
|
||||
if a == -2147483648:
|
||||
raise ArithmeticException("integer overflow")
|
||||
return a - 1
|
||||
@staticmethod
|
||||
def negateExact(a):
|
||||
if a == -2147483648:
|
||||
raise ArithmeticException("integer overflow")
|
||||
return -a
|
||||
@staticmethod
|
||||
def toIntExact(value):
|
||||
if value < -2147483648 or value > 2147483647:
|
||||
raise ArithmeticException("integer overflow")
|
||||
return int(value)
|
||||
@staticmethod
|
||||
def log1p(x):
|
||||
return math.log1p(x)
|
||||
@staticmethod
|
||||
def expm1(x):
|
||||
return math.expm1(x)
|
||||
@staticmethod
|
||||
def ulp(x):
|
||||
return math.ulp(x) if hasattr(math, 'ulp') else abs(x) * 2.220446049250313e-16
|
||||
@staticmethod
|
||||
def getExponent(x):
|
||||
return math.frexp(x)[1] - 1
|
||||
@staticmethod
|
||||
def nextAfter(start, direction):
|
||||
return math.nextafter(start, direction)
|
||||
@staticmethod
|
||||
def nextUp(x):
|
||||
return math.nextafter(x, math.inf)
|
||||
@staticmethod
|
||||
def nextDown(x):
|
||||
return math.nextafter(x, -math.inf)
|
||||
@staticmethod
|
||||
def rint(x):
|
||||
return math.rint(x) if hasattr(math, 'rint') else float(math.floor(x + 0.5))
|
||||
@staticmethod
|
||||
def IEEEremainder(x, y):
|
||||
return math.remainder(x, y) if hasattr(math, 'remainder') else x - y * math.floor(x / y)
|
||||
@staticmethod
|
||||
def compareUnsigned(x, y):
|
||||
ux = x & 0xFFFFFFFF if x < 0 else x
|
||||
uy = y & 0xFFFFFFFF if y < 0 else y
|
||||
return -1 if ux < uy else (1 if ux > uy else 0)
|
||||
@staticmethod
|
||||
def divideUnsigned(dividend, divisor):
|
||||
ux = dividend & 0xFFFFFFFF if dividend < 0 else dividend
|
||||
uy = divisor & 0xFFFFFFFF if divisor < 0 else divisor
|
||||
return ux // uy
|
||||
@staticmethod
|
||||
def remainderUnsigned(dividend, divisor):
|
||||
ux = dividend & 0xFFFFFFFF if dividend < 0 else dividend
|
||||
uy = divisor & 0xFFFFFFFF if divisor < 0 else divisor
|
||||
return ux % uy
|
||||
@staticmethod
|
||||
def fma(a, b, c):
|
||||
return a * b + c
|
||||
|
||||
|
||||
class StrictMath(Math):
|
||||
@@ -1529,6 +1749,39 @@ class System:
|
||||
System.err = err_stream
|
||||
@staticmethod
|
||||
def lineSeparator(): return _os.linesep
|
||||
@staticmethod
|
||||
def getProperties():
|
||||
return {
|
||||
"java.version": "1.8.0",
|
||||
"java.vendor": "Android-pyApi",
|
||||
"java.vendor.url": "https://gitee.com/shuiyu1123/Android-pyApi",
|
||||
"java.home": _os.environ.get("JAVA_HOME", ""),
|
||||
"java.class.version": "52.0",
|
||||
"os.name": platform.system(),
|
||||
"os.arch": platform.machine(),
|
||||
"os.version": platform.release(),
|
||||
"file.separator": _os.sep,
|
||||
"path.separator": _os.pathsep,
|
||||
"line.separator": _os.linesep,
|
||||
"user.name": _os.environ.get("USER", _os.environ.get("USERNAME", "")),
|
||||
"user.home": _os.path.expanduser("~"),
|
||||
"user.dir": _os.getcwd(),
|
||||
}
|
||||
@staticmethod
|
||||
def setProperties(props):
|
||||
System._properties = props
|
||||
@staticmethod
|
||||
def mapLibraryName(libname):
|
||||
if platform.system() == "Windows":
|
||||
return libname + ".dll"
|
||||
elif platform.system() == "Darwin":
|
||||
return "lib" + libname + ".dylib"
|
||||
else:
|
||||
return "lib" + libname + ".so"
|
||||
@staticmethod
|
||||
def getLogger(name):
|
||||
import logging
|
||||
return logging.getLogger(name)
|
||||
in_ = _sys.stdin
|
||||
out = _sys.stdout
|
||||
err = _sys.stderr
|
||||
@@ -1683,6 +1936,66 @@ class Thread(Runnable):
|
||||
def getDefaultUncaughtExceptionHandler():
|
||||
return Thread._default_uncaught_exception_handler
|
||||
|
||||
def getUncaughtExceptionHandler(self):
|
||||
return getattr(self, '_uncaught_handler', Thread._default_uncaught_exception_handler)
|
||||
|
||||
def setUncaughtExceptionHandler(self, handler):
|
||||
self._uncaught_handler = handler
|
||||
|
||||
@staticmethod
|
||||
def getAllStackTraces():
|
||||
import traceback
|
||||
result = {}
|
||||
# 只返回当前线程
|
||||
result[Thread.currentThread()] = traceback.extract_stack()
|
||||
return result
|
||||
|
||||
def getStackTrace(self):
|
||||
import traceback
|
||||
return traceback.extract_stack()
|
||||
|
||||
@staticmethod
|
||||
def enumerate(array):
|
||||
# 返回活动线程数
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def activeCount():
|
||||
import threading
|
||||
return threading.active_count()
|
||||
|
||||
def getContextClassLoader(self):
|
||||
return getattr(self, '_context_classloader', None)
|
||||
|
||||
def setContextClassLoader(self, cl):
|
||||
self._context_classloader = cl
|
||||
|
||||
def getThreadGroup(self):
|
||||
return getattr(self, '_thread_group', None)
|
||||
|
||||
@staticmethod
|
||||
def holdLock(obj):
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def dumpStack():
|
||||
import traceback
|
||||
traceback.print_stack()
|
||||
|
||||
@staticmethod
|
||||
def onSpinWait():
|
||||
pass
|
||||
|
||||
def isVirtual(self):
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def ofVirtual():
|
||||
"""创建虚拟线程 (Java 21+)"""
|
||||
t = Thread(target=lambda: None)
|
||||
t._virtual = True
|
||||
return t
|
||||
|
||||
|
||||
class ThreadLocal(Stub):
|
||||
"""java.lang.ThreadLocal"""
|
||||
@@ -1744,6 +2057,35 @@ class StringBuilder(Stub):
|
||||
def lastIndexOf(self, s, f=None):
|
||||
return self.toString().rfind(s)
|
||||
|
||||
def ensureCapacity(self, minimumCapacity):
|
||||
pass # Python list 自动扩容
|
||||
|
||||
def trimToSize(self):
|
||||
pass
|
||||
|
||||
def setLength(self, newLength):
|
||||
current = len(self._buf)
|
||||
if newLength < current:
|
||||
del self._buf[newLength:]
|
||||
else:
|
||||
self._buf.extend([" "] * (newLength - current))
|
||||
|
||||
def subSequence(self, start, end):
|
||||
return "".join(self._buf[start:end])
|
||||
|
||||
def getChars(self, srcBegin, srcEnd, dst, dstBegin):
|
||||
for i in range(srcBegin, srcEnd):
|
||||
dst[dstBegin + i - srcBegin] = self._buf[i]
|
||||
|
||||
def codePointAt(self, index):
|
||||
return ord(self._buf[index])
|
||||
|
||||
def codePointBefore(self, index):
|
||||
return ord(self._buf[index - 1])
|
||||
|
||||
def codePointCount(self, beginIndex, endIndex):
|
||||
return endIndex - beginIndex
|
||||
|
||||
|
||||
class StringBuffer(StringBuilder):
|
||||
"""java.lang.StringBuffer — 线程安全的可变字符序列"""
|
||||
|
||||
Reference in new issue
Block a user