index.uts 9.7 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 206 207 208
}

/************************* 下面是对外提供的函数 *************************/

/**
 * 获取wifi列表
 */
杜庆泉's avatar
杜庆泉 已提交
209
export function getWifiList(option: WifiOption) {
杜庆泉's avatar
杜庆泉 已提交
210
	let wifiManager: WifiManager =
杜庆泉's avatar
杜庆泉 已提交
211 212 213
		getAppContext()!.getSystemService(Context.WIFI_SERVICE) as WifiManager
	wifiManager.startScan()

杜庆泉's avatar
杜庆泉 已提交
214
	let ret = {
杜庆泉's avatar
杜庆泉 已提交
215 216 217
		errNo: 0,
		errCode: 0,
		errMsg: "getWifiList:ok"
杜庆泉's avatar
杜庆泉 已提交
218 219 220
	}
	option?.success?.(ret)
	option?.complete?.(ret)
杜庆泉's avatar
杜庆泉 已提交
221

杜庆泉's avatar
杜庆泉 已提交
222 223 224
}


杜庆泉's avatar
杜庆泉 已提交
225 226 227
/**
 * wifi 链接成功的回调注册
 */
杜庆泉's avatar
杜庆泉 已提交
228
export function onWifiConnected(callback: UTSCallback) {
杜庆泉's avatar
杜庆泉 已提交
229 230 231 232 233 234
	Global.onWifiConnectCallbackList.push(callback)
}

/**
 * wifi 链接成功的回调取消注册
 */
杜庆泉's avatar
杜庆泉 已提交
235
export function offWifiConnected(callback: UTSCallback) {
杜庆泉's avatar
杜庆泉 已提交
236
	let callbackIndex = Global.onWifiConnectCallbackList.indexOf(callback)
杜庆泉's avatar
杜庆泉 已提交
237 238
	if (callbackIndex > 0) {
		Global.onWifiConnectCallbackList.splice(callbackIndex, 1);
杜庆泉's avatar
杜庆泉 已提交
239 240 241
	}
}

杜庆泉's avatar
杜庆泉 已提交
242 243 244
/**
 * 注册Wifi列表的监听事件
 */
杜庆泉's avatar
杜庆泉 已提交
245 246
export function onGetWifiList(callback: UTSCallback) {

杜庆泉's avatar
杜庆泉 已提交
247 248 249 250 251
	Global.getWifiListCallbackList.push(callback)
}
/**
 * 取消注册Wifi列表的监听事件
 */
杜庆泉's avatar
杜庆泉 已提交
252
export function offGetWifiList(callback: UTSCallback) {
杜庆泉's avatar
杜庆泉 已提交
253
	let callbackIndex = Global.getWifiListCallbackList.indexOf(callback)
杜庆泉's avatar
杜庆泉 已提交
254 255
	if (callbackIndex > 0) {
		Global.getWifiListCallbackList.splice(callbackIndex, 1);
杜庆泉's avatar
杜庆泉 已提交
256 257 258
	}
}

杜庆泉's avatar
杜庆泉 已提交
259 260 261 262
export function connectWifi(option: WifiOption) {
	
}

杜庆泉's avatar
杜庆泉 已提交
263 264 265
/**
 * 开启wifi
 */
杜庆泉's avatar
杜庆泉 已提交
266
export function startWifi(option: WifiOption) {
杜庆泉's avatar
杜庆泉 已提交
267 268 269
	// 需要先开启wifi,才能使用后续的功能
	let requestCode = 1001;
	let permissionWifi = arrayOf("android.permission.ACCESS_FINE_LOCATION");
杜庆泉's avatar
杜庆泉 已提交
270

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

杜庆泉's avatar
杜庆泉 已提交
274 275 276
		ActivityCompat.requestPermissions(getUniActivity()!, permissionWifi, requestCode)
		// 尚不具备权限,返回错误
		var result = {
杜庆泉's avatar
杜庆泉 已提交
277 278 279
			errNo: 0,
			errCode: 0,
			errMsg: "startWifi:premission loss"
杜庆泉's avatar
杜庆泉 已提交
280 281 282
		}
		option.fail?.(result)
		option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
283

杜庆泉's avatar
杜庆泉 已提交
284
		return;
杜庆泉's avatar
杜庆泉 已提交
285 286
	}

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

