我正在开发 React Native 应用程序,该应用程序具有扫描所有可用 wifi、使用正确密码连接 wifi 的功能,并使用它来通过云技术控制设备。 我已成功从应用程序完成 WiFi 连接,但我无法从中使用互联网。 我已经安装了 wifi reborn 库和 wifi 管理器以及更多来执行此操作,但没有一个工作。
`import React, {useState, useEffect} from 'react';
import {
View,
Text,
FlatList,
TouchableOpacity,
TextInput,
PermissionsAndroid,
Platform,
Modal,
ToastAndroid,
Image,
StyleSheet,
} from 'react-native';
import WifiManager from 'react-native-wifi-reborn';
import {check, request, PERMISSIONS, RESULTS} from 'react-native-permissions';
// import OpenSettings from 'react-native-open-settings';
const WifiScannerScreen = () => {
const [wifiList, setWifiList] = useState([]);
const [password, setPassword] = useState('');
const [connectingSSID, setConnectingSSID] = useState('');
const [selectedSSID, setSelectedSSID] = useState('');
const [isPasswordModalVisible, setPasswordModalVisible] = useState(false);
const checkWifiPermissions = async () => {
try {
if (Platform.OS === 'android') {
const wifiPermissionResult = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
if (wifiPermissionResult === PermissionsAndroid.RESULTS.GRANTED) {
scanWifi();
} else {
console.error('Wi-Fi permissions denied.');
}
} else {
const wifiPermissionResult = await check(
PERMISSIONS.IOS.LOCATION_WHEN_IN_USE,
);
if (wifiPermissionResult === RESULTS.GRANTED) {
scanWifi();
} else {
const permissionRequestResult = await request(
PERMISSIONS.IOS.LOCATION_WHEN_IN_USE,
);
if (permissionRequestResult === RESULTS.GRANTED) {
scanWifi();
} else {
console.error('Wi-Fi permissions denied.');
}
}
}
} catch (error) {
console.error('Error checking Wi-Fi permissions:', error);
}
};
const scanWifi = async () => {
try {
const wifiArray = await WifiManager.loadWifiList();
setWifiList(wifiArray);
} catch (error) {
console.error('Error scanning for Wi-Fi:', error);
}
};
const connectToWifi = async (ssid, password) => {
try {
if (!validatePassword(password)) {
console.error('Invalid password');
return;
}
setConnectingSSID(ssid);
await WifiManager.connectToProtectedSSID(ssid, password, false, true);
console.log('Connected to Wi-Fi:', ssid);
setTimeout(() => {
checkInternetConnectivity(ssid);
}, 5000);
} catch (error) {
console.error('Error connecting to Wi-Fi:', error);
} finally {
setConnectingSSID('');
setSelectedSSID('');
setPasswordModalVisible(false);
}
};
const checkInternetConnectivity = async ssid => {
try {
const response = await fetch('https://www.google.com', {method: 'HEAD'});
if (response.ok) {
console.log('Connected to the internet');
showToast('Wi-Fi connected!');
} else {
console.error('No internet connection');
}
} catch (error) {
console.error('Error checking internet connectivity:', error);
}
};
const showToast = message => {
ToastAndroid.show(message, ToastAndroid.SHORT);
};
const validatePassword = password => {
return true;
};
useEffect(() => {
checkWifiPermissions();
// OpenSettings.openSettings();
}, []);
const showPasswordInputModal = ssid => {
setSelectedSSID(ssid);
setPasswordModalVisible(true);
};
const hidePasswordInputModal = () => {
setSelectedSSID('');
setPassword('');
setPasswordModalVisible(false);
};
const getSignalStrengthCategory = level => {
if (level >= -50) {
return 'full';
} else if (level >= -70) {
return 'medium';
} else {
return 'poor';
}
};
const getImageSource = category => {
switch (category) {
case 'full':
return require('./src/assets/wifi-high-icon-original.png');
case 'medium':
return require('./src/assets/wifi-medium-icon-original.png');
case 'poor':
return require('./src/assets/wifi-low-icon-original.png');
default:
return require('./src/assets/wifi-none-icon-original.png');
}
};
const renderItem = ({item}) => (
<TouchableOpacity
onPress={() => showPasswordInputModal(item.SSID)}
style={{
padding: 10,
borderBottomWidth: 1,
borderBottomColor: '#ccc',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}>
<View>
<Text style={styles.wifiNames}>{`${item.SSID}`}</Text>
{/* <Text>{`BSSID: ${item.BSSID}`}</Text> */}
<Text>{`Signal Strength: ${item.level} dBm`}</Text>
</View>
<Image
source={getImageSource(getSignalStrengthCategory(item.level))}
style={{width: 30, height: 30}}
/>
</TouchableOpacity>
);
return (
<View style={{flex: 1, padding: 20}}>
<Text style={styles.headerText}>Available Networks</Text>
<FlatList
data={wifiList}
keyExtractor={item => item.BSSID}
renderItem={renderItem}
ListEmptyComponent={<Text>No Wi-Fi networks found</Text>}
/>
<Modal
animationType="slide"
transparent={false}
visible={isPasswordModalVisible}
onRequestClose={hidePasswordInputModal}>
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<View style={styles.modalContent}>
<Text
style={
styles.modalHeader
}>{`Enter the password for ${selectedSSID}`}</Text>
<TextInput
style={styles.passwordTextInput}
placeholder="Wi-Fi Password"
secureTextEntry
value={password}
onChangeText={text => setPassword(text)}
/>
<View style={styles.okCancelContainer}>
<TouchableOpacity
style={styles.okButton}
onPress={() => connectToWifi(selectedSSID, password)}>
<Text style={styles.buttonText}>OK</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.cancelButton}
onPress={hidePasswordInputModal}>
<Text style={styles.buttonText}>Cancel</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
</View>
);
};
const styles = StyleSheet.create({
headerText: {
fontSize: 24,
color: 'black',
textAlign: 'center',
marginBottom: 12,
},
wifiNames: {
color: 'gray',
fontSize: 20,
},
modalContent: {
backgroundColor: 'white',
padding: 20,
borderRadius: 10,
elevation: 5,
justifyContent: 'center',
alignItems: 'center',
flexWrap: 'wrap',
},
modalHeader: {
color: 'red',
marginBottom: 12,
},
passwordTextInput: {
height: 50,
borderColor: 'black',
borderWidth: 1,
marginBottom: 10,
borderRadius: 12,
},
okCancelContainer: {
flexDirection: 'row',
justifyContent: 'space-evenly',
width: '80%',
},
okButton: {
borderWidth: 2,
borderColor: 'black',
paddingHorizontal: 40,
paddingVertical: 10,
borderRadius: 18,
marginVertical: 5,
},
cancelButton: {
borderWidth: 2,
borderColor: 'black',
paddingHorizontal: 40,
paddingVertical: 10,
borderRadius: 18,
marginVertical: 5,
},
buttonText: {
color: 'black',
textAlign: 'center',
},
});
export default WifiScannerScreen;
`
这是组件的代码。
我尝试了 wifi reborn、wifi manager、tethring 和更多库来做到这一点。 我希望用户应该能够使用互联网。
如何修复
ACCESS_FINE_LOCATION
。
- 对于 iOS,请请求 LOCATION_WHEN_IN_USE
。import React, { useState, useEffect } from "react";
import {
View,
Text,
FlatList,
TouchableOpacity,
TextInput,
PermissionsAndroid,
Platform,
Modal,
ToastAndroid,
Image,
StyleSheet,
} from "react-native";
import WifiManager from "react-native-wifi-reborn";
import { check, request, PERMISSIONS, RESULTS } from "react-native-permissions";
const WifiScannerScreen = () => {
const [wifiList, setWifiList] = useState([]);
const [password, setPassword] = useState("");
const [connectingSSID, setConnectingSSID] = useState("");
const [selectedSSID, setSelectedSSID] = useState("");
const [isPasswordModalVisible, setPasswordModalVisible] = useState(false);
const checkWifiPermissions = async () => {
try {
if (Platform.OS === "android") {
const wifiPermission = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
);
if (wifiPermission === PermissionsAndroid.RESULTS.GRANTED) {
scanWifi();
} else {
console.error("Wi-Fi permissions denied.");
}
} else {
const wifiPermission = await check(
PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
);
if (wifiPermission === RESULTS.GRANTED) {
scanWifi();
} else {
const permissionRequestResult = await request(
PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
);
if (permissionRequestResult === RESULTS.GRANTED) {
scanWifi();
} else {
console.error("Wi-Fi permissions denied.");
}
}
}
} catch (error) {
console.error("Error checking Wi-Fi permissions:", error);
}
};
const scanWifi = async () => {
try {
const wifiArray = await WifiManager.loadWifiList();
setWifiList(wifiArray);
} catch (error) {
console.error("Error scanning for Wi-Fi:", error);
}
};
const connectToWifi = async (ssid, password) => {
try {
if (!validatePassword(password)) {
console.error("Invalid password");
return;
}
setConnectingSSID(ssid);
await WifiManager.connectToProtectedSSID(ssid, password, false, true);
console.log(`Connected to Wi-Fi: ${ssid}`);
if (Platform.OS === "android" && Platform.Version >= 29) {
await WifiManager.forceWifiUsage(true);
}
setTimeout(() => {
checkInternetConnectivity(ssid);
}, 5000);
} catch (error) {
console.error("Error connecting to Wi-Fi:", error);
} finally {
resetModalState();
}
};
const checkInternetConnectivity = async (ssid) => {
try {
const response = await fetch("https://www.google.com", {
method: "HEAD",
});
if (response.ok) {
showToast("Wi-Fi connected with internet!");
} else {
console.error("No internet connection");
}
} catch (error) {
console.error("Error checking internet connectivity:", error);
}
};
const validatePassword = (password) => password.length > 0;
const showToast = (message) => {
ToastAndroid.show(message, ToastAndroid.SHORT);
};
const resetModalState = () => {
setConnectingSSID("");
setSelectedSSID("");
setPasswordModalVisible(false);
};
useEffect(() => {
checkWifiPermissions();
}, []);
const renderItem = ({ item }) => (
<TouchableOpacity
onPress={() => {
setSelectedSSID(item.SSID);
setPasswordModalVisible(true);
}}
style={styles.listItem}
>
<Text style={styles.ssidText}>{item.SSID}</Text>
<Image source={getSignalIcon(item.level)} style={styles.signalIcon} />
</TouchableOpacity>
);
const getSignalIcon = (level) => {
if (level >= -50) return require("./assets/wifi-full.png");
if (level >= -70) return require("./assets/wifi-medium.png");
return require("./assets/wifi-low.png");
};
return (
<View style={styles.container}>
<Text style={styles.header}>Available Wi-Fi Networks</Text>
<FlatList
data={wifiList}
keyExtractor={(item) => item.BSSID}
renderItem={renderItem}
ListEmptyComponent={<Text>No Wi-Fi networks found</Text>}
/>
<Modal
animationType="slide"
transparent={false}
visible={isPasswordModalVisible}
onRequestClose={resetModalState}
>
<View style={styles.modalContainer}>
<Text style={styles.modalTitle}>
Enter password for {selectedSSID}
</Text>
<TextInput
style={styles.passwordInput}
placeholder="Wi-Fi Password"
secureTextEntry
value={password}
onChangeText={setPassword}
/>
<View style={styles.modalButtons}>
<TouchableOpacity
style={styles.okButton}
onPress={() => connectToWifi(selectedSSID, password)}
>
<Text style={styles.buttonText}>OK</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.cancelButton}
onPress={resetModalState}
>
<Text style={styles.buttonText}>Cancel</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
);
};
const styles = StyleSheet.create({
container: { flex: 1, padding: 20 },
header: { fontSize: 24, textAlign: "center", marginVertical: 10 },
listItem: {
padding: 10,
borderBottomWidth: 1,
borderBottomColor: "#ccc",
flexDirection: "row",
justifyContent: "space-between",
},
ssidText: { fontSize: 18, color: "gray" },
signalIcon: { width: 30, height: 30 },
modalContainer: { flex: 1, justifyContent: "center", padding: 20 },
modalTitle: { fontSize: 18, marginBottom: 10, textAlign: "center" },
passwordInput: {
borderWidth: 1,
borderColor: "black",
padding: 10,
borderRadius: 5,
},
modalButtons: {
flexDirection: "row",
justifyContent: "space-around",
marginTop: 20,
},
okButton: { padding: 10, borderRadius: 5, backgroundColor: "#4CAF50" },
cancelButton: { padding: 10, borderRadius: 5, backgroundColor: "#f44336" },
buttonText: { color: "white", textAlign: "center" },
});
export default WifiScannerScreen;
Android
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
iOS
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need access to your location to scan Wi-Fi networks.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>We need access to your location to scan Wi-Fi networks.</string>