index.uts 10.1 KB
Newer Older
1
import Context from "android.content.Context";
杜庆泉's avatar
杜庆泉 已提交
2
import { getAppContext, getUniActivity } from "io.dcloud.uts.android";
3
import WifiManager from "android.net.wifi.WifiManager";
杜庆泉's avatar
杜庆泉 已提交
4
import WifiInfo from "android.net.wifi.WifiInfo";
杜庆泉's avatar
杜庆泉 已提交
5 6 7 8 9 10 11 12 13
import Manifest from "android.Manifest";
import PackageManager from "android.content.pm.PackageManager";
import ScanResult from "android.net.wifi.ScanResult";
import BroadcastReceiver from "android.content.BroadcastReceiver";
import ActivityCompat from "androidx.core.app.ActivityCompat";
import IntentFilter from "android.content.IntentFilter";
import Gson from "com.google.gson.Gson";
import JSONObject from "com.alibaba.fastjson.JSONObject";
import Intent from "android.content.Intent";
杜庆泉's avatar
杜庆泉 已提交
14
import Thread from "java.lang.Thread";
15

杜庆泉's avatar
杜庆泉 已提交
16 17 18 19 20 21 22 23 24
/**
 * Wifi 函数通用入参封装
 */
type WifiOption = {
	success?: (res: object) => void;
	fail?: (res: object) => void;
	complete?: (res: object) => void;
};

杜庆泉's avatar
杜庆泉 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37
/**
 * Wifi 链接参数封装
 */
type WifiConnectOption = {
	SSID:string;
	BSSID:string;
	password:string;
	maunal:boolean;
	partialInfo:boolean;
	success?: (res: object) => void;
	fail?: (res: object) => void;
	complete?: (res: object) => void;
}
杜庆泉's avatar
杜庆泉 已提交
38 39 40 41 42

/**
 * Wifi信息统一数据结构
 */
class UniWifiInfo {
杜庆泉's avatar
杜庆泉 已提交
43 44 45 46 47 48 49 50 51

	SSID: String = "";
	BSSID: String = "";
	secure: boolean = false;
	signalStrength: Number = 0;
	frequency: Number = 0;

	constructor(scanResult?: ScanResult) {
		if (scanResult != null) {
杜庆泉's avatar
杜庆泉 已提交
52 53 54
			// 如果是通过扫描列表得到的数据,进行封装
			this.BSSID = scanResult.BSSID;
			this.SSID = scanResult.SSID;
杜庆泉's avatar
杜庆泉 已提交
55

杜庆泉's avatar
杜庆泉 已提交
56 57
			this.signalStrength = scanResult.level;
			this.frequency = scanResult.frequency;
杜庆泉's avatar
杜庆泉 已提交
58

杜庆泉's avatar
杜庆泉 已提交
59 60 61 62 63
			// 是否安全,微信的标准是是否需要密码。 来源:https://developers.weixin.qq.com/community/develop/doc/00064cf1790458db19cddf9925ac00?highLine=WifiInfo
			this.secure = false;
			let capabilities = scanResult.capabilities.trim();
			if (capabilities != null && (capabilities.equals(Global.WIFI_AUTH_OPEN) || capabilities.equals(Global.WIFI_AUTH_ROAM))) {
				this.secure = false;
杜庆泉's avatar
杜庆泉 已提交
64
			} else {
杜庆泉's avatar
杜庆泉 已提交
65 66 67 68
				this.secure = true;
			}
		}
	}
杜庆泉's avatar
杜庆泉 已提交
69

杜庆泉's avatar
杜庆泉 已提交
70 71 72
	/**
	 * 根据connectInfo 链接信息对wifi数据结构进行初始化
	 */
杜庆泉's avatar
杜庆泉 已提交
73
	wrapConnectInfo(connectInfo: WifiInfo): void {
杜庆泉's avatar
杜庆泉 已提交
74 75
		console.log(connectInfo.getSSID());
		console.log(connectInfo.getBSSID());
杜庆泉's avatar
杜庆泉 已提交
76 77
		if (connectInfo.getBSSID() == null) {
			return
杜庆泉's avatar
杜庆泉 已提交
78 79
		}
		if (connectInfo != null) {
杜庆泉's avatar
杜庆泉 已提交
80
			if (connectInfo.getSSID() != null) {
杜庆泉's avatar
杜庆泉 已提交
81 82 83 84 85 86 87
				let s = connectInfo.getSSID();
				// 微信不带,这里需要去掉引号
				if (s.length > 2 && s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') {
					s = s.substring(1, s.length - 1);
				}
				this.SSID = s;
			}
杜庆泉's avatar
杜庆泉 已提交
88

杜庆泉's avatar
杜庆泉 已提交
89
			this.BSSID = connectInfo.getBSSID();
杜庆泉's avatar
杜庆泉 已提交
90 91
			//Android返回的值是-100~0,而微信API规范是0~100,值越大信号越好,需要+100拉齐
			this.signalStrength = connectInfo.getRssi() + 100; 
杜庆泉's avatar
杜庆泉 已提交
92
			this.frequency = connectInfo.getFrequency();
杜庆泉's avatar
杜庆泉 已提交
93

杜庆泉's avatar
杜庆泉 已提交
94 95
		}
	}
杜庆泉's avatar
杜庆泉 已提交
96 97


杜庆泉's avatar
杜庆泉 已提交
98 99 100 101 102
}

