Files
Android-pyApi/android_pyapi/android/net_wifi.py
T
shuiyu1123 fbb8263b13 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行
2026-06-25 00:40:59 +00:00

1136 lines
37 KiB
Python

"""
Android WiFi 组件 — WifiManager, WifiInfo, ScanResult 等
方法签名完全对齐 Android SDK
"""
import os
import sys
import json
import random
from typing import Any, Dict, List, Optional, Set, Tuple, Union
from datetime import datetime
from .._core import (
Stub, AndroidOnlyError, android_context,
resolve_android_path, to_android_path,
_sdcard_root, _app_data_dir, _package_name,
)
# Linux 真实实现导入
try:
from .._linux_impl import IS_LINUX, LinuxNetwork, HAS_IP
_USE_LINUX = IS_LINUX
except ImportError:
_USE_LINUX = False
# ═══════════════════════════════════════════════════════════════
# SupplicantState
# ═══════════════════════════════════════════════════════════════
class SupplicantState(Stub):
"""SupplicantState — wpa_supplicant 状态枚举"""
ASSOCIATED = "ASSOCIATED"
ASSOCIATING = "ASSOCIATING"
COMPLETED = "COMPLETED"
DISCONNECTED = "DISCONNECTED"
DORMANT = "DORMANT"
FOUR_WAY_HANDSHAKE = "FOUR_WAY_HANDSHAKE"
GROUP_HANDSHAKE = "GROUP_HANDSHAKE"
INACTIVE = "INACTIVE"
INTERFACE_DISABLED = "INTERFACE_DISABLED"
INVALID = "INVALID"
SCANNING = "SCANNING"
UNINITIALIZED = "UNINITIALIZED"
_VALID_STATES = [
"ASSOCIATED", "ASSOCIATING", "COMPLETED", "DISCONNECTED",
"DORMANT", "FOUR_WAY_HANDSHAKE", "GROUP_HANDSHAKE", "INACTIVE",
"INTERFACE_DISABLED", "INVALID", "SCANNING", "UNINITIALIZED",
]
def __init__(self, state: str = "DISCONNECTED"):
super().__init__()
self._state = state if state in self._VALID_STATES else "INVALID"
def getState(self) -> str:
return self._state
def toString(self) -> str:
return self._state
@staticmethod
def isValid(state_str: str) -> bool:
return state_str in SupplicantState._VALID_STATES
def compareTo(self, other: "SupplicantState") -> int:
if self._state == other._state:
return 0
return -1 if (self._VALID_STATES.index(self._state)
< self._VALID_STATES.index(other._state)) else 1
def equals(self, other) -> bool:
if isinstance(other, SupplicantState):
return self._state == other._state
return False
def hashCode(self) -> int:
return hash(self._state) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# WifiSsid
# ═══════════════════════════════════════════════════════════════
class WifiSsid(Stub):
"""WifiSsid — WiFi SSID 封装"""
def __init__(self, ssid: str = ""):
super().__init__()
self._ssid = ssid
@staticmethod
def createFromAsciiBytes(ssid_bytes: bytes) -> "WifiSsid":
try:
return WifiSsid(ssid_bytes.decode("utf-8"))
except UnicodeDecodeError:
return WifiSsid(repr(ssid_bytes))
@staticmethod
def createFromHex(hex_str: str) -> "WifiSsid":
try:
decoded = bytes.fromhex(hex_str).decode("utf-8", errors="replace")
return WifiSsid(decoded)
except Exception:
return WifiSsid(hex_str)
def toString(self) -> str:
return self._ssid
# ═══════════════════════════════════════════════════════════════
# WifiConfiguration
# ═══════════════════════════════════════════════════════════════
class WifiConfiguration(Stub):
"""WifiConfiguration — WiFi 网络配置"""
SECURITY_OPEN = 0
SECURITY_WEP = 1
SECURITY_PSK = 2
SECURITY_EAP = 3
SECURITY_SAE = 4
SECURITY_OWE = 5
class KeyMgmt(Stub):
NONE = 0
WPA_PSK = 1
WPA_EAP = 2
IEEE8021X = 3
WPA2_PSK = 4
OSEN = 5
FT_PSK = 6
FT_EAP = 7
SAE = 8
OWE = 9
SUITE_B_192 = 10
WPA3_SAE = 8
WPA3_OWE = 9
class GroupCipher(Stub):
NONE = 0
TKIP = 1
CCMP = 2
TKIP_CCMP = 3
AES = 4
SMS4 = 5
GCMP_128 = 6
GCMP_256 = 7
BIP_GMAC_128 = 8
BIP_GMAC_256 = 9
BIP_CMAC_256 = 10
class PairwiseCipher(Stub):
NONE = 0
TKIP = 1
CCMP = 2
NONE_ = 3
GCMP_128 = 4
GCMP_256 = 5
SMS4 = 6
class AuthAlgorithm(Stub):
OPEN = 0
SHARED = 1
LEAP = 2
class Protocol(Stub):
RSN = 0
WPA = 1
OSEN = 2
class Status(Stub):
CURRENT = 0
DISABLED = 1
ENABLED = 2
def __init__(self):
super().__init__()
self.SSID: Optional[str] = None
self.BSSID: Optional[str] = None
self.preSharedKey: Optional[str] = None
self.status: int = WifiConfiguration.Status.DISABLED
self.networkId: int = -1
self.allowedKeyManagement: Set[int] = set()
self.allowedGroupCiphers: Set[int] = set()
self.allowedPairwiseCiphers: Set[int] = set()
self.allowedAuthAlgorithms: Set[int] = set()
self.allowedProtocols: Set[int] = set()
self.hiddenSSID: bool = False
self.priority: int = 0
self.wepKeys: List[Optional[str]] = [None, None, None, None]
self.wepTxKeyIndex: int = 0
self.isEnterprise: bool = False
self._enterprise_config: Optional["WifiEnterpriseConfig"] = None
def getNetworkId(self) -> int:
return self.networkId
def toString(self) -> str:
ssid = self.SSID or "(none)"
return f"WifiConfiguration(SSID={ssid}, id={self.networkId})"
def hashCode(self) -> int:
return hash(self.SSID) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# WifiEnterpriseConfig
# ═══════════════════════════════════════════════════════════════
class WifiEnterpriseConfig(Stub):
"""WifiEnterpriseConfig — 企业级 WiFi 配置"""
def __init__(self):
super().__init__()
self._identity: str = ""
self._password: str = ""
self._ca_cert: Optional[str] = None
self._client_cert: Optional[str] = None
self._subject_match: str = ""
self._alt_subject_match: str = ""
self._domain_suffix_match: str = ""
self._eap_method: int = -1
self._phase2_method: int = -1
def setIdentity(self, identity: str):
self._identity = identity
def getIdentity(self) -> str:
return self._identity
def setPassword(self, password: str):
self._password = password
def getPassword(self) -> str:
return self._password
def setCaCertificate(self, cert: Any):
pass
def getCaCertificate(self) -> Optional[Any]:
return None
def setClientCertificate(self, cert: Any):
pass
def getClientCertificate(self) -> Optional[Any]:
return None
def setSubjectMatch(self, match: str):
self._subject_match = match
def getSubjectMatch(self) -> str:
return self._subject_match
def setDomainSuffixMatch(self, match: str):
self._domain_suffix_match = match
def getDomainSuffixMatch(self) -> str:
return self._domain_suffix_match
def toString(self) -> str:
return f"WifiEnterpriseConfig(identity={self._identity})"
# ═══════════════════════════════════════════════════════════════
# WifiInfo
# ═══════════════════════════════════════════════════════════════
class WifiInfo(Stub):
"""WifiInfo — WiFi 连接信息"""
LINK_SPEED_UNITS = "Mbps"
STANDARD_LEGACY = 1
STANDARD_11N = 4
STANDARD_11AC = 5
STANDARD_11AX = 6
STANDARD_11BE = 7
SECURITY_TYPE_OPEN = 0
SECURITY_TYPE_WEP = 1
SECURITY_TYPE_PSK = 2
SECURITY_TYPE_EAP = 3
SECURITY_TYPE_SAE = 4
SECURITY_TYPE_OWE = 5
SECURITY_TYPE_WAPI_PSK = 6
SECURITY_TYPE_PASSPOINT_R1_R2 = 7
SECURITY_TYPE_PASSPOINT_R3 = 8
INVALID_RSSI = -127
DEFAULT_RSSI = -60
def __init__(self):
super().__init__()
self._ssid: str = "<unknown ssid>"
self._bssid: str = "00:00:00:00:00:00"
self._rssi: int = self.INVALID_RSSI
self._link_speed: int = 0
self._frequency: int = 0
self._ip_address: int = 0
self._mac_address: str = "02:00:00:00:00:00"
self._network_id: int = -1
self._supplicant_state: SupplicantState = SupplicantState(SupplicantState.DISCONNECTED)
self._wifi_standard: int = self.STANDARD_LEGACY
self._is_hidden_ssid: bool = False
self._tx_link_speed: int = 0
self._rx_link_speed: int = 0
self._max_rx_link_speed: int = 0
self._max_tx_link_speed: int = 0
self._security_type: int = self.SECURITY_TYPE_OPEN
self._rssi_timestamp: int = 0
def getSSID(self) -> str:
return self._ssid
def getBSSID(self) -> str:
return self._bssid
def getRssi(self) -> int:
return self._rssi
def getLinkSpeed(self) -> int:
return self._link_speed
def getFrequency(self) -> int:
return self._frequency
def getIpAddress(self) -> int:
return self._ip_address
def getMacAddress(self) -> str:
return self._mac_address
def getNetworkId(self) -> int:
return self._network_id
def getSupplicantState(self) -> SupplicantState:
return self._supplicant_state
def getWifiStandard(self) -> int:
return self._wifi_standard
def isHiddenSSID(self) -> bool:
return self._is_hidden_ssid
def getTxLinkSpeedMbps(self) -> int:
return self._tx_link_speed
def getRxLinkSpeedMbps(self) -> int:
return self._rx_link_speed
def getMaxSupportedRxLinkSpeedMbps(self) -> int:
return self._max_rx_link_speed
def getMaxSupportedTxLinkSpeedMbps(self) -> int:
return self._max_tx_link_speed
def getSecurityType(self) -> int:
return self._security_type
def getRssiTimestamp(self) -> int:
return self._rssi_timestamp
def toString(self) -> str:
return (f"WifiInfo(SSID={self._ssid}, BSSID={self._bssid}, "
f"rssi={self._rssi}, speed={self._link_speed} {self.LINK_SPEED_UNITS})")
def hashCode(self) -> int:
return hash(self._bssid) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# ScanResult
# ═══════════════════════════════════════════════════════════════
class ScanResult(Stub):
"""ScanResult — WiFi 扫描结果"""
WIFI_BAND_24_GHZ = 0
WIFI_BAND_5_GHZ = 1
WIFI_BAND_6_GHZ = 2
CHANNEL_WIDTH_20MHZ = 0
CHANNEL_WIDTH_40MHZ = 1
CHANNEL_WIDTH_80MHZ = 2
CHANNEL_WIDTH_160MHZ = 3
CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4
UNSPECIFIED = -1
def __init__(self):
super().__init__()
self.SSID: str = ""
self.BSSID: str = ""
self.capabilities: str = ""
self.level: int = 0
self.frequency: int = 0
self.timestamp: int = 0
self.channelWidth: int = self.CHANNEL_WIDTH_20MHZ
self.centerFreq0: int = 0
self.centerFreq1: int = 0
self.operatorFriendlyName: str = ""
self.venueName: str = ""
self.is80211mcResponder: bool = False
self.isPasspointNetwork: bool = False
self._wifi_standard: int = 0
self._seen: int = 0
self._distance: Optional[float] = None
self._distance_sd: Optional[float] = None
def getSSID(self) -> str:
return self.SSID
def getBSSID(self) -> str:
return self.BSSID
def getCapabilities(self) -> str:
return self.capabilities
def getLevel(self) -> int:
return self.level
def getFrequency(self) -> int:
return self.frequency
def getTimestamp(self) -> int:
return self.timestamp
def getChannelWidth(self) -> int:
return self.channelWidth
def getCenterFreq0(self) -> int:
return self.centerFreq0
def getCenterFreq1(self) -> int:
return self.centerFreq1
def getOperatorFriendlyName(self) -> str:
return self.operatorFriendlyName
def getVenueName(self) -> str:
return self.venueName
def is80211mcResponder(self) -> bool:
return self.is80211mcResponder
def isPasspointNetwork(self) -> bool:
return self.isPasspointNetwork
def getWifiStandard(self) -> int:
return self._wifi_standard
def getDistance(self) -> Optional[float]:
return self._distance
def getDistanceSd(self) -> Optional[float]:
return self._distance_sd
def toString(self) -> str:
return f"ScanResult(SSID={self.SSID}, BSSID={self.BSSID}, level={self.level})"
# ═══════════════════════════════════════════════════════════════
# WifiNetworkSpecifier
# ═══════════════════════════════════════════════════════════════
class WifiNetworkSpecifier(Stub):
"""WifiNetworkSpecifier — WiFi 网络说明符"""
def __init__(self, ssid: Optional[str] = None, bssid: Optional[str] = None,
band: int = 0, security_type: int = 0):
super().__init__()
self._ssid = ssid
self._bssid = bssid
self._band = band
self._security_type = security_type
def getSsid(self) -> Optional[str]:
return self._ssid
def getBssid(self) -> Optional[str]:
return self._bssid
def getBand(self) -> int:
return self._band
def toString(self) -> str:
return f"WifiNetworkSpecifier(SSID={self._ssid})"
# ═══════════════════════════════════════════════════════════════
# WifiNetworkSuggestion
# ═══════════════════════════════════════════════════════════════
class WifiNetworkSuggestion(Stub):
"""WifiNetworkSuggestion — WiFi 网络建议"""
def __init__(self, ssid: str = "", bssid: Optional[str] = None,
is_hidden: bool = False, priority: int = 0,
wpa2_passphrase: Optional[str] = None,
wpa3_passphrase: Optional[str] = None,
is_owe: bool = False):
super().__init__()
self._ssid = ssid
self._bssid = bssid
self._is_hidden = is_hidden
self._priority = priority
self._wpa2_passphrase = wpa2_passphrase
self._wpa3_passphrase = wpa3_passphrase
self._is_owe = is_owe
def getSsid(self) -> str:
return self._ssid
def getBssid(self) -> Optional[str]:
return self._bssid
def isHidden(self) -> bool:
return self._is_hidden
def getPriority(self) -> int:
return self._priority
def toString(self) -> str:
return f"WifiNetworkSuggestion(SSID={self._ssid})"
# ═══════════════════════════════════════════════════════════════
# WifiManager helpers
# ═══════════════════════════════════════════════════════════════
class WifiManagerMulticastLock(Stub):
"""WifiManager.MulticastLock"""
def __init__(self, tag: str):
super().__init__()
self._tag = tag
self._held = False
self._ref_count = 0
def acquire(self):
self._held = True
self._ref_count += 1
def release(self):
if self._ref_count > 0:
self._ref_count -= 1
if self._ref_count == 0:
self._held = False
def isHeld(self) -> bool:
return self._held
def toString(self) -> str:
return f"MulticastLock(tag={self._tag}, held={self._held})"
class WifiManagerLocalOnlyHotspotCallback(Stub):
"""WifiManager.LocalOnlyHotspotCallback"""
ERROR_NO_CHANNEL = 1
ERROR_GENERIC = 2
ERROR_INCOMPATIBLE_MODE = 3
ERROR_TETHERING_DISALLOWED = 4
def onStarted(self, hotspot: Any):
pass
def onStopped(self):
pass
def onFailed(self, reason: int):
pass
class WifiManagerWpsCallback(Stub):
"""WifiManager.WpsCallback"""
def onStarted(self, pin: str):
pass
def onSucceeded(self):
pass
def onFailed(self, reason: int):
pass
# ═══════════════════════════════════════════════════════════════
# WifiManager
# ═══════════════════════════════════════════════════════════════
class WifiManager(Stub):
"""WifiManager — WiFi 管理器"""
WIFI_STATE_DISABLING = 0
WIFI_STATE_DISABLED = 1
WIFI_STATE_ENABLING = 2
WIFI_STATE_ENABLED = 3
WIFI_STATE_UNKNOWN = 4
WIFI_MODE_FULL = 1
WIFI_MODE_FULL_HIGH_PERF = 3
WIFI_MODE_SCAN_ONLY = 2
ERROR_AUTHENTICATING = 1
SAP_START_FAILURE_GENERAL = 0
ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"
SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE"
SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.SUPPLICANT_STATE_CHANGED"
NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"
SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"
WIFI_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_STATE_CHANGED"
RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"
NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"
def __init__(self):
super().__init__()
self._wifi_state = self.WIFI_STATE_ENABLED
self._wifi_enabled = True
self._connection_info: Optional[WifiInfo] = None
self._scan_results: List[ScanResult] = []
self._configured_networks: List[WifiConfiguration] = []
self._network_suggestions: List[WifiNetworkSuggestion] = []
self._listeners: Dict[str, List[Any]] = {}
self._next_network_id = 0
self._p2p_channels: List[int] = []
def getConnectionInfo(self) -> Optional[WifiInfo]:
if _USE_LINUX:
return self._get_linux_connection_info()
if self._connection_info is None:
info = WifiInfo()
info._ssid = '"mock_wifi"'
info._bssid = "00:1A:2B:3C:4D:5E"
info._rssi = -55
info._link_speed = 1300
info._frequency = 5180
info._network_id = 0
info._supplicant_state = SupplicantState(SupplicantState.COMPLETED)
self._connection_info = info
return self._connection_info
def getWifiInfo(self) -> Optional[WifiInfo]:
"""getWifiInfo — getConnectionInfo 的别名"""
return self.getConnectionInfo()
def _get_linux_connection_info(self) -> WifiInfo:
"""从 LinuxNetwork.get_wifi_info() 构造 WifiInfo"""
info = WifiInfo()
try:
data = LinuxNetwork.get_wifi_info() or {}
ssid = data.get("ssid", "")
info._ssid = f'"{ssid}"' if ssid else "<unknown ssid>"
info._bssid = data.get("bssid", "00:00:00:00:00:00")
# signal 通常是 0-100, 转换为 RSSI (dBm, 约 -100..0)
signal = data.get("signal", 0)
if isinstance(signal, (int, float)) and signal > 0:
info._rssi = int(-100 + (signal / 100.0) * 60)
else:
info._rssi = int(signal) if signal else WifiInfo.INVALID_RSSI
iface = data.get("interface", "")
if iface:
info._frequency = 2412 # 默认 2.4GHz
info._link_speed = data.get("link_speed", 0) or 0
info._network_id = 0
info._supplicant_state = SupplicantState(SupplicantState.COMPLETED)
except Exception:
pass
return info
def getScanResults(self) -> List[ScanResult]:
if _USE_LINUX:
results = self._linux_scan_results()
if results is not None:
return results
return list(self._scan_results)
def _linux_scan_results(self) -> Optional[List[ScanResult]]:
"""通过 nmcli 获取 WiFi 扫描结果 (真实实现)"""
import subprocess
import re
try:
proc = subprocess.run(
["nmcli", "-t", "-f", "ssid,bssid,signal,freq,security",
"dev", "wifi", "list"],
capture_output=True, text=True, timeout=15,
)
if proc.returncode != 0:
return None
results: List[ScanResult] = []
seen: Set[str] = set()
for line in proc.stdout.strip().split("\n"):
if not line:
continue
# nmcli -t 模式中值内的 : 被转义为 \:, 按非转义 : 分割
parts = re.split(r'(?<!\\):', line)
parts = [p.replace('\\:', ':') for p in parts]
if len(parts) < 5:
continue
ssid = parts[0]
bssid = parts[1]
if not bssid or bssid in seen:
continue
seen.add(bssid)
sr = ScanResult()
sr.SSID = ssid
sr.BSSID = bssid
try:
sr.level = int(parts[2]) if parts[2] else 0
except ValueError:
sr.level = 0
try:
sr.frequency = int(float(parts[3])) if parts[3] else 0
except ValueError:
sr.frequency = 0
sr.capabilities = parts[4] if len(parts) > 4 else ""
results.append(sr)
return results
except Exception:
return None
def startScan(self) -> bool:
return True
def setWifiEnabled(self, enabled: bool) -> bool:
if _USE_LINUX:
import subprocess
import shutil
try:
cmd = ["nmcli", "radio", "wifi", "on" if enabled else "off"]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
if proc.returncode != 0 and shutil.which("rfkill"):
# 回退到 rfkill
rfkill_cmd = (["rfkill", "unblock", "wifi"] if enabled
else ["rfkill", "block", "wifi"])
subprocess.run(rfkill_cmd, capture_output=True, timeout=5)
except Exception:
pass
self._wifi_enabled = enabled
self._wifi_state = self.WIFI_STATE_ENABLED if enabled else self.WIFI_STATE_DISABLED
return True
def isWifiEnabled(self) -> bool:
if _USE_LINUX:
return self._linux_has_wireless_interface()
return self._wifi_enabled
def _linux_has_wireless_interface(self) -> bool:
"""检查是否存在无线网络接口"""
try:
for iface in LinuxNetwork.get_interfaces():
name = iface.get("ifname") or iface.get("name", "")
if name and name.startswith(("wl", "wlan", "wlp")):
return True
# 回退: 检查 /sys/class/net 下的无线接口
import os as _os
for name in _os.listdir("/sys/class/net/") if _os.path.isdir("/sys/class/net") else []:
if name.startswith(("wl", "wlan", "wlp")):
return True
except Exception:
pass
return False
def getWifiState(self) -> int:
return self._wifi_state
def getConfiguredNetworks(self) -> List[WifiConfiguration]:
return list(self._configured_networks)
def addNetwork(self, config: WifiConfiguration) -> int:
config.networkId = self._next_network_id
self._next_network_id += 1
self._configured_networks.append(config)
return config.networkId
def updateNetwork(self, config: WifiConfiguration) -> int:
for i, c in enumerate(self._configured_networks):
if c.networkId == config.networkId:
self._configured_networks[i] = config
return config.networkId
return -1
def removeNetwork(self, net_id: int) -> bool:
self._configured_networks = [
c for c in self._configured_networks if c.networkId != net_id
]
return True
def enableNetwork(self, net_id: int, disable_others: bool = False) -> bool:
for c in self._configured_networks:
if c.networkId == net_id:
c.status = WifiConfiguration.Status.ENABLED
elif disable_others:
c.status = WifiConfiguration.Status.DISABLED
return True
def disableNetwork(self, net_id: int) -> bool:
for c in self._configured_networks:
if c.networkId == net_id:
c.status = WifiConfiguration.Status.DISABLED
return True
def disconnect(self) -> bool:
return True
def reconnect(self) -> bool:
return True
def reassociate(self) -> bool:
return True
def is5GHzBandSupported(self) -> bool:
return True
def is6GHzBandSupported(self) -> bool:
import sys
return sys.version_info >= (3, 10)
def isEasyConnectSupported(self) -> bool:
return False
def getP2pChannelList(self) -> List[int]:
return list(self._p2p_channels)
def startLocalOnlyHotspot(self, callback: WifiManagerLocalOnlyHotspotCallback, handler: Any = None):
try:
callback.onStarted("MockHotspot")
except Exception:
pass
def addNetworkSuggestions(self, suggestions: List[WifiNetworkSuggestion]) -> int:
self._network_suggestions.extend(suggestions)
return 0 # STATUS_SUGGESTION_SUCCESS
def removeNetworkSuggestions(self, suggestions: List[WifiNetworkSuggestion]) -> int:
for s in suggestions:
self._network_suggestions = [x for x in self._network_suggestions if x is not s]
return 0
def createMulticastLock(self, tag: str) -> WifiManagerMulticastLock:
return WifiManagerMulticastLock(tag)
def getDhcpInfo(self):
from .net import DhcpInfo
return DhcpInfo()
def pingSupplicant(self) -> bool:
return True
def startScanActive(self) -> bool:
return True
def setScanAlwaysAvailable(self, enabled: bool):
pass
def isScanAlwaysAvailable(self) -> bool:
return True
def saveConfiguration(self) -> bool:
return True
def toString(self) -> str:
return f"WifiManager(state={self._wifi_state})"
# ═══════════════════════════════════════════════════════════════
# WifiP2pManager
# ═══════════════════════════════════════════════════════════════
class WifiP2pDevice(Stub):
"""WifiP2pDevice — P2P 设备"""
CONNECTED = 0
INVITED = 1
FAILED = 2
AVAILABLE = 3
UNAVAILABLE = 4
def __init__(self):
super().__init__()
self.deviceAddress: str = ""
self.deviceName: str = ""
self.primaryDeviceType: str = ""
self.secondaryDeviceType: str = ""
self.wpsConfigMethods: int = 0
self.deviceCapability: int = 0
self.groupCapability: int = 0
self.status: int = self.UNAVAILABLE
self.GO_PORT: int = 0
def getDeviceAddress(self) -> str:
return self.deviceAddress
def getDeviceName(self) -> str:
return self.deviceName
def isServiceDiscoveryCapable(self) -> bool:
return True
def isGroupOwner(self) -> bool:
return self.groupCapability > 0
def toString(self) -> str:
return f"WifiP2pDevice(name={self.deviceName}, addr={self.deviceAddress})"
class WifiP2pConfig(Stub):
"""WifiP2pConfig — P2P 配置"""
class Builder(Stub):
def __init__(self):
super().__init__()
self._device_address = ""
self._network_name = ""
self._passphrase = ""
self._group_owner_band = 0
def setDeviceAddress(self, addr: str) -> "WifiP2pConfig.Builder":
self._device_address = addr
return self
def setNetworkName(self, name: str) -> "WifiP2pConfig.Builder":
self._network_name = name
return self
def setPassphrase(self, passphrase: str) -> "WifiP2pConfig.Builder":
self._passphrase = passphrase
return self
def setGroupOwnerBand(self, band: int) -> "WifiP2pConfig.Builder":
self._group_owner_band = band
return self
def build(self) -> "WifiP2pConfig":
config = WifiP2pConfig()
config.deviceAddress = self._device_address
config.networkName = self._network_name
config.passphrase = self._passphrase
return config
def __init__(self):
super().__init__()
self.deviceAddress: str = ""
self.networkName: str = ""
self.passphrase: str = ""
class WifiP2pGroup(Stub):
"""WifiP2pGroup — P2P 群组"""
def __init__(self):
super().__init__()
self._network_name: str = ""
self._is_group_owner: bool = False
self._owner: Optional[WifiP2pDevice] = None
self._clients: List[WifiP2pDevice] = []
self._passphrase: str = ""
self._interface: str = ""
def getNetworkName(self) -> str:
return self._network_name
def isGroupOwner(self) -> bool:
return self._is_group_owner
def getOwner(self) -> Optional[WifiP2pDevice]:
return self._owner
def getClientList(self) -> List[WifiP2pDevice]:
return list(self._clients)
def getPassphrase(self) -> str:
return self._passphrase
def getInterface(self) -> str:
return self._interface
def toString(self) -> str:
return f"WifiP2pGroup(name={self._network_name})"
class WifiP2pManager(Stub):
"""WifiP2pManager — P2P 管理器"""
WIFI_P2P_STATE_ENABLED_ACTION = "android.net.wifi.p2p.STATE_CHANGED"
WIFI_P2P_STATE_CHANGED_ACTION = "android.net.wifi.p2p.STATE_CHANGED"
WIFI_P2P_PEERS_CHANGED_ACTION = "android.net.wifi.p2p.PEERS_CHANGED"
WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_CHANGED"
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION = "android.net.wifi.p2p.THIS_DEVICE_CHANGED"
WIFI_P2P_DISCOVERY_CHANGED_ACTION = "android.net.wifi.p2p.DISCOVERY_CHANGED"
class Channel(Stub):
"""P2P 通道"""
def __init__(self):
super().__init__()
def __init__(self):
super().__init__()
self._channel: Optional[WifiP2pManager.Channel] = None
self._peers: List[WifiP2pDevice] = []
def initialize(self, context: Any, looper: Any, listener: Any) -> "WifiP2pManager.Channel":
self._channel = WifiP2pManager.Channel()
if listener:
try:
listener.onSuccess()
except Exception:
pass
return self._channel
def discoverPeers(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def discoverServices(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def requestPeers(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onPeersAvailable(self._peers)
except Exception:
pass
def requestGroupInfo(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onGroupInfoAvailable(WifiP2pGroup())
except Exception:
pass
def createGroup(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def removeGroup(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def connect(self, channel: "WifiP2pManager.Channel", config: WifiP2pConfig, listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def cancelConnect(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def stopPeerDiscovery(self, channel: "WifiP2pManager.Channel", listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def requestDeviceInfo(self, channel: "WifiP2pManager.Channel", device_address: str, listener: Any):
if listener:
try:
listener.onDeviceInfoAvailable(WifiP2pDevice())
except Exception:
pass
def setDeviceName(self, channel: "WifiP2pManager.Channel", device_name: str, listener: Any):
if listener:
try:
listener.onSuccess()
except Exception:
pass
def setWfdEnabled(self, channel: "WifiP2pManager.Channel", enabled: bool, listener: Any):
pass
def toString(self) -> str:
return f"WifiP2pManager(peers={len(self._peers)})"
# ═══════════════════════════════════════════════════════════════
# WifiConfigurationKeyMgmt / WifiConfiguration... aliases
# ═══════════════════════════════════════════════════════════════
WifiConfigurationKeyMgmt = WifiConfiguration.KeyMgmt
WifiConfigurationGroupCipher = WifiConfiguration.GroupCipher
WifiConfigurationPairwiseCipher = WifiConfiguration.PairwiseCipher
WifiConfigurationAuthAlgorithm = WifiConfiguration.AuthAlgorithm
WifiConfigurationProtocol = WifiConfiguration.Protocol
WifiConfigurationStatus = WifiConfiguration.Status
# ═══════════════════════════════════════════════════════════════
# __all__
# ═══════════════════════════════════════════════════════════════
__all__ = [
"WifiManager",
"WifiInfo",
"WifiConfiguration",
"WifiConfigurationKeyMgmt",
"WifiConfigurationGroupCipher",
"WifiConfigurationPairwiseCipher",
"WifiConfigurationAuthAlgorithm",
"WifiConfigurationProtocol",
"WifiConfigurationStatus",
"ScanResult",
"WifiSsid",
"SupplicantState",
"WifiEnterpriseConfig",
"WifiNetworkSpecifier",
"WifiNetworkSuggestion",
"WifiManagerLocalOnlyHotspotCallback",
"WifiManagerWpsCallback",
"WifiManagerMulticastLock",
"WifiP2pManager",
"WifiP2pDevice",
"WifiP2pConfig",
"WifiP2pGroup",
]