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:
1 parent
4235f8692c
commit
fbb8263b13
13 files changed
+1373
-146
No files matched your search
@@ -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":
|
||||
|
||||
Reference in new issue
Block a user