/**
 * 获取当前链接的wifi信息
 */
103
type GetConnectedWifiOptions = {
杜庆泉's avatar
杜庆泉 已提交
104 105 106 107
	partialInfo?: boolean
	success?: (res: UTSJSONObject) => void
	fail?: (res: UTSJSONObject) => void
	complete?: (res: UTSJSONObject) => void
108 109
}

杜庆泉's avatar
杜庆泉 已提交
110 111 112 113 114


/**
 * 全局数据储存
 */
杜庆泉's avatar
杜庆泉 已提交
115 116 117 118 119 120 121
class Global {
	static mReceiver?: CustomBroadcastReceiver = null;
	static scanList: UniWifiInfo[] = []
	static WIFI_AUTH_OPEN: String = "";
	static WIFI_AUTH_ROAM: String = "[ESS]";
	static getWifiListCallbackList: UTSCallback[] = []
	static onWifiConnectCallbackList: UTSCallback[] = []
杜庆泉's avatar
杜庆泉 已提交
122 123 124 125 126 127
}


/**
 * 自定义wifi变化广播监听器
 */
杜庆泉's avatar
杜庆泉 已提交
128
class CustomBroadcastReceiver extends BroadcastReceiver {
杜庆泉's avatar
杜庆泉 已提交
129

杜庆泉's avatar
杜庆泉 已提交
130 131 132
	mWifiManager?: WifiManager = null;

	constructor(wifiManager: WifiManager) {
杜庆泉's avatar
杜庆泉 已提交
133 134 135
		super();
		this.mWifiManager = wifiManager;
	}
杜庆泉's avatar
杜庆泉 已提交
136 137 138 139

