前言
在ReactNative
中无法直接实时监听WIFI
的状态,但得益于RN
可以直接和原生层进行通信的特点,可以在原生层注册广播,实时监听WIFI
变化并通过Bridge
向RN
发送状态事件,RN
层实时监听事件,获取WIFI
状态。
原生层订阅广播
首先在android/app/src/main/AndroidManifest.xml
中添加网络状态权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
打开android
目录下的应用主文件:android/app/src/main/java/com/<工程名>/MainApplication.java
,找到onCreate
方法,在方法内订阅广播,如下:
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
// 添加以下广播订阅代码,监听广播实时传递wifi状态
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
ReactContext reactContext = getReactNativeHost().getReactInstanceManager().getCurrentReactContext();
if (reactContext == null) {
return;
}
// 事件名称,RN层通过订阅该名称的事件实时接收wifi状态
String eventName = "wifi-status";
// wifi是否连接
if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (info != null && info.getState().equals(NetworkInfo.State.DISCONNECTED)) {
// 断开连接
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, "201");
} else if (info != null && info.getState().equals(NetworkInfo.State.CONNECTED)) {
// 建立连接
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, "200");
}
}
// wifi是否打开
if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
if (wifistate == WifiManager.WIFI_STATE_DISABLED) {
// 关闭wifi
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, "204");
} else if (wifistate == WifiManager.WIFI_STATE_ENABLED) {
// 打开wifi
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, "203");
}
}
}
};
// 注册广播
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(receiver, filter);
}
RN
前端监听wifi
状态事件并获取所连wifi
的SSID
首先安装react-native-wifi-reborn
用于获取wifi
信息:
yarn add react-native-wifi-reborn
需要注意的时,在Android10
以上系统,需要获取位置权限才能扫描wifi
并获取wifi
信息,因此,将请求权限与获取当前所连wifi
的SSID
封装为一个工具类,如下:
import {PermissionsAndroid} from 'react-native';
import WifiManager from 'react-native-wifi-reborn';
export default class WifiUtil {
// 请求位置权限
static async grantPermission() {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: '请求位置权限',
message: '需要位置权限以扫描附近的WIFI网络', // 指定message,若第一次用户拒绝了,可以弹出一个说明框再次进行请求
buttonPositive: '确定',
// buttonNegative: '取消',
},
);
return granted === PermissionsAndroid.RESULTS.GRANTED;
}
// 获取当前所连wifi的SSID
static async getCurrentWifiSSID() {
const ssid = await WifiManager.getCurrentWifiSSID().then(
id => id,
() => null,
);
return ssid;
}
}
在需要监听wifi
状态的控件中即可请求权限并监听广播传来的事件,如下:
import React, {useEffect} from 'react';
import {View, Text} from 'react-native';
import WifiUtil from '../util/WifiUtil';
export default function App() {
useEffect(() => {
// 获取位置权限
WifiUtil.grantPermission().then(wifiGranted => {
if (!wifiGranted) {
console.log('网络位置权限请求失败,可能无法扫描WIFI信息并自动获取当前WIFI的SSID');
}
// 获取ssid
WifiUtil.getCurrentWifiSSID().then(ssid => {
if (ssid) {
console.log(`ssid = ${ssid}`);
} else {
console.log('未获取到SSID');
}
});
});
}, []);
useEffect(() => {
// 监听wifi状态事件
const messageEmitter = DeviceEventEmitter.addListener('wifi-status', (code: string) => {
switch (code) {
case “200”:
console.log('wifi连接已建立 ...');
WifiUtil.getCurrentWifiSSID().then(ssid => {
if (ssid) {
console.log(`ssid = ${ssid}`);
} else {
console.log('未获取到SSID');
}
});
break;
case “201”:
console.log('wifi连接已断开 ...');
break;
case “203”:
console.log('wifi已打开 ...');
break;
case “204”:
console.log('wifi已关闭 ...');
break;
default:
console.log('未知状态 ...');
}
});
return () => {
messageEmitter.remove(); // 销毁事件
};
}, []);
return (
<View>
<Text>App</Text>
</View>
);
}