feat: 第三轮深度完善 — SQLite/JSON/网络/媒体/文本 真实实现

SQLite真实数据库:
- SQLiteDatabase: execSQL/insert/insertOrThrow/replace/update/delete/query 用sqlite3
- 修复getVersion/setVersion用PRAGMA user_version
- 修复getMaximumSize/getPageSize/setMaximumSize/setPageSize用PRAGMA
- SQLiteStatement: execute/simpleQueryForLong/simpleQueryForString/execQuery
- SQLiteOpenHelper: onCreate/onUpgrade/onDowngrade回调正确触发
- 修复SQLiteCursor.moveToPosition越界处理
- 修复ContentValues值对提取bug

JSON真实实现:
- JSONObject: isNull/append/putOnce/putOpt/getNames
- JSONArray: 完整put/get/opt/length/toString

网络真实实现:
- NetworkInterface: getByName/getNetworkInterfaces/getHardwareAddress 用/sys/class/net+fcntl.ioctl
- InterfaceAddress: 新增类
- ConnectivityManager: getActiveNetwork/getAllNetworks 用LinuxNetwork
- WifiManager: getScanResults用nmcli, setWifiEnabled用nmcli/rfkill
- BluetoothAdapter: getAddress/getName 用bluetoothctl

媒体真实实现:
- MediaPlayer: prepare检查文件, getCurrentPosition实时计算, getDuration/getVideoWidth用ffprobe
- MediaRecorder: setVideoSize/setVideoFrameRate/setVideoEncodingBitRate配置存储
- MediaMetadataRetriever: extractMetadata用ffprobe, getFrameAtTime用ffmpeg, getEmbeddedPicture用ffmpeg

文本真实实现:
- TextUtils: split用re.split, concat/indexOf/lastIndexOf/urlEncode/urlDecode
- SpannableString: setSpan/getSpans/getSpanFlags/nextSpanTransition 真实实现
- SpannableStringBuilder: 修复append重载bug

Provider增强:
- Settings: putBoolean/getBoolean
- MediaStore: getContentUri/VOLUME常量
- ContactsContract: 补全常量和CommonDataKinds

Util增强:
- Log: w/e/wtf支持Throwable参数, 修复wtf重复定义bug
- TypedValue: 修复complexToDimension/complexToFloat/getFloat实现

修复:
- __init__.py: 补全NetworkInterface/InetAddress/MediaMetadataRetriever/SpannableStringBuilder导出

统计: 221模块, 3666类, 31005方法, 183529行
This commit is contained in:
shuiyu1123 committed 2026-06-25 00:40:59 +00:00
1 parent 4235f8692c
commit fbb8263b13
13 files changed
+1373 -146

No files matched your search

+80 -19
View File
@@ -7,6 +7,7 @@ import html as _html
import re as _re
import sys
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, Union
from urllib.parse import quote_plus as _quote_plus, unquote_plus as _unquote_plus
from .._core import (
Stub, AndroidOnlyError, android_context,
@@ -176,7 +177,9 @@ class TextUtils(Stub):
@staticmethod
def split(text: str, delimiter: str) -> List[str]:
return text.split(delimiter)
if text is None or len(text) == 0:
return []
return _re.split(delimiter, text)
@staticmethod
def htmlEncode(s: str) -> str:
@@ -186,6 +189,48 @@ class TextUtils(Stub):
def htmlDecode(s: str) -> str:
return _html.unescape(s)
@staticmethod
def concat(*texts: Any) -> str:
parts = []
for t in texts:
if t is not None:
parts.append(str(t))
return "".join(parts)
@staticmethod
def indexOf(s: Any, needle: Any, start: int = 0) -> int:
if s is None:
return -1
s = str(s)
needle = str(needle)
if start < 0:
start = 0
return s.find(needle, start)
@staticmethod
def lastIndexOf(s: Any, needle: Any, last: Optional[int] = None) -> int:
if s is None:
return -1
s = str(s)
needle = str(needle)
if last is None:
return s.rfind(needle)
if last < 0:
return -1
return s.rfind(needle, 0, last + 1)
@staticmethod
def urlEncode(s: str) -> str:
if s is None:
return ""
return _quote_plus(str(s))
@staticmethod
def urlDecode(s: str) -> str:
if s is None:
return ""
return _unquote_plus(str(s))
@staticmethod
def getReverse(s: str, start: int, end: int) -> str:
return s[start:end][::-1]
@@ -227,8 +272,13 @@ class TextUtils(Stub):
return text[:max_chars] + ellipsis
@staticmethod
def isDigitsOnly(s: str) -> bool:
return s.isdigit() if s else False
def isDigitsOnly(s: Any) -> bool:
if s is None:
return False
s = str(s)
if len(s) == 0:
return False
return s.isdigit()
@staticmethod
def isGraphical(s: str) -> bool:
@@ -293,12 +343,12 @@ class Spanned(Stub):
def __init__(self, source: str = ""):
super().__init__()
self._source = source
self._spans: Dict[Tuple[type, int], Tuple[int, int, Any]] = {} # (type, id) -> (start, end, span_obj)
self._spans: Dict[Tuple[type, int], Tuple[int, int, int, Any]] = {} # (type, id) -> (start, end, flags, span_obj)
def setSpan(self, span_obj: Any, start: int, end: int, flags: int):
span_id = id(span_obj)
span_type = type(span_obj)
self._spans[(span_type, span_id)] = (start, end, span_obj)
self._spans[(span_type, span_id)] = (start, end, flags, span_obj)
def removeSpan(self, span_obj: Any):
span_id = id(span_obj)
@@ -306,12 +356,13 @@ class Spanned(Stub):
self._spans.pop((span_type, span_id), None)
def getSpans(self, start: int, end: int, span_type: Optional[type] = None) -> List[Any]:
result = []
for (st, sid), (s, e, obj) in self._spans.items():
collected = []
for (st, sid), (s, e, flags, obj) in self._spans.items():
if span_type is None or st == span_type:
if s < end and e > start:
result.append(obj)
return result
collected.append((s, obj))
collected.sort(key=lambda t: t[0])
return [obj for _, obj in collected]
def getSpanStart(self, span_obj: Any) -> int:
span_id = id(span_obj)
@@ -329,10 +380,18 @@ class Spanned(Stub):
span_id = id(span_obj)
span_type = type(span_obj)
data = self._spans.get((span_type, span_id))
return 0 if data is None else 0
return data[2] if data else 0
def nextSpanTransition(self, start: int, end: int, span_type: Optional[type] = None) -> int:
return end
result = end
for (st, sid), (s, e, flags, obj) in self._spans.items():
if span_type is not None and st != span_type:
continue
if start < s < result:
result = s
if start < e < result:
result = e
return result
def toString(self) -> str:
return self._source
@@ -435,15 +494,17 @@ class SpannableStringBuilder(Editable):
else:
super().__init__(str(source))
def append(self, text: Any) -> "SpannableStringBuilder":
super().append(text)
return self
def append(self, text: Any, start: int, end: int) -> "SpannableStringBuilder":
if isinstance(text, str):
self._source += text[start:end]
def append(self, text: Any, start: Optional[int] = None,
end: Optional[int] = None) -> "SpannableStringBuilder":
if text is None:
return self
if start is None and end is None:
self._source += str(text)
else:
self._source += str(text)[start:end]
s = 0 if start is None else start
text_str = str(text)
e = len(text_str) if end is None else end
self._source += text_str[s:e]
return self
def insert(self, where: int, text: Any) -> "SpannableStringBuilder":