	override onReceive(_context: Context, intent: Intent): void {


杜庆泉's avatar
杜庆泉 已提交
140 141 142 143 144 145
		if (intent.action == WifiManager.WIFI_STATE_CHANGED_ACTION) {
			let state =
				intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)
			if (state == WifiManager.WIFI_STATE_ENABLED) {
				// 获取当前的connectInfo 并且进行数据封装
				let uniWifiInfo = new UniWifiInfo(null)
杜庆泉's avatar
杜庆泉 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
				//做一些异步操作
				setTimeout(function() {
					// BroadcastReceiver 中不能执行耗时任务,需要使用setTimeout
					console.log(Thread.currentThread().getName())
					let winfo = this.mWifiManager!.getConnectionInfo();
					while (winfo.bssid == null) {
						Thread.sleep(1000)
						winfo = this.mWifiManager!!.getConnectionInfo();
					}

					// 封装成数据对象
					uniWifiInfo.wrapConnectInfo(winfo)
					let res = {
						errMsg: 'onWifiConnected:ok',
						errCode: 0,
						wifi: uniWifiInfo
					}
					console.log("Global.onWifiConnectCallbackList  == " + Global.onWifiConnectCallbackList.length);
					// wifi状态可用了,分发当前的链接状态给已注册的监听集合
					for (let perCallback in Global.onWifiConnectCallbackList) {
						perCallback(res);
					}

				}, 100);
			}

杜庆泉's avatar
杜庆泉 已提交
172
		}
杜庆泉's avatar
杜庆泉 已提交
173 174


杜庆泉's avatar
杜庆泉 已提交
175
		if (intent.action == WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) {
杜庆泉's avatar
杜庆泉 已提交
176 177
			// wifi 扫描结果回调
			let results = this.mWifiManager!.scanResults;
杜庆泉's avatar
杜庆泉 已提交
178

杜庆泉's avatar
杜庆泉 已提交
179 180
			if (results != null) {
				Global.scanList = []
杜庆泉's avatar
杜庆泉 已提交
181 182 183
				for (let scanResult in results) {
					if (scanResult.SSID == null) {
						continue;
杜庆泉's avatar
杜庆泉 已提交
184
					}
杜庆泉's avatar
杜庆泉 已提交
185
					Global.scanList.push(new UniWifiInfo(scanResult));
杜庆泉's avatar
杜庆泉 已提交
186
				}
杜庆泉's avatar
杜庆泉 已提交
187

杜庆泉's avatar
杜庆泉 已提交
188
				// 挨个通知,所有的监听器
杜庆泉's avatar
杜庆泉 已提交
189 190
				for (let perCallback in Global.getWifiListCallbackList) {

杜庆泉's avatar
杜庆泉 已提交
191 192 193 194 195
					const data = new JSONObject();
					let mainJsonStr = Gson().toJson(Global.scanList);
					data["wifiList"] = mainJsonStr
					perCallback(data);
				}
杜庆泉's avatar
杜庆泉 已提交
196

杜庆泉's avatar
杜庆泉 已提交
197
			}
杜庆泉's avatar
杜庆泉 已提交
198

杜庆泉's avatar
杜庆泉 已提交
199 200
		}
	}
杜庆泉's avatar
杜庆泉 已提交
201

杜庆泉's avatar
杜庆泉 已提交
202 203
}

204 205


杜庆泉's avatar
杜庆泉 已提交
206 207 208 209 210
/************************* 下面是对外提供的函数 *************************/

/**
 * 获取wifi列表
 */
杜庆泉's avatar
杜庆泉 已提交
211
export function getWifiList(option: WifiOption) {
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
	
	
	
	if (Global.mReceiver == null) {
		// 还没调用startWifi 提示报错
		var result = {
			errCode: 12000,
			errMsg: "getWifiList:fail fail:not init,you shall call startWifi first"
		}
		option.fail?.(result)
		option.complete?.(result)
	
		return
	}
	
杜庆泉's avatar
杜庆泉 已提交
227
	let wifiManager: WifiManager =
杜庆泉's avatar
杜庆泉 已提交
228 229 230
		getAppContext()!.getSystemService(Context.WIFI_SERVICE) as WifiManager
	wifiManager.startScan()

杜庆泉's avatar
杜庆泉 已提交
231
	let ret = {
杜庆泉's avatar
杜庆泉 已提交
232 233
		errCode: 0,
		errMsg: "getWifiList:ok"
杜庆泉's avatar
杜庆泉 已提交
234 235 236
	}
	option?.success?.(ret)
	option?.complete?.(ret)
杜庆泉's avatar
杜庆泉 已提交
237

杜庆泉's avatar
杜庆泉 已提交
238 239 240
}


杜庆泉's avatar
杜庆泉 已提交
241 242 243
/**
 * wifi 链接成功的回调注册
 */
杜庆泉's avatar
杜庆泉 已提交
244
export function onWifiConnected(callback: UTSCallback) {
杜庆泉's avatar
杜庆泉 已提交
245 246 247 248 249 250
	Global.onWifiConnectCallbackList.push(callback)
}

/**
 * wifi 链接成功的回调取消注册
 */
