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
			// 是否安全,微信的标准是是否需要密码。 来源:https://developers.weixin.qq.com/community/develop/doc/00064cf1790458db19cddf9925ac00?highLine=WifiInfo
			this.secure = false;
			let capabilities = scanResult.capabilities.trim();
打打卡夫卡's avatar
打打卡夫卡 已提交
62
			if ((capabilities.equals(Global.WIFI_AUTH_OPEN) || capabilities.equals(Global.WIFI_AUTH_ROAM))) {
杜庆泉's avatar
杜庆泉 已提交
63
				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
		}
打打卡夫卡's avatar
打打卡夫卡 已提交
79 80 81 82 83
		if (connectInfo.getSSID() != null) {
			let s = connectInfo.getSSID();
			// 微信不带,这里需要去掉引号
			if (s.length > 2 && s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') {
				s = s.substring(1, s.length - 1);
杜庆泉's avatar
杜庆泉 已提交
84
			}
打打卡夫卡's avatar
打打卡夫卡 已提交
85 86
			this.SSID = s;
		}
杜庆泉's avatar
杜庆泉 已提交
87

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

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


杜庆泉's avatar
杜庆泉 已提交
96 97 98 99 100
}

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

杜庆泉's avatar
杜庆泉 已提交
108 109 110 111 112


/**
 * 全局数据储存
 */
杜庆泉's avatar
杜庆泉 已提交
113 114 115 116 117 118 119
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
杜庆泉 已提交
120 121 122 123 124 125
}


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

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

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

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


杜庆泉's avatar
杜庆泉 已提交
138 139 140 141 142 143
		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
杜庆泉 已提交
144 145 146 147
				//做一些异步操作
				setTimeout(function() {
					// BroadcastReceiver 中不能执行耗时任务,需要使用setTimeout
					console.log(Thread.currentThread().getName())
打打卡夫卡's avatar
打打卡夫卡 已提交
148
					// @ts-ignore
杜庆泉's avatar
杜庆泉 已提交
149 150 151
					let winfo = this.mWifiManager!.getConnectionInfo();
					while (winfo.bssid == null) {
						Thread.sleep(1000)
打打卡夫卡's avatar
打打卡夫卡 已提交
152
						winfo = this.mWifiManager!.getConnectionInfo();
杜庆泉's avatar
杜庆泉 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
					}

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

				}, 100);
			}

杜庆泉's avatar
杜庆泉 已提交
170
		}
杜庆泉's avatar
杜庆泉 已提交
171 172


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

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

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

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

杜庆泉's avatar
杜庆泉 已提交
195
			}
杜庆泉's avatar
杜庆泉 已提交
196

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

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

202 203


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

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

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

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


杜庆泉's avatar
杜庆泉 已提交
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
export function connectWifi(_option: WifiConnectOption) {
打打卡夫卡's avatar
打打卡夫卡 已提交
276 277
	// todo
	console.log(_option)
杜庆泉's avatar
杜庆泉 已提交
278 279 280 281 282 283
	if(_option.maunal == true){
		// 指定了手动模式
		let manunalIntent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS);
		getUniActivity()!!.startActivity(manunalIntent);
	}
	
杜庆泉's avatar
杜庆泉 已提交
284 285
}

杜庆泉's avatar
杜庆泉 已提交
286 287 288
/**
 * 开启wifi
 */
