feat 配置WiFi模块

This commit is contained in:
Ironsp
2026-09-14 10:42:40 +08:00
parent 6672fdcac3
commit 5f848e6c78
3 changed files with 224 additions and 65 deletions

View File

@@ -55,6 +55,9 @@
* - android.permission.ACCESS_WIFI_STATE
* - android.permission.CHANGE_WIFI_STATE
* - android.permission.ACCESS_NETWORK_STATE
* - android.permission.ACCESS_FINE_LOCATION
* - android.permission.ACCESS_COARSE_LOCATION
* - Android 6+ 还需运行时授予定位权限,且系统「位置信息」开关需开启
*/
// ======================== 类型定义 ========================
@@ -111,6 +114,90 @@ function importClass(name: string) {
return (plus.android as any).importClass(name)
}
/** 读取 Java 对象字段(ScanResult.SSID 等是字段不是方法) */
function getAttr(obj: any, name: string) {
try {
return (plus.android as any).getAttribute(obj, name)
}
catch {
return invoke(obj, name)
}
}
/** 申请定位权限(Android 扫描 WiFi 必需) */
function requestLocationPermission(): Promise<boolean> {
return new Promise((resolve) => {
try {
;(plus.android as any).requestPermissions(
[
'android.permission.ACCESS_FINE_LOCATION',
'android.permission.ACCESS_COARSE_LOCATION',
],
(result: { granted?: string[], deniedAlways?: string[], deniedPresent?: string[] }) => {
const granted = result?.granted || []
const ok = granted.includes('android.permission.ACCESS_FINE_LOCATION')
|| granted.includes('android.permission.ACCESS_COARSE_LOCATION')
console.log('定位权限申请结果:', result)
resolve(ok)
},
(err: unknown) => {
console.error('定位权限申请失败:', err)
resolve(false)
},
)
}
catch (err) {
console.error('requestPermissions 不可用:', err)
resolve(false)
}
})
}
/** 系统定位开关是否开启 */
function isLocationEnabled(): boolean {
try {
const LocationManager = importClass('android.location.LocationManager')
const Context = importClass('android.content.Context')
const activity = (plus.android as any).runtimeMainActivity()
const lm = activity.getSystemService(Context.LOCATION_SERVICE)
return !!(
invoke(lm, 'isProviderEnabled', LocationManager.GPS_PROVIDER)
|| invoke(lm, 'isProviderEnabled', LocationManager.NETWORK_PROVIDER)
)
}
catch {
return true
}
}
/** 解析 getScanResults 列表 */
function parseScanResults(wm: any): WifiInfo[] {
const results = invoke(wm, 'getScanResults')
if (!results)
return []
const size = invoke(results, 'size') || 0
const networks: WifiInfo[] = []
for (let i = 0; i < size; i++) {
const r = invoke(results, 'get', i)
const ssid = String(getAttr(r, 'SSID') || '').replace(/"/g, '')
if (!ssid || ssid === '<unknown ssid>')
continue
networks.push({
SSID: ssid,
BSSID: String(getAttr(r, 'BSSID') || ''),
signalStrength: Number(getAttr(r, 'level') || 0),
securityType: String(getAttr(r, 'capabilities') || ''),
frequency: Number(getAttr(r, 'frequency') || 0),
connected: false,
})
}
return networks
}
// ======================== WiFi 工具 ========================
const wifi = {
@@ -157,74 +244,89 @@ const wifi = {
},
/** 扫描附近 WiFi 网络 */
scanWifi(): Promise<WifiInfo[]> {
async scanWifi(): Promise<WifiInfo[]> {
const wm = getWifiManager()
const isEnabled = invoke(wm, 'isWifiEnabled')
console.log('WiFi 是否开启:', isEnabled)
if (!isEnabled)
throw new Error('请先开启 WiFi')
const hasPermission = await requestLocationPermission()
if (!hasPermission)
throw new Error('需要定位权限才能扫描 WiFi,请在系统设置中允许')
if (!isLocationEnabled())
throw new Error('请先打开系统「位置信息/定位」开关,否则无法扫描 WiFi')
return new Promise((resolve, reject) => {
try {
const wm = getWifiManager()
let settled = false
let receiver: any = null
let timer: ReturnType<typeof setTimeout> | undefined
const activity = (plus.android as any).runtimeMainActivity()
// 检查 WiFi 是否开启
const isEnabled = invoke(wm, 'isWifiEnabled')
console.log('WiFi 是否开启:', isEnabled)
if (!isEnabled) {
console.warn('WiFi 未开启,返回模拟数据')
// 模拟器或 WiFi 未开启时返回模拟数据
resolve([
{ SSID: 'MOCK_WIFI_1', BSSID: 'AA:BB:CC:DD:EE:01', signalStrength: -45, frequency: 5180, connected: false },
{ SSID: 'MOCK_WIFI_2', BSSID: 'AA:BB:CC:DD:EE:02', signalStrength: -65, frequency: 2437, connected: false },
{ SSID: 'TestNetwork', BSSID: 'AA:BB:CC:DD:EE:03', signalStrength: -72, frequency: 2412, connected: false },
])
const finish = (networks: WifiInfo[], err?: Error) => {
if (settled)
return
settled = true
if (timer)
clearTimeout(timer)
try {
if (receiver)
activity.unregisterReceiver(receiver)
}
catch {}
if (err)
reject(err)
else
resolve(networks)
}
try {
const Filter = importClass('android.content.IntentFilter')
const Receiver = importClass('android.content.BroadcastReceiver')
const filter = new Filter()
filter.addAction('android.net.wifi.SCAN_RESULTS')
receiver = new Receiver({
onReceive(_ctx: any, intent: any) {
const updated = invoke(intent, 'getBooleanExtra', 'resultsUpdated', false)
console.log('收到 SCAN_RESULTS, resultsUpdated:', updated)
const networks = parseScanResults(wm)
console.log('解析后网络数量:', networks.length)
finish(networks)
},
})
activity.registerReceiver(receiver, filter)
// 启动扫描
const started = invoke(wm, 'startScan')
console.log('WiFi 扫描启动:', started)
// 等待 3 秒确保扫描完成
setTimeout(() => {
try {
const results = invoke(wm, 'getScanResults')
if (!results) {
console.log('扫描结果为 null')
resolve([])
return
}
const size = invoke(results, 'size')
console.log('扫描到网络数量:', size)
const networks: WifiInfo[] = []
for (let i = 0; i < size; i++) {
const r = invoke(results, 'get', i)
const ssid = (invoke(r, 'SSID') || '').replace(/"/g, '')
if (!ssid || ssid === '<unknown ssid>')
continue
networks.push({
SSID: ssid,
BSSID: invoke(r, 'BSSID') || '',
signalStrength: invoke(r, 'level') || 0,
securityType: invoke(r, 'capabilities') || '',
frequency: invoke(r, 'frequency') || 0,
connected: false,
})
}
console.log('解析后网络数量:', networks.length)
resolve(networks)
// startScan 失败时仍尝试读取缓存结果(限流时常见)
if (!started) {
const cached = parseScanResults(wm)
console.log('startScan 失败,缓存网络数量:', cached.length)
if (cached.length > 0) {
finish(cached)
return
}
catch (err) {
console.error('获取扫描结果失败:', err)
reject(err)
}
}, 3000)
finish([], new Error('WiFi 扫描被拒绝(可能被系统限流,请稍后再试)'))
return
}
}
catch (err) {
console.error('扫描启动失败:', err)
reject(err)
finish([], err instanceof Error ? err : new Error(String(err)))
return
}
timer = setTimeout(() => {
const networks = parseScanResults(wm)
console.log('扫描超时,当前网络数量:', networks.length)
if (networks.length > 0)
finish(networks)
else
finish([], new Error('扫描超时,未发现可用网络'))
}, 8000)
})
},
@@ -453,7 +555,8 @@ const wifi = {
const receiver = new Receiver({
onReceive() {
wifi.scanWifi().then(callback)
const wm = getWifiManager()
callback(parseScanResults(wm))
},
})