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:
shuiyu1123 committed 2026-06-25 00:17:50 +00:00
1 parent 39b1da37c9
commit 4235f8692c
13 files changed
+2248 -163

No files matched your search

+193 -13
View File
@@ -620,6 +620,9 @@ class GnssStatus(Stub):
return 0.0
def getBasebandCn0DbHz(self, index: int) -> float:
"""返回指定卫星的基带载噪比(dB-Hz)。"""
if 0 <= index < len(self._satellites):
return self._satellites[index].get("baseband_cn0", 0.0)
return 0.0
def getCn0DbHz(self, index: int) -> float:
@@ -873,6 +876,42 @@ class Address(Stub):
def setFeatureName(self, name: str):
self._feature_name = name
def setAdminArea(self, area: str):
self._admin_area = area
def setSubAdminArea(self, area: str):
self._sub_admin_area = area
def setLocality(self, locality: str):
self._locality = locality
def setSubLocality(self, sub_locality: str):
self._sub_locality = sub_locality
def setPremises(self, premises: str):
self._premises = premises
def setThoroughfare(self, thoroughfare: str):
self._thoroughfare = thoroughfare
def setSubThoroughfare(self, sub_thoroughfare: str):
self._sub_thoroughfare = sub_thoroughfare
def setPostalCode(self, postal_code: str):
self._postal_code = postal_code
def setCountryName(self, country_name: str):
self._country_name = country_name
def setCountryCode(self, country_code: str):
self._country_code = country_code
def setPhone(self, phone: str):
self._phone = phone
def setUrl(self, url: str):
self._url = url
def setLatitude(self, latitude: float):
self._latitude = latitude
self._has_lat_lon = True
@@ -898,29 +937,144 @@ class Address(Stub):
class Geocoder(Stub):
"""Geocoder — 地理编码/逆地理编码"""
# Nominatim (OpenStreetMap) 免费 API
_NOMINATIM_URL = "https://nominatim.openstreetmap.org"
_USER_AGENT = "Android-pyApi/1.0"
def __init__(self, context: Any = None, locale: Any = None):
super().__init__()
self._context = context
self._locale = locale
def _get_locale_str(self) -> str:
if self._locale is None:
return "en"
if hasattr(self._locale, "getLanguage"):
lang = self._locale.getLanguage()
country = self._locale.getCountry()
return f"{lang}-{country}" if country else lang
return str(self._locale)
@staticmethod
def _http_get_json(url: str) -> Optional[Any]:
"""使用 urllib 发送 GET 请求并解析 JSON。"""
try:
import urllib.request
import json
req = urllib.request.Request(url, headers={
"User-Agent": Geocoder._USER_AGENT,
"Accept-Language": "en",
})
with urllib.request.urlopen(req, timeout=10) as resp:
return json.loads(resp.read().decode("utf-8"))
except Exception:
return None
def getFromLocation(self, latitude: float, longitude: float,
max_results: int = 1) -> List[Address]:
"""逆地理编码:根据经纬度获取地址。优先使用 Nominatim API。"""
results: List[Address] = []
# 尝试在线逆地理编码
try:
url = (f"{self._NOMINATIM_URL}/reverse?"
f"lat={latitude}&lon={longitude}&format=jsonv2"
f"&addressdetails=1&limit={max_results}")
data = self._http_get_json(url)
if data and isinstance(data, dict) and "address" in data:
addr = self._parse_nominatim_reverse(data)
results.append(addr)
except Exception:
pass
# 回退到默认地址
if not results:
addr = Address()
addr.setLatitude(latitude)
addr.setLongitude(longitude)
addr.setFeatureName("Unknown Location")
addr.setLocality("Unknown")
addr.setCountryName("Unknown")
results.append(addr)
return results[:max_results] if max_results > 0 else []
def _parse_nominatim_reverse(self, data: dict) -> Address:
"""解析 Nominatim 逆地理编码响应。"""
addr = Address()
addr.setLatitude(latitude)
addr.setLongitude(longitude)
addr.setFeatureName("Unknown Location")
addr.setLocality("Unknown")
addr.setCountryName("Unknown")
return [addr] if max_results > 0 else []
address = data.get("address", {})
lat = data.get("lat")
lon = data.get("lon")
if lat is not None:
addr.setLatitude(float(lat))
if lon is not None:
addr.setLongitude(float(lon))
addr.setFeatureName(address.get("road") or address.get("building")
or data.get("name") or "Unknown")
addr.setLocality(address.get("city") or address.get("town")
or address.get("village") or address.get("county") or "Unknown")
addr.setAdminArea(address.get("state") or "")
addr.setSubAdminArea(address.get("state_district") or "")
addr.setCountryName(address.get("country") or "Unknown")
addr.setCountryCode(address.get("country_code", "").upper())
addr.setPostalCode(address.get("postcode") or "")
addr.setAddressLine(0, data.get("display_name", ""))
return addr
def getFromLocationName(self, location_name: str, max_results: int = 1,
lower_left_lat: Optional[float] = None,
lower_left_lon: Optional[float] = None,
upper_right_lat: Optional[float] = None,
upper_right_lon: Optional[float] = None) -> List[Address]:
"""地理编码:根据地名获取经纬度。优先使用 Nominatim API。"""
results: List[Address] = []
# 尝试在线地理编码
try:
import urllib.parse
params = {
"q": location_name,
"format": "jsonv2",
"addressdetails": "1",
"limit": str(max_results),
}
# 添加边界框
if all(v is not None for v in (lower_left_lat, lower_left_lon,
upper_right_lat, upper_right_lon)):
params["viewbox"] = f"{lower_left_lon},{upper_right_lat},{upper_right_lon},{lower_left_lat}"
params["bounded"] = "1"
query = urllib.parse.urlencode(params)
url = f"{self._NOMINATIM_URL}/search?{query}"
data = self._http_get_json(url)
if data and isinstance(data, list):
for item in data[:max_results]:
addr = self._parse_nominatim_search(item)
results.append(addr)
except Exception:
pass
# 回退到默认地址
if not results:
addr = Address()
addr.setFeatureName(location_name)
addr.setLocality(location_name)
results.append(addr)
return results[:max_results] if max_results > 0 else []
def _parse_nominatim_search(self, item: dict) -> Address:
"""解析 Nominatim 搜索响应。"""
addr = Address()
addr.setFeatureName(location_name)
addr.setLocality(location_name)
return [addr] if max_results > 0 else []
lat = item.get("lat")
lon = item.get("lon")
if lat is not None:
addr.setLatitude(float(lat))
if lon is not None:
addr.setLongitude(float(lon))
address = item.get("address", {})
addr.setFeatureName(item.get("name") or address.get("road") or "Unknown")
addr.setLocality(address.get("city") or address.get("town")
or address.get("village") or address.get("county") or "Unknown")
addr.setAdminArea(address.get("state") or "")
addr.setCountryName(address.get("country") or "Unknown")
addr.setCountryCode(address.get("country_code", "").upper())
addr.setPostalCode(address.get("postcode") or "")
addr.setAddressLine(0, item.get("display_name", ""))
return addr
# ═══════════════════════════════════════════════════════════════
@@ -956,6 +1110,9 @@ class LocationManager(Stub):
self._last_known_locations: Dict[str, Location] = {}
self._enabled_providers = {self.GPS_PROVIDER, self.NETWORK_PROVIDER,
self.PASSIVE_PROVIDER, self.FUSED_PROVIDER}
self._test_providers: Dict[str, LocationProvider] = {}
self._test_locations: Dict[str, Location] = {}
self._proximity_alerts: List[Dict[str, Any]] = []
def getLastKnownLocation(self, provider: str) -> Optional[Location]:
if _USE_LINUX:
@@ -1036,19 +1193,42 @@ class LocationManager(Stub):
def addProximityAlert(self, latitude: float, longitude: float,
radius: float, expiration: int, intent: Any):
pass
"""添加接近警报。记录警报信息,在位置更新时检查是否进入/离开区域。"""
import time as _time
alert = {
"latitude": latitude,
"longitude": longitude,
"radius": radius,
"expiration": expiration,
"intent": intent,
"created_at": _time.time(),
"last_state": None, # None=未触发, True=在区域内, False=在区域外
}
self._proximity_alerts.append(alert)
def sendExtraCommand(self, provider: str, command: str, extras: Any) -> bool:
"""向位置提供者发送额外命令。桌面端无实际效果,返回成功。"""
return True
def clearTestProviderLocation(self, provider: str):
pass
"""清除测试提供者的位置数据。"""
self._test_locations.pop(provider, None)
def setTestProviderLocation(self, provider: str, location: Location):
pass
"""设置测试提供者的位置。"""
self._test_locations[provider] = location
# 通知该提供者的监听器
if provider in self._listeners:
for listener in self._listeners[provider]:
try:
listener.onLocationChanged(location)
except Exception:
pass
def removeTestProvider(self, provider: str):
pass
"""移除测试提供者。"""
self._test_providers.pop(provider, None)
self._test_locations.pop(provider, None)
def addTestProvider(self, name: str, requires_network: bool, requires_satellite: bool,
requires_cell: bool, has_monetary_cost: bool, supports_altitude: bool,