杜庆泉's avatar
杜庆泉 已提交
289
export function startWifi(option: WifiOption) {
290
	
打打卡夫卡's avatar
打打卡夫卡 已提交
291 292
	
	
杜庆泉's avatar
杜庆泉 已提交
293 294 295
	// 需要先开启wifi,才能使用后续的功能
	let requestCode = 1001;
	let permissionWifi = arrayOf("android.permission.ACCESS_FINE_LOCATION");
打打卡夫卡's avatar
打打卡夫卡 已提交
296 297 298 299
	var result = {
		errCode: 12001,
		errMsg: "startWifi:premission loss"
	}
杜庆泉's avatar
杜庆泉 已提交
300
	// 检查权限
杜庆泉's avatar
杜庆泉 已提交
301 302
	if (ActivityCompat.checkSelfPermission(getUniActivity()!, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

杜庆泉's avatar
杜庆泉 已提交
303 304 305 306
		ActivityCompat.requestPermissions(getUniActivity()!, permissionWifi, requestCode)
		// 尚不具备权限,返回错误
		option.fail?.(result)
		option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
307

杜庆泉's avatar
杜庆泉 已提交
308
		return;
杜庆泉's avatar
杜庆泉 已提交
309 310
	}

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

杜庆泉's avatar
杜庆泉 已提交
315 316 317
	if (Global.mReceiver == null) {
		Global.mReceiver = new CustomBroadcastReceiver(wifiManager)
	}
杜庆泉's avatar
杜庆泉 已提交
318

杜庆泉's avatar
杜庆泉 已提交
319 320
	let filter = new IntentFilter()
	filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
打打卡夫卡's avatar
打打卡夫卡 已提交
321
	// @ts-ignore
杜庆泉's avatar
杜庆泉 已提交
322
	filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
打打卡夫卡's avatar
打打卡夫卡 已提交
323
	// @ts-ignore
杜庆泉's avatar
杜庆泉 已提交
324
	filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
杜庆泉's avatar
杜庆泉 已提交
325

杜庆泉's avatar
杜庆泉 已提交
326
	getUniActivity()!.registerReceiver(Global.mReceiver, filter)
杜庆泉's avatar
杜庆泉 已提交
327
	wifiManager.startScan()
打打卡夫卡's avatar
打打卡夫卡 已提交
328 329 330
	result.errCode = 0
	result.errMsg = "startWifi:ok"
	
杜庆泉's avatar
杜庆泉 已提交
331 332
	option.success?.(result)
	option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
333

334 335
}

杜庆泉's avatar
杜庆泉 已提交
336 337 338 339

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

		return
杜庆泉's avatar
杜庆泉 已提交
352
	}
杜庆泉's avatar
杜庆泉 已提交
353

杜庆泉's avatar
杜庆泉 已提交
354 355
	getUniActivity()!.unregisterReceiver(Global.mReceiver)
	var result = {
杜庆泉's avatar
杜庆泉 已提交
356 357 358
		errNo: 0,
		errCode: 0,
		errMsg: "stopWifi:ok"
359
	}
杜庆泉's avatar
杜庆泉 已提交
360 361
	option.success?.(result)
	option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
362

杜庆泉's avatar
杜庆泉 已提交
363 364 365 366 367 368
}

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

打打卡夫卡's avatar
打打卡夫卡 已提交
370 371 372 373 374 375 376 377
	let wifiInfo = new UniWifiInfo(null)

	var res = {
		errCode: 12000,
		errMsg: "getConnectedWifi:fail:not invoke startWifi",
		wifi:wifiInfo
	}

378
	if (Global.mReceiver == null) {
打打卡夫卡's avatar
打打卡夫卡 已提交
379 380 381
		// 还没调用startWifi 提示报错
		option.fail?.(res)
		option.complete?.(res)
382 383 384 385
	
		return
	}
	
杜庆泉's avatar
杜庆泉 已提交
386
	if (ActivityCompat.checkSelfPermission(getUniActivity()!, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
杜庆泉's avatar
杜庆泉 已提交
387
		// 尚不具备权限,返回错误
打打卡夫卡's avatar
打打卡夫卡 已提交
388 389 390
		res.errCode = 12001
		res.errMsg = "getConnectedWifi:permission loss"
		
杜庆泉's avatar
杜庆泉 已提交
391 392 393
		option.fail?.(res)
		option.complete?.(res)
		return;
杜庆泉's avatar
杜庆泉 已提交
394 395
	}

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

杜庆泉's avatar
杜庆泉 已提交
409 410
		res.errCode = 0
		res.errMsg = "getConnectedWifi:ok"
打打卡夫卡's avatar
打打卡夫卡 已提交
411
		res.wifi = wifiInfo;
杜庆泉's avatar
杜庆泉 已提交
412 413 414
		option.success?.(res)
		option.complete?.(res)
		return
415
	}
杜庆泉's avatar
杜庆泉 已提交
416 417
	option.fail?.(res)
	option.complete?.(res)
418
}