杜庆泉's avatar
杜庆泉 已提交
291 292 293
	if (Global.mReceiver == null) {
		Global.mReceiver = new CustomBroadcastReceiver(wifiManager)
	}
杜庆泉's avatar
杜庆泉 已提交
294

杜庆泉's avatar
杜庆泉 已提交
295 296 297 298
	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
杜庆泉 已提交
299

杜庆泉's avatar
杜庆泉 已提交
300
	getUniActivity()!.registerReceiver(Global.mReceiver, filter)
杜庆泉's avatar
杜庆泉 已提交
301
	wifiManager.startScan()
杜庆泉's avatar
杜庆泉 已提交
302
	var result = {
杜庆泉's avatar
杜庆泉 已提交
303 304 305
		errNo: 0,
		errCode: 0,
		errMsg: "startWifi:ok"
杜庆泉's avatar
杜庆泉 已提交
306 307 308
	}
	option.success?.(result)
	option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
309

310 311
}

杜庆泉's avatar
杜庆泉 已提交
312 313 314 315

/**
 * 关闭wifi
 */
杜庆泉's avatar
杜庆泉 已提交
316
export function stopWifi(option: WifiOption) {
杜庆泉's avatar
杜庆泉 已提交
317 318 319
	// 需要先开启wifi,才能使用后续的功能
	if (Global.mReceiver == null) {
		var result = {
杜庆泉's avatar
杜庆泉 已提交
320 321 322
			errNo: 12000,
			errCode: 12000,
			errMsg: "stopWifi:not init"
杜庆泉's avatar
杜庆泉 已提交
323 324 325
		}
		option.fail?.(result)
		option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
326 327

		return
杜庆泉's avatar
杜庆泉 已提交
328
	}
杜庆泉's avatar
杜庆泉 已提交
329

杜庆泉's avatar
杜庆泉 已提交
330 331
	getUniActivity()!.unregisterReceiver(Global.mReceiver)
	var result = {
杜庆泉's avatar
杜庆泉 已提交
332 333 334
		errNo: 0,
		errCode: 0,
		errMsg: "stopWifi:ok"
335
	}
杜庆泉's avatar
杜庆泉 已提交
336 337
	option.success?.(result)
	option.complete?.(result)
杜庆泉's avatar
杜庆泉 已提交
338

杜庆泉's avatar
杜庆泉 已提交
339 340 341 342 343 344
}

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

杜庆泉's avatar
杜庆泉 已提交
346
	console.log(option);
杜庆泉's avatar
杜庆泉 已提交
347

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

350
	let res = {
杜庆泉's avatar
杜庆泉 已提交
351 352 353
		errMsg: 'getConnectedWifi:fail. please check permission about location or enable wifi or connect wifi',
		errCode: -1,
		wifi: WifiInfo
354
	}
杜庆泉's avatar
杜庆泉 已提交
355 356 357


	if (ActivityCompat.checkSelfPermission(getUniActivity()!, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
杜庆泉's avatar
杜庆泉 已提交
358 359 360 361
		// 尚不具备权限,返回错误
		option.fail?.(res)
		option.complete?.(res)
		return;
杜庆泉's avatar
杜庆泉 已提交
362 363
	}

364 365 366 367
	// TODO 应该try catch一下,把系统的错误码给返回来,然后和微信的错误码拉齐
	// 需要先校验权限,没有位置权限无法获取wifi
	const context = getAppContext();
	if (context != null) {
杜庆泉's avatar
杜庆泉 已提交
368 369 370
		const wm = context.getSystemService(
			Context.WIFI_SERVICE
		) as WifiManager;
杜庆泉's avatar
杜庆泉 已提交
371
		// 测试android 12上可以使用
杜庆泉's avatar
杜庆泉 已提交
372
		const winfo = wm.getConnectionInfo();
杜庆泉's avatar
杜庆泉 已提交
373 374
		// 封装成数据对象
		WifiInfo.wrapConnectInfo(winfo);
杜庆泉's avatar
杜庆泉 已提交
375

杜庆泉's avatar
杜庆泉 已提交
376 377 378 379 380 381
		res.errCode = 0
		res.errMsg = "getConnectedWifi:ok"
		res.wifi = WifiInfo;
		option.success?.(res)
		option.complete?.(res)
		return
382
	}
杜庆泉's avatar
杜庆泉 已提交
383 384
	option.fail?.(res)
	option.complete?.(res)
385
}