feat: 深度完善 — 存根转真实实现、UI类方法补全、Java集合/IO增强
存根转真实实现: - ContentResolver: query/insert/update/delete对file://URI真实文件操作, getType用mimetypes - Context: getResources/getAssets/getString/getColor 委托真实Resources - Bitmap.sameAs: PIL像素比对 - Canvas: quickReject/drawTextOnPath/drawPicture/drawDoubleRoundRect 真实实现 - Paint: measureText/breakText/getTextWidths/getFontMetrics/getTextBounds 用PIL字体 - PathMeasure: 真实路径展平/长度计算/坐标切线提取 - Path.op/Region.op: 布尔运算 - Camera: 3D变换矩阵计算 - SystemClock.setCurrentTimeMillis: date -s命令 - Environment.isExternalStorageRemovable: /proc/mounts检查 - Process.myUid: os.getuid() - PowerManager.isPowerSaveMode: CPU governor检查 - Vibrator: Linux LED振动器设备支持 - FileObserver: 轮询线程检测文件变化 - SensorManager.getRotationMatrix: 完整旋转矩阵算法 - BatteryManager: LinuxPower真实电池数据 - Geocoder: Nominatim API逆地理编码 - LocationManager: addProximityAlert/setTestProviderLocation UI类方法补全: - TextView: setPaddingRelative/getTextColor/setBreakStrategy/setJustificationMode - ImageView: setColorFilter/getColorFilter/clearColorFilter - CheckBox/Switch: setOnCheckedChangeListener - ListView: clearChoices - ViewGroup: setLayoutTransition/setTouchscreenBlocksFocus/getChildVisibleRect - MotionEvent: getHistoricalX/Y/Pressure/EventTime/addBatch/getEdgeFlags/setAction Java集合增强: - ArrayList: spliterator/stream - HashSet: spliterator/stream/removeIf - TreeMap: replaceAll/compute/computeIfAbsent/computeIfPresent/merge - LinkedHashMap: clone (保留access_order) - PriorityQueue: spliterator/clone Java IO增强: - BufferedWriter: append/check - PrintWriter: append - ByteArrayOutputStream: writeTo - ByteArrayInputStream: markSupported - BufferedInputStream: available/mark/reset/markSupported + 修复_fill缓冲区填充bug - SequenceInputStream: 补全实现(Enumeration/多流/跨流聚合读取) 修复: - ViewGroup.addView: 合并重复定义为智能参数分派 - view_ext.ViewGroup: 继承view.ViewGroup - view_ext.KeyEvent: 继承view.KeyEvent - hardware_sensor_ext.SensorManager: 继承hardware.SensorManager - app_fragment: 使用java.lang.IllegalStateException - content_intent.Intent: setData/getScheme正确从Uri提取scheme - __init__.py: 补全Fragment/KeyEvent/MotionEvent/TrafficStats/RecyclerView/TreeMap/Vibrator等导出 统计: 221模块, 3662类, 30952方法, 182302行
This commit is contained in:
1 parent
39b1da37c9
commit
4235f8692c
13 files changed
+2248
-163
No files matched your search
+168
-25
@@ -745,14 +745,48 @@ class BufferedInputStream(FilterInputStream):
|
||||
return total if total > 0 else -1
|
||||
|
||||
def _fill(self):
|
||||
data = self._in.read(bytearray(self._buf_size), 0, self._buf_size)
|
||||
if data is None or data == -1:
|
||||
tmp = bytearray(self._buf_size)
|
||||
n = self._in.read(tmp, 0, self._buf_size)
|
||||
if n is None or n == -1:
|
||||
return False
|
||||
n = data if isinstance(data, int) else len(data)
|
||||
self._buffer = bytearray(self._in._buffer if hasattr(self._in, '_buffer') else data) if n > 0 else bytearray()
|
||||
if isinstance(n, (bytes, bytearray)):
|
||||
# defensive: underlying stream returned raw data instead of a count
|
||||
tmp = bytearray(n)
|
||||
n = len(tmp)
|
||||
if not isinstance(n, int) or n <= 0:
|
||||
return False
|
||||
self._buffer = bytearray(tmp[:n])
|
||||
self._pos = 0
|
||||
self._count = n
|
||||
return n > 0
|
||||
return True
|
||||
|
||||
def available(self):
|
||||
buf_avail = self._count - self._pos
|
||||
if buf_avail < 0:
|
||||
buf_avail = 0
|
||||
try:
|
||||
underlying = self._in.available()
|
||||
if underlying and underlying > 0:
|
||||
return buf_avail + underlying
|
||||
except Exception:
|
||||
pass
|
||||
return buf_avail
|
||||
|
||||
def mark(self, readlimit):
|
||||
self._mark_pos = self._pos
|
||||
self._mark_buffer = bytes(self._buffer)
|
||||
self._mark_count = self._count
|
||||
self._mark_limit = readlimit
|
||||
|
||||
def reset(self):
|
||||
if not hasattr(self, '_mark_pos'):
|
||||
raise IOException("Resetting to invalid mark")
|
||||
self._buffer = bytearray(self._mark_buffer)
|
||||
self._count = self._mark_count
|
||||
self._pos = self._mark_pos
|
||||
|
||||
def markSupported(self):
|
||||
return True
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -1034,6 +1068,26 @@ class BufferedWriter(Closeable, Flushable):
|
||||
def newLine(self):
|
||||
self._buffer.append("\n")
|
||||
|
||||
def append(self, csq=None, start=None, end=None):
|
||||
if csq is None:
|
||||
return self
|
||||
if isinstance(csq, int):
|
||||
self._buffer.append(chr(csq))
|
||||
else:
|
||||
s = str(csq)
|
||||
if start is not None and end is not None:
|
||||
s = s[start:end]
|
||||
elif start is not None:
|
||||
s = s[start:]
|
||||
self._buffer.append(s)
|
||||
if sum(len(x) for x in self._buffer) >= self._buf_size:
|
||||
self.flush()
|
||||
return self
|
||||
|
||||
def check(self):
|
||||
if getattr(self._writer, '_closed', False):
|
||||
raise IOException("Stream closed")
|
||||
|
||||
def flush(self):
|
||||
if self._buffer:
|
||||
data = "".join(self._buffer)
|
||||
@@ -1171,6 +1225,20 @@ class PrintWriter(Closeable, Flushable):
|
||||
else:
|
||||
self._write_str(str(s))
|
||||
|
||||
def append(self, csq=None, start=None, end=None):
|
||||
if csq is None:
|
||||
csq = "null"
|
||||
if isinstance(csq, int):
|
||||
self._write_str(chr(csq))
|
||||
else:
|
||||
s = str(csq)
|
||||
if start is not None and end is not None:
|
||||
s = s[start:end]
|
||||
elif start is not None:
|
||||
s = s[start:]
|
||||
self._write_str(s)
|
||||
return self
|
||||
|
||||
def format(self, fmt, *args):
|
||||
s = str(fmt) % args if args else str(fmt)
|
||||
self._write_str(s)
|
||||
@@ -1256,6 +1324,9 @@ class ByteArrayInputStream(Closeable):
|
||||
def reset(self):
|
||||
self._pos = self._mark
|
||||
|
||||
def markSupported(self):
|
||||
return True
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ByteArrayOutputStream
|
||||
@@ -1283,6 +1354,11 @@ class ByteArrayOutputStream(Closeable, Flushable):
|
||||
def toByteArray(self):
|
||||
return bytes(self._buf)
|
||||
|
||||
def writeTo(self, out):
|
||||
if self._closed:
|
||||
raise IOException("Stream closed")
|
||||
out.write(bytes(self._buf))
|
||||
|
||||
def size(self):
|
||||
return len(self._buf)
|
||||
|
||||
@@ -1730,37 +1806,104 @@ class PushbackInputStream(FilterInputStream):
|
||||
# SequenceInputStream
|
||||
# ============================================================
|
||||
|
||||
def _is_enumeration(obj) -> bool:
|
||||
"""True if obj really exposes hasMoreElements/nextElement (not via Stub)."""
|
||||
for cls in type(obj).__mro__:
|
||||
if ('hasMoreElements' in cls.__dict__
|
||||
and 'nextElement' in cls.__dict__):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class SequenceInputStream(Closeable):
|
||||
def __init__(self, streams):
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
if hasattr(streams, 'hasMoreElements'):
|
||||
self._streams = []
|
||||
while streams.hasMoreElements():
|
||||
self._streams.append(streams.nextElement())
|
||||
else:
|
||||
self._streams = list(streams)
|
||||
self._streams = []
|
||||
self._current_idx = 0
|
||||
self._closed = False
|
||||
if len(args) == 0:
|
||||
return
|
||||
if len(args) == 1:
|
||||
streams = args[0]
|
||||
if isinstance(streams, (list, tuple)):
|
||||
self._streams = list(streams)
|
||||
elif _is_enumeration(streams):
|
||||
while streams.hasMoreElements():
|
||||
self._streams.append(streams.nextElement())
|
||||
else:
|
||||
# single stream
|
||||
self._streams = [streams]
|
||||
else:
|
||||
# SequenceInputStream(s1, s2, ...)
|
||||
self._streams = list(args)
|
||||
|
||||
def _current(self):
|
||||
if self._current_idx < len(self._streams):
|
||||
return self._streams[self._current_idx]
|
||||
while self._current_idx < len(self._streams):
|
||||
inp = self._streams[self._current_idx]
|
||||
if inp is None:
|
||||
self._current_idx += 1
|
||||
continue
|
||||
return inp
|
||||
return None
|
||||
|
||||
def read(self, b=None, off=None, length=None):
|
||||
while self._current():
|
||||
inp = self._current()
|
||||
if b is None:
|
||||
result = inp.read()
|
||||
else:
|
||||
result = inp.read(b, off, length)
|
||||
if result != -1:
|
||||
return result
|
||||
def _advance(self):
|
||||
if self._current_idx < len(self._streams):
|
||||
cur = self._streams[self._current_idx]
|
||||
if cur is not None:
|
||||
try:
|
||||
cur.close()
|
||||
except Exception:
|
||||
pass
|
||||
self._current_idx += 1
|
||||
return -1
|
||||
|
||||
def read(self, b=None, off=None, length=None):
|
||||
if self._closed:
|
||||
raise IOException("Stream closed")
|
||||
if b is None:
|
||||
while True:
|
||||
inp = self._current()
|
||||
if inp is None:
|
||||
return -1
|
||||
result = inp.read()
|
||||
if result != -1:
|
||||
return result
|
||||
self._advance()
|
||||
if off is None:
|
||||
off = 0
|
||||
if length is None:
|
||||
length = len(b)
|
||||
total = 0
|
||||
while total < length:
|
||||
inp = self._current()
|
||||
if inp is None:
|
||||
break
|
||||
n = inp.read(b, off + total, length - total)
|
||||
if n is None or n == -1:
|
||||
self._advance()
|
||||
continue
|
||||
if n == 0:
|
||||
self._advance()
|
||||
continue
|
||||
total += n
|
||||
return total if total > 0 else -1
|
||||
|
||||
def available(self):
|
||||
inp = self._current()
|
||||
if inp is None:
|
||||
return 0
|
||||
try:
|
||||
return inp.available()
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
def close(self):
|
||||
self._closed = True
|
||||
for s in self._streams:
|
||||
s.close()
|
||||
if s is not None:
|
||||
try:
|
||||
s.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -148,6 +148,240 @@ class Enumeration(Stub):
|
||||
return Iterator(self._it)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Stream / Spliterator helpers (lightweight, stdlib-backed)
|
||||
# ============================================================
|
||||
|
||||
class _Spliterator(Stub):
|
||||
"""Lightweight java.util.Spliterator backed by a Python sequence."""
|
||||
ORDERED = 0x00000010
|
||||
DISTINCT = 0x00000001
|
||||
SORTED = 0x00000004
|
||||
SIZED = 0x00000040
|
||||
NONNULL = 0x00000100
|
||||
IMMUTABLE = 0x00000400
|
||||
CONCURRENT = 0x00001000
|
||||
SUBSIZED = 0x00004000
|
||||
|
||||
def __init__(self, data, characteristics: int = 0):
|
||||
super().__init__()
|
||||
self._data = list(data)
|
||||
self._index = 0
|
||||
self._characteristics = (characteristics
|
||||
| _Spliterator.SIZED
|
||||
| _Spliterator.SUBSIZED)
|
||||
|
||||
def tryAdvance(self, action) -> bool:
|
||||
if self._index < len(self._data):
|
||||
action(self._data[self._index])
|
||||
self._index += 1
|
||||
return True
|
||||
return False
|
||||
|
||||
def forEachRemaining(self, action) -> None:
|
||||
while self._index < len(self._data):
|
||||
action(self._data[self._index])
|
||||
self._index += 1
|
||||
|
||||
def trySplit(self):
|
||||
mid = (self._index + len(self._data)) // 2
|
||||
if self._index >= mid:
|
||||
return None
|
||||
split = _Spliterator(self._data[self._index:mid],
|
||||
self._characteristics)
|
||||
self._index = mid
|
||||
return split
|
||||
|
||||
def estimateSize(self) -> int:
|
||||
return len(self._data) - self._index
|
||||
|
||||
def getExactSizeIfKnown(self) -> int:
|
||||
return self.estimateSize()
|
||||
|
||||
def characteristics(self) -> int:
|
||||
return self._characteristics
|
||||
|
||||
def hasCharacteristics(self, characteristics: int) -> bool:
|
||||
return (self._characteristics & characteristics) == characteristics
|
||||
|
||||
def iterator(self) -> Iterator:
|
||||
return Iterator(self._data[self._index:])
|
||||
|
||||
|
||||
class _Stream(Stub):
|
||||
"""Lightweight java.util.stream.Stream wrapper over a Python list."""
|
||||
def __init__(self, data):
|
||||
super().__init__()
|
||||
self._data = list(data)
|
||||
self._parallel = False
|
||||
|
||||
def iterator(self) -> Iterator:
|
||||
return Iterator(self._data)
|
||||
|
||||
def spliterator(self) -> _Spliterator:
|
||||
return _Spliterator(self._data)
|
||||
|
||||
def isParallel(self) -> bool:
|
||||
return self._parallel
|
||||
|
||||
def parallel(self) -> '_Stream':
|
||||
self._parallel = True
|
||||
return self
|
||||
|
||||
def sequential(self) -> '_Stream':
|
||||
self._parallel = False
|
||||
return self
|
||||
|
||||
def unordered(self) -> '_Stream':
|
||||
return self
|
||||
|
||||
def filter(self, predicate) -> '_Stream':
|
||||
return _Stream([x for x in self._data if predicate(x)])
|
||||
|
||||
def map(self, mapper) -> '_Stream':
|
||||
return _Stream([mapper(x) for x in self._data])
|
||||
|
||||
def mapToInt(self, mapper) -> '_Stream':
|
||||
return _Stream([mapper(x) for x in self._data])
|
||||
|
||||
def mapToLong(self, mapper) -> '_Stream':
|
||||
return _Stream([mapper(x) for x in self._data])
|
||||
|
||||
def mapToDouble(self, mapper) -> '_Stream':
|
||||
return _Stream([mapper(x) for x in self._data])
|
||||
|
||||
def flatMap(self, mapper) -> '_Stream':
|
||||
result = []
|
||||
for x in self._data:
|
||||
part = mapper(x)
|
||||
if isinstance(part, (list, tuple)):
|
||||
result.extend(part)
|
||||
else:
|
||||
result.extend(list(part))
|
||||
return _Stream(result)
|
||||
|
||||
def peek(self, action) -> '_Stream':
|
||||
for x in self._data:
|
||||
action(x)
|
||||
return self
|
||||
|
||||
def distinct(self) -> '_Stream':
|
||||
seen = []
|
||||
seen_keys = set()
|
||||
for x in self._data:
|
||||
key = x if isinstance(x, (int, str, tuple, frozenset)) else id(x)
|
||||
if key not in seen_keys:
|
||||
seen_keys.add(key)
|
||||
seen.append(x)
|
||||
return _Stream(seen)
|
||||
|
||||
def sorted(self, key=None, reverse: bool = False) -> '_Stream':
|
||||
return _Stream(sorted(self._data, key=key, reverse=reverse))
|
||||
|
||||
def limit(self, maxSize: int) -> '_Stream':
|
||||
return _Stream(self._data[:maxSize])
|
||||
|
||||
def skip(self, n: int) -> '_Stream':
|
||||
return _Stream(self._data[n:])
|
||||
|
||||
def forEach(self, action) -> None:
|
||||
for x in self._data:
|
||||
action(x)
|
||||
|
||||
def forEachOrdered(self, action) -> None:
|
||||
for x in self._data:
|
||||
action(x)
|
||||
|
||||
def toArray(self, generator=None):
|
||||
if generator is None:
|
||||
return list(self._data)
|
||||
return list(self._data)
|
||||
|
||||
def reduce(self, *args):
|
||||
if len(args) == 1:
|
||||
accumulator = args[0]
|
||||
it = iter(self._data)
|
||||
try:
|
||||
acc = next(it)
|
||||
except StopIteration:
|
||||
return Optional.empty()
|
||||
for x in it:
|
||||
acc = accumulator(acc, x)
|
||||
return Optional.of(acc)
|
||||
elif len(args) == 2:
|
||||
identity, accumulator = args
|
||||
acc = identity
|
||||
for x in self._data:
|
||||
acc = accumulator(acc, x)
|
||||
return acc
|
||||
else:
|
||||
identity, accumulator, combiner = args
|
||||
acc = identity
|
||||
for x in self._data:
|
||||
acc = accumulator(acc, x)
|
||||
return acc
|
||||
|
||||
def collect(self, *args):
|
||||
if not args:
|
||||
return list(self._data)
|
||||
if len(args) == 1:
|
||||
collector = args[0]
|
||||
supplier = getattr(collector, 'supplier', None)
|
||||
accumulator = getattr(collector, 'accumulator', None)
|
||||
finisher = getattr(collector, 'finisher', None)
|
||||
if supplier is not None and accumulator is not None:
|
||||
container = supplier() if callable(supplier) else supplier
|
||||
for x in self._data:
|
||||
if callable(accumulator):
|
||||
accumulator(container, x)
|
||||
if finisher is not None and callable(finisher):
|
||||
return finisher(container)
|
||||
return container
|
||||
if callable(collector):
|
||||
return collector(list(self._data))
|
||||
return list(self._data)
|
||||
supplier, accumulator, combiner = args[0], args[1], args[2]
|
||||
container = supplier() if callable(supplier) else supplier
|
||||
for x in self._data:
|
||||
if callable(accumulator):
|
||||
accumulator(container, x)
|
||||
return container
|
||||
|
||||
def count(self) -> int:
|
||||
return len(self._data)
|
||||
|
||||
def findFirst(self):
|
||||
return Optional.of(self._data[0]) if self._data else Optional.empty()
|
||||
|
||||
def findAny(self):
|
||||
return self.findFirst()
|
||||
|
||||
def anyMatch(self, predicate) -> bool:
|
||||
return any(predicate(x) for x in self._data)
|
||||
|
||||
def allMatch(self, predicate) -> bool:
|
||||
return all(predicate(x) for x in self._data)
|
||||
|
||||
def noneMatch(self, predicate) -> bool:
|
||||
return not any(predicate(x) for x in self._data)
|
||||
|
||||
def min(self, key=None):
|
||||
if not self._data:
|
||||
return Optional.empty()
|
||||
return Optional.of(min(self._data, key=key) if key else min(self._data))
|
||||
|
||||
def max(self, key=None):
|
||||
if not self._data:
|
||||
return Optional.empty()
|
||||
return Optional.of(max(self._data, key=key) if key else max(self._data))
|
||||
|
||||
def onClose(self, close_handler) -> '_Stream':
|
||||
return self
|
||||
|
||||
def close(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ArrayList
|
||||
# ============================================================
|
||||
@@ -294,6 +528,12 @@ class ArrayList(Stub):
|
||||
def replaceAll(self, operator) -> None:
|
||||
self._data = [operator(x) for x in self._data]
|
||||
|
||||
def spliterator(self) -> _Spliterator:
|
||||
return _Spliterator(self._data, _Spliterator.ORDERED)
|
||||
|
||||
def stream(self) -> _Stream:
|
||||
return _Stream(self._data)
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
if isinstance(other, ArrayList):
|
||||
return self._data == other._data
|
||||
@@ -789,6 +1029,10 @@ class LinkedHashMap(HashMap):
|
||||
key = next(iter(self._data))
|
||||
return (key, self._data[key])
|
||||
|
||||
def clone(self) -> 'LinkedHashMap':
|
||||
result = LinkedHashMap(self._data, 0.75, self._access_order)
|
||||
return result
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TreeMap
|
||||
@@ -993,6 +1237,48 @@ class TreeMap(Stub):
|
||||
return True
|
||||
return False
|
||||
|
||||
def replaceAll(self, function) -> None:
|
||||
for k in list(self._data.keys()):
|
||||
self._data[k] = function(k, self._data[k])
|
||||
|
||||
def compute(self, key, remapping_function):
|
||||
old = self._data.get(key)
|
||||
new_val = remapping_function(key, old)
|
||||
if new_val is not None:
|
||||
self._data[key] = new_val
|
||||
return new_val
|
||||
self._data.pop(key, None)
|
||||
return None
|
||||
|
||||
def computeIfAbsent(self, key, mapping_function):
|
||||
if key not in self._data:
|
||||
new_val = mapping_function(key)
|
||||
if new_val is not None:
|
||||
self._data[key] = new_val
|
||||
return new_val
|
||||
return self._data.get(key)
|
||||
|
||||
def computeIfPresent(self, key, remapping_function):
|
||||
if key in self._data:
|
||||
new_val = remapping_function(key, self._data[key])
|
||||
if new_val is not None:
|
||||
self._data[key] = new_val
|
||||
return new_val
|
||||
self._data.pop(key, None)
|
||||
return None
|
||||
|
||||
def merge(self, key, value, remapping_function):
|
||||
old = self._data.get(key)
|
||||
if old is None:
|
||||
self._data[key] = value
|
||||
return value
|
||||
new_val = remapping_function(old, value)
|
||||
if new_val is not None:
|
||||
self._data[key] = new_val
|
||||
return new_val
|
||||
self._data.pop(key, None)
|
||||
return None
|
||||
|
||||
def size(self) -> int:
|
||||
return len(self._data)
|
||||
|
||||
@@ -1140,6 +1426,19 @@ class HashSet(Stub):
|
||||
for item in list(self._data):
|
||||
action(item)
|
||||
|
||||
def removeIf(self, predicate) -> bool:
|
||||
old_size = len(self._data)
|
||||
to_remove = [x for x in self._data if predicate(x)]
|
||||
for x in to_remove:
|
||||
self._data.discard(x)
|
||||
return len(self._data) != old_size
|
||||
|
||||
def spliterator(self) -> _Spliterator:
|
||||
return _Spliterator(self._data, _Spliterator.DISTINCT)
|
||||
|
||||
def stream(self) -> _Stream:
|
||||
return _Stream(self._data)
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
if isinstance(other, HashSet):
|
||||
return self._data == other._data
|
||||
@@ -3445,6 +3744,18 @@ class PriorityQueue(Stub):
|
||||
for item in list(self._heap):
|
||||
action(item)
|
||||
|
||||
def spliterator(self) -> _Spliterator:
|
||||
if self._comparator:
|
||||
items = [v[1] for v in self._heap]
|
||||
else:
|
||||
items = list(self._heap)
|
||||
return _Spliterator(items)
|
||||
|
||||
def clone(self) -> 'PriorityQueue':
|
||||
result = PriorityQueue(comparator=self._comparator)
|
||||
result._heap = list(self._heap)
|
||||
return result
|
||||
|
||||
def toString(self) -> str:
|
||||
items = ", ".join(str(x) for x in self._heap)
|
||||
return f"[{items}]"
|
||||
|
||||
Reference in new issue
Block a user