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
+200
-23
@@ -24,7 +24,7 @@ __all__ = [
|
||||
"InetAddress", "InetSocketAddress",
|
||||
"Socket", "ServerSocket", "DatagramSocket", "DatagramPacket",
|
||||
"Proxy", "ProxySelector", "Authenticator", "PasswordAuthentication",
|
||||
"NetworkInterface", "URI",
|
||||
"NetworkInterface", "InterfaceAddress", "URI",
|
||||
"CookieHandler", "CookieManager", "HttpCookie",
|
||||
"URLDecoder", "URLEncoder",
|
||||
"SocketException", "ConnectException", "BindException",
|
||||
@@ -1289,26 +1289,79 @@ class PasswordAuthentication(Stub):
|
||||
return self._password
|
||||
|
||||
|
||||
# ============================================================
|
||||
# InterfaceAddress
|
||||
# ============================================================
|
||||
|
||||
class InterfaceAddress(Stub):
|
||||
"""java.net.InterfaceAddress — 接口地址信息 (地址/广播/前缀长度)"""
|
||||
|
||||
def __init__(self, address=None, broadcast=None, prefix_length=0):
|
||||
super().__init__()
|
||||
self._address = address # InetAddress
|
||||
self._broadcast = broadcast # InetAddress or None
|
||||
self._prefix_length = prefix_length
|
||||
|
||||
def getAddress(self):
|
||||
return self._address
|
||||
|
||||
def getBroadcast(self):
|
||||
return self._broadcast
|
||||
|
||||
def getNetworkPrefixLength(self):
|
||||
return self._prefix_length
|
||||
|
||||
def equals(self, other):
|
||||
if isinstance(other, InterfaceAddress):
|
||||
return (self._address == other._address
|
||||
and self._prefix_length == other._prefix_length)
|
||||
return False
|
||||
|
||||
def hashCode(self):
|
||||
return hash((repr(self._address), self._prefix_length)) & 0x7FFFFFFF
|
||||
|
||||
def toString(self):
|
||||
addr = self._address.getHostAddress() if self._address else "0.0.0.0"
|
||||
return f"{addr}/{self._prefix_length}"
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NetworkInterface
|
||||
# ============================================================
|
||||
|
||||
class NetworkInterface(Stub):
|
||||
_cache = {}
|
||||
_initialized = False
|
||||
|
||||
def __init__(self, name, display_name, addrs):
|
||||
super().__init__()
|
||||
self._name = name
|
||||
self._display_name = display_name
|
||||
self._addrs = addrs
|
||||
self._mac = None # bytes, hardware address
|
||||
self._mtu = 1500
|
||||
self._state = "unknown"
|
||||
self._flags = 0
|
||||
self._interface_addrs = [] # List[InterfaceAddress]
|
||||
|
||||
@staticmethod
|
||||
def _read_sys_file(path):
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
return f.read().strip()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def getByName(name):
|
||||
if name in NetworkInterface._cache:
|
||||
return NetworkInterface._cache[name]
|
||||
if name is None:
|
||||
return None
|
||||
NetworkInterface._ensure_init()
|
||||
return NetworkInterface._cache.get(name)
|
||||
|
||||
@staticmethod
|
||||
def getByInetAddress(addr):
|
||||
NetworkInterface._ensure_init()
|
||||
for ni in NetworkInterface._cache.values():
|
||||
for a in ni._addrs:
|
||||
if a.equals(addr):
|
||||
@@ -1317,8 +1370,18 @@ class NetworkInterface(Stub):
|
||||
|
||||
@staticmethod
|
||||
def getNetworkInterfaces():
|
||||
NetworkInterface._ensure_init()
|
||||
return list(NetworkInterface._cache.values())
|
||||
|
||||
@staticmethod
|
||||
def _ensure_init():
|
||||
if not NetworkInterface._initialized:
|
||||
NetworkInterface._initialized = True
|
||||
try:
|
||||
NetworkInterface._init_from_socket()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def getName(self):
|
||||
return self._name
|
||||
|
||||
@@ -1329,25 +1392,25 @@ class NetworkInterface(Stub):
|
||||
return iter(self._addrs)
|
||||
|
||||
def getInterfaceAddresses(self):
|
||||
return self._addrs
|
||||
return list(self._interface_addrs)
|
||||
|
||||
def isUp(self):
|
||||
return True
|
||||
return self._state.lower() == "up" or (self._flags & 0x1) != 0
|
||||
|
||||
def isLoopback(self):
|
||||
return self._name == "lo"
|
||||
return (self._flags & 0x8) != 0 or self._name == "lo"
|
||||
|
||||
def isPointToPoint(self):
|
||||
return False
|
||||
return (self._flags & 0x10) != 0
|
||||
|
||||
def supportsMulticast(self):
|
||||
return True
|
||||
return (self._flags & 0x1000) != 0
|
||||
|
||||
def getHardwareAddress(self):
|
||||
return None
|
||||
return self._mac
|
||||
|
||||
def getMTU(self):
|
||||
return 1500
|
||||
return self._mtu
|
||||
|
||||
def getSubInterfaces(self):
|
||||
return iter([])
|
||||
@@ -1363,25 +1426,139 @@ class NetworkInterface(Stub):
|
||||
|
||||
@staticmethod
|
||||
def _init_from_socket():
|
||||
import netifaces
|
||||
for iface_name in netifaces.interfaces():
|
||||
"""从 /sys/class/net/ 和 socket/fcntl 枚举真实网络接口 (不依赖 netifaces)"""
|
||||
import os as _os
|
||||
net_dir = "/sys/class/net"
|
||||
if not _os.path.isdir(net_dir):
|
||||
# 非 Linux 环境: 尝试用 socket 获取本机地址
|
||||
try:
|
||||
hostname = _socket.gethostname()
|
||||
addr = InetAddress.getByName(hostname)
|
||||
ni = NetworkInterface(hostname, hostname, [addr])
|
||||
NetworkInterface._cache[hostname] = ni
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
# 尝试用 fcntl.ioctl 获取 IPv4 地址/掩码/广播
|
||||
fcntl_available = True
|
||||
try:
|
||||
import fcntl as _fcntl
|
||||
except ImportError:
|
||||
fcntl_available = False
|
||||
|
||||
for iface_name in _os.listdir(net_dir):
|
||||
addrs = []
|
||||
ifaddresses = netifaces.ifaddresses(iface_name)
|
||||
for family in [netifaces.AF_INET, netifaces.AF_INET6]:
|
||||
if family in ifaddresses:
|
||||
for addr_info in ifaddresses[family]:
|
||||
interface_addrs = []
|
||||
mac = None
|
||||
mtu = 1500
|
||||
state = "unknown"
|
||||
flags = 0
|
||||
|
||||
# --- MAC 地址 ---
|
||||
mac_str = NetworkInterface._read_sys_file(f"{net_dir}/{iface_name}/address")
|
||||
if mac_str:
|
||||
try:
|
||||
mac = bytes(int(b, 16) for b in mac_str.split(":"))
|
||||
except Exception:
|
||||
mac = None
|
||||
|
||||
# --- MTU ---
|
||||
mtu_str = NetworkInterface._read_sys_file(f"{net_dir}/{iface_name}/mtu")
|
||||
if mtu_str:
|
||||
try:
|
||||
mtu = int(mtu_str)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# --- operstate ---
|
||||
state = NetworkInterface._read_sys_file(
|
||||
f"{net_dir}/{iface_name}/operstate") or "unknown"
|
||||
|
||||
# --- flags (十六进制字符串, 如 0x1003) ---
|
||||
flags_str = NetworkInterface._read_sys_file(
|
||||
f"{net_dir}/{iface_name}/flags")
|
||||
if flags_str:
|
||||
try:
|
||||
flags = int(flags_str, 16)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# --- IPv4 地址 (fcntl.ioctl) ---
|
||||
if fcntl_available:
|
||||
sock = None
|
||||
try:
|
||||
sock = _socket.socket(_socket.AF_INET, _socket.SOCK_DGRAM)
|
||||
packed = _struct.pack('256s', iface_name.encode()[:15])
|
||||
# SIOCGIFADDR = 0x8915
|
||||
result = _fcntl.ioctl(sock.fileno(), 0x8915, packed)
|
||||
ip_raw = result[20:24]
|
||||
inet_addr = InetAddress(iface_name, bytes(ip_raw))
|
||||
addrs.append(inet_addr)
|
||||
|
||||
# SIOCGIFNETMASK = 0x891b
|
||||
prefix = 24
|
||||
try:
|
||||
result = _fcntl.ioctl(sock.fileno(), 0x891b, packed)
|
||||
netmask_str = _socket.inet_ntoa(result[20:24])
|
||||
prefix = sum(bin(int(b)).count('1') for b in netmask_str.split('.'))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# SIOCGIFBRDADDR = 0x8919 (广播地址)
|
||||
broadcast_addr = None
|
||||
try:
|
||||
result = _fcntl.ioctl(sock.fileno(), 0x8919, packed)
|
||||
bcast_raw = result[20:24]
|
||||
broadcast_addr = InetAddress(iface_name, bytes(bcast_raw))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
interface_addrs.append(InterfaceAddress(
|
||||
address=inet_addr,
|
||||
broadcast=broadcast_addr,
|
||||
prefix_length=prefix
|
||||
))
|
||||
except OSError:
|
||||
pass # 接口没有 IPv4 地址
|
||||
finally:
|
||||
if sock is not None:
|
||||
try:
|
||||
addr = addr_info["addr"]
|
||||
if "." in addr:
|
||||
addrs.append(InetAddress(addr, _socket.inet_pton(_socket.AF_INET, addr)))
|
||||
else:
|
||||
addrs.append(InetAddress(addr, _socket.inet_pton(_socket.AF_INET6, addr)))
|
||||
sock.close()
|
||||
except Exception:
|
||||
pass
|
||||
NetworkInterface._cache[iface_name] = NetworkInterface(iface_name, iface_name, addrs)
|
||||
|
||||
# --- IPv6 地址 (/proc/net/if_inet6) ---
|
||||
try:
|
||||
with open("/proc/net/if_inet6", "r") as f:
|
||||
for line in f:
|
||||
parts = line.split()
|
||||
if len(parts) >= 6 and parts[5] == iface_name:
|
||||
hex_addr = parts[0]
|
||||
raw = bytes.fromhex(hex_addr)
|
||||
prefix6 = int(parts[2], 16) if parts[2] else 64
|
||||
inet6_addr = InetAddress(iface_name, raw)
|
||||
addrs.append(inet6_addr)
|
||||
interface_addrs.append(InterfaceAddress(
|
||||
address=inet6_addr,
|
||||
broadcast=None,
|
||||
prefix_length=prefix6
|
||||
))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
ni = NetworkInterface(iface_name, iface_name, addrs)
|
||||
ni._mac = mac
|
||||
ni._mtu = mtu
|
||||
ni._state = state
|
||||
ni._flags = flags
|
||||
ni._interface_addrs = interface_addrs
|
||||
NetworkInterface._cache[iface_name] = ni
|
||||
|
||||
|
||||
# 初始化缓存
|
||||
try:
|
||||
NetworkInterface._init_from_socket()
|
||||
NetworkInterface._ensure_init()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in new issue
Block a user