杜庆泉's avatar
杜庆泉 已提交
251
export function offWifiConnected(callback: UTSCallback) {
杜庆泉's avatar
杜庆泉 已提交
252
	let callbackIndex = Global.onWifiConnectCallbackList.indexOf(callback)
杜庆泉's avatar
杜庆泉 已提交
253 254
	if (callbackIndex > 0) {
		Global.onWifiConnectCallbackList.splice(callbackIndex, 1);
杜庆泉's avatar
杜庆泉 已提交
255 256 257
	}
}

杜庆泉's avatar
杜庆泉 已提交
258 259 260
/**
 * 注册Wifi列表的监听事件
 */
杜庆泉's avatar
杜庆泉 已提交
261 262
export function onGetWifiList(callback: UTSCallback) {

杜庆泉's avatar
杜庆泉 已提交
263 264 265 266 267
	Global.getWifiListCallbackList.push(callback)
}
/**
 * 取消注册Wifi列表的监听事件
 */
杜庆泉's avatar
杜庆泉 已提交
268
export function offGetWifiList(callback: UTSCallback) {
杜庆泉's avatar
杜庆泉 已提交
269
	let callbackIndex = Global.getWifiListCallbackList.indexOf(callback)
杜庆泉's avatar
杜庆泉 已提交
270 271
	if (callbackIndex > 0) {
		Global.getWifiListCallbackList.splice(callbackIndex, 1);
杜庆泉's avatar
杜庆泉 已提交
272 273 274
	}
}

杜庆泉's avatar
杜庆泉 已提交
275 276 277 278
export function connectWifi(option: WifiOption) {
	
}

杜庆泉's avatar
杜庆泉 已提交
279 280 281
/**
 * 开启wifi
 */
杜庆泉's avatar
杜庆泉 已提交
282
export function startWifi(option: WifiOption) {
283
	
杜庆泉's avatar
杜庆泉 已提交
284 285 286
	// 需要先开启wifi,才能使用后续的功能
	let requestCode = 1001;
	let permissionWifi = arrayOf("android.permission.ACCESS_FINE_LOCATION");
杜庆泉's avatar
杜庆泉 已提交
287

杜庆泉's avatar
杜庆泉 已提交
288
	// 检查权限
杜庆泉's avatar
杜庆泉 已提交
289 290
	if (ActivityCompat.checkSelfPermission(getUniActivity()!, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

杜庆泉's avatar
杜庆泉 已提交
291 292 293
		ActivityCompat.requestPermissions(getUniActivity()!, permissionWifi, requestCode)
		// 尚不具备权限,返回错误
		var result = {
杜庆泉's avatar
杜庆泉 已提交
294 295 296
			errNo: 0,
			errCode: 0,
			errMsg: "startWifi:premission loss"
杜庆泉's avatar
杜庆泉 已提交
297 298 299
		}
		option.fail?.(result)
		option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
300

杜庆泉's avatar
杜庆泉 已提交
301
		return;
杜庆泉's avatar
杜庆泉 已提交
302 303
	}

杜庆泉's avatar
杜庆泉 已提交
304 305
	// 具备了权限,继续前进
	let wifiManager: WifiManager =
杜庆泉's avatar
杜庆泉 已提交
306 307
		getAppContext()!.getSystemService(Context.WIFI_SERVICE) as WifiManager

杜庆泉's avatar
杜庆泉 已提交
308 309 310
	if (Global.mReceiver == null) {
		Global.mReceiver = new CustomBroadcastReceiver(wifiManager)
	}
杜庆泉's avatar
杜庆泉 已提交
311

杜庆泉's avatar
杜庆泉 已提交
312 313 314 315
	let filter = new IntentFilter()
	filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
	filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
	filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
杜庆泉's avatar
杜庆泉 已提交
316

杜庆泉's avatar
杜庆泉 已提交
317
	getUniActivity()!.registerReceiver(Global.mReceiver, filter)
杜庆泉's avatar
杜庆泉 已提交
318
	wifiManager.startScan()
杜庆泉's avatar
杜庆泉 已提交
319
	var result = {
杜庆泉's avatar
杜庆泉 已提交
320 321 322
		errNo: 0,
		errCode: 0,
		errMsg: "startWifi:ok"
杜庆泉's avatar
杜庆泉 已提交
323 324 325
	}
	option.success?.(result)
	option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
326

327 328
}

杜庆泉's avatar
杜庆泉 已提交
329 330 331 332

/**
 * 关闭wifi
 */
杜庆泉's avatar
杜庆泉 已提交
333
export function stopWifi(option: WifiOption) {
杜庆泉's avatar
杜庆泉 已提交
334 335 336
	// 需要先开启wifi,才能使用后续的功能
	if (Global.mReceiver == null) {
		var result = {
杜庆泉's avatar
杜庆泉 已提交
337 338 339
			errNo: 12000,
			errCode: 12000,
			errMsg: "stopWifi:not init"
杜庆泉's avatar
杜庆泉 已提交
340 341 342
		}
		option.fail?.(result)
		option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
343 344

		return
杜庆泉's avatar
杜庆泉 已提交
345
	}
杜庆泉's avatar
杜庆泉 已提交
346

杜庆泉's avatar
杜庆泉 已提交
347 348
	getUniActivity()!.unregisterReceiver(Global.mReceiver)
	var result = {
杜庆泉's avatar
杜庆泉 已提交
349 350 351
		errNo: 0,
		errCode: 0,
		errMsg: "stopWifi:ok"
352
	}
杜庆泉's avatar
杜庆泉 已提交
353 354
	option.success?.(result)
	option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
355

杜庆泉's avatar
杜庆泉 已提交
356 357 358 359 360 361
}

/**
 * 获取当前连接中的wifi信息
 */
export function getConnectedWifi(option: GetConnectedWifiOptions) {
杜庆泉's avatar
杜庆泉 已提交
362

363 364 365 366 367 368 369 370 371 372 373 374
	if (Global.mReceiver == null) {
		var result = {
			errNo: 12000,
			errCode: 12000,
			errMsg: "startWifi:not init"
		}
		option.fail?.(result)
		option.complete?.(result)
	
		return
	}
	
杜庆泉's avatar
杜庆泉 已提交
375

杜庆泉's avatar
杜庆泉 已提交
376
	let WifiInfo = new UniWifiInfo(null)
杜庆泉's avatar
杜庆泉 已提交
377

378
	let res = {
杜庆泉's avatar
杜庆泉 已提交
379 380 381
		errMsg: 'getConnectedWifi:fail. please check permission about location or enable wifi or connect wifi',
		errCode: -1,
		wifi: WifiInfo
382
	}
杜庆泉's avatar
杜庆泉 已提交
383 384 385


	if (ActivityCompat.checkSelfPermission(getUniActivity()!, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
杜庆泉's avatar
杜庆泉 已提交
386 387 388 389
		// 尚不具备权限,返回错误
		option.fail?.(res)
		option.complete?.(res)
		return;
杜庆泉's avatar
杜庆泉 已提交
390 391
	}

392 393 394 395
	// TODO 应该try catch一下,把系统的错误码给返回来,然后和微信的错误码拉齐
	// 需要先校验权限,没有位置权限无法获取wifi
	const context = getAppContext();
	if (context != null) {
杜庆泉's avatar
杜庆泉 已提交
396 397 398
		const wm = context.getSystemService(
			Context.WIFI_SERVICE
		) as WifiManager;
杜庆泉's avatar
杜庆泉 已提交
399
		// 测试android 12上可以使用
杜庆泉's avatar
杜庆泉 已提交
400
		const winfo = wm.getConnectionInfo();
杜庆泉's avatar
杜庆泉 已提交
401 402
		// 封装成数据对象
		WifiInfo.wrapConnectInfo(winfo);
杜庆泉's avatar
杜庆泉 已提交
403

杜庆泉's avatar
杜庆泉 已提交
404 405 406 407 408 409
		res.errCode = 0
		res.errMsg = "getConnectedWifi:ok"
		res.wifi = WifiInfo;
		option.success?.(res)
		option.complete?.(res)
		return
410
	}
杜庆泉's avatar
杜庆泉 已提交
411 412
	option.fail?.(res)
	option.complete?.(res)
413
}