如何在React Native应用程序中检查iOS和Android的网络连接?

66

我有一个React Native应用程序,希望添加一个功能,在应用程序启动时以及之后持续检查是否存在活动的互联网连接。

如果没有互联网连接,我希望显示一条消息,上面写着“未检测到互联网连接”,并提供一个“重试”按钮;如果有互联网连接,我希望加载一个页面(WebView)。

我还希望支持iOS和Android设备;我已经独立进行了研究,并在GitHub上找到了几个库。然而,许多库需要在Android清单XML中包含权限附加项,但我在我的应用程序中没有看到Android Manifest XML文件;为什么只有Android需要一个清单?

非常感谢您的帮助;谢谢,保重。


1
我认为获取有关更改的正确和简单方法在https://github.com/react-native-community/react-native-netinfo#usage中有所描述。此外,还可以查看https://github.com/react-native-community/react-native-netinfo#netinfostate以获取更多信息,例如isConnected和isInternetReachable之间的区别。 - Yossi
15个回答

57

今天我遇到了这个问题,并找到了我认为最好的解决方案。 它将会持续搜索网络变化并相应地显示它们。

我使用expo install @react-native-community/netinfo测试过了,它工作得非常完美

import {useNetInfo} from "@react-native-community/netinfo";
import {View, Text} from "react-native";
const YourComponent = () => {
  const netInfo = useNetInfo();

  return (
    <View>
      <Text>Type: {netInfo.type}</Text>
      <Text>Is Connected? {netInfo.isConnected.toString()}</Text>
    </View>
  );
};

当我使用它时,它有一个缺陷。它首先返回“null”,然后返回“true”或“false”。那个“null”很烦人。 - Four
如果连接稍后发生更改,则不会更新。如果连接更改了,我们如何更新它? - gggx
2
useNetInfo 是一个 React Hook,如果连接状态发生变化,它将自动更新组件状态。请确保您遵循示例,或花些时间学习 React Hooks/组件等。 - Jone Polvora

29

请阅读此https://reactnativeforyou.com/how-to-check-internet-connectivity-in-react-native-android-and-ios/链接。

import React, { Component } from "react";
import { View, Text, Button, Alert, NetInfo, Platform } from "react-native";

export default class componentName extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  CheckConnectivity = () => {
    // For Android devices
    if (Platform.OS === "android") {
      NetInfo.isConnected.fetch().then(isConnected => {
        if (isConnected) {
          Alert.alert("You are online!");
        } else {
          Alert.alert("You are offline!");
        }
      });
    } else {
      // For iOS devices
      NetInfo.isConnected.addEventListener(
        "connectionChange",
        this.handleFirstConnectivityChange
      );
    }
  };

  handleFirstConnectivityChange = isConnected => {
    NetInfo.isConnected.removeEventListener(
      "connectionChange",
      this.handleFirstConnectivityChange
    );

    if (isConnected === false) {
      Alert.alert("You are offline!");
    } else {
      Alert.alert("You are online!");
    }
  };

  render() {
    return (
      <View>
        <Button
          onPress={() => this.CheckConnectivity()}
          title="Check Internet Connectivity"
          color="#841584"
          accessibilityLabel="Learn more about this purple button"
        />
      </View>
    );
  }
}

2
这很有帮助;但是,如果没有按钮,如何持续检查互联网连接(如果互联网连接状态发生变化,则触发操作)? - zstardust225
这是连接更改的回调函数NetInfo.isConnected.addEventListener( "connectionChange", this.handleFirstConnectivityChange );handleFirstConnectivityChange = isConnected => { //NetInfo.isConnected.removeEventListener("connectionChange",this.handleFirstConnectivityChange); if (isConnected === false) { Alert.alert("您已离线!"); } else { Alert.alert("您已上线!"); } }; - Mirzohid Akbarov
当连接发生变化时,whenhandleFirstConnectivityChange() 方法被调用。 - Mirzohid Akbarov
我不明白为什么iOS和Android之间的代码需要不同。在我看来,获取有关更改的正确和简单方法已在https://github.com/react-native-community/react-native-netinfo#usage中描述。还可以查看https://github.com/react-native-community/react-native-netinfo#netinfostate以获取更多信息,例如isConnected和isInternetReachable之间的区别。 - Yossi
11
NetInfo不再是React Native项目的一部分,已从核心中分离出来。您可以使用此示例->https://dev59.com/2L3pa4cB1Zd3GeqPiqcw#64295620。 - twboc
显示剩余2条评论

22

似乎这个问题在stackoverflow上已经被广泛讨论,但似乎没有人关注其他现有答案。

你应该使用"@react-native-community/netinfo"库。 NetInfo曾经是react-native的一部分,但后来被分离出核心。如果您想观察网络状态改变,只需使用提供的addEventListener方法即可。

import NetInfo from "@react-native-community/netinfo";

NetInfo.fetch().then(state => {
    console.log("Connection type", state.type);
    console.log("Is connected?", state.isConnected);
});

const unsubscribe = NetInfo.addEventListener(state => {
    console.log("Connection type", state.type);
    console.log("Is connected?", state.isConnected);
});

// Unsubscribe
unsubscribe();

我在 Android 中切换无线网络开关或切换无线和蜂窝网络时遇到问题,状态值没有更新。 - Jeaf Gilbert
@JeafGilbert,您是在后台还是前台执行此操作?也许您可以粘贴一下代码?我猜当您打开选项时,应用程序会进入后台,这将需要在后台任务中使用不同的监听器。这也可能与休眠问题有关。https://github.com/react-native-netinfo/react-native-netinfo/issues/537 - twboc
1
结果发现将版本从v6.0.0更新到v7.1.7导致了这个问题。所以我回滚到了v6.0.0,现在能够正常工作了。 - Jeaf Gilbert
代码示例应该保存在哪里? - Green
1
为您的应用程序创建一个网络代码或模块的文件夹。然后在应用程序的某个init块代码中调用此处提供的方法。并在关闭应用程序时取消订阅。 - twboc

9

这不是对@NSA提出的问题的答案。 - manish kumar
7
抱歉,我通过提供新信息完成了第一个答案 :) - Jocelyn Nsa

8

6
创建 NetworkUtills.js
import NetInfo from "@react-native-community/netinfo";
export default class NetworkUtils {
  static async isNetworkAvailable() {
    const response = await NetInfo.fetch();
    return response.isConnected;
}}

可像这样在任何地方使用

const isConnected = await NetworkUtils.isNetworkAvailable()

3

这是对我有效的方法(使用TypeScript)

import React, {useEffect, useState} from "react";
import NetInfo, {NetInfoState} from "@react-native-community/netinfo";

const OfflineScreen = () => {
    const [isOffline, setIsOffline] = useState(false);
    useEffect(() => {
        const removeNetInfoSubscription = NetInfo.addEventListener((state: NetInfoState) => {
          const offline = !(state.isConnected && state.isInternetReachable)
          console.log(offline)
          setIsOffline(offline)
        })
    
        return () => removeNetInfoSubscription()
      }, [])

    return <Text>{`Internet Status: ${isOffline}`}</Text>
}

这个答案应该是被选中的。因为它使用了一个事件监听器,如果使用refresh方法,它将会被更新。 - Ali Bahaari

3

以下是关于如何检查您的应用是否能够访问互联网的最新解决方案。

首先安装官方的 NetInfo 社区包:

yarn add @react-native-community/netinfo

然后是代码片段。
import { Platform } from "react-native";
import NetInfo from "@react-native-community/netinfo";
...


const checkConnectivity: Promise<boolean | null> = () => {
    return new Promise(resolve => {
        if (Platform.OS === "android") {
            // For Android devices
            NetInfo.fetch().then(state => {
                resolve(state.isInternetReachable);
            });
        } else {
            // For iOS devices
            const unsubscribe = NetInfo.addEventListener(state => {
                unsubscribe();
                resolve(state.isInternetReachable);
            });
        }
    });
};

...

以及它的使用方法

...
const hasInternetAccess = await checkConnectivity();

if(hasInternetAccess) {
   // My app can reach the internet
} 
else {
  // Can't connect to the internet. Too bad!
}


NetInfo.addEventListener() 内定义的 unsubscribe() 函数是如何工作的?我收到了“未定义的 unsubscribe()”错误。 - Rahul.S
@Rahul.S,调用 NetInfo.addEventListener 将返回一个回调函数,可用于取消订阅事件监听器。您可以在该包的 npm 页面上查看一些示例,网址为 https://www.npmjs.com/package/@react-native-community/netinfo 。 - Cels

3

非常感谢这些答案,但这里是一个完整的例子,使用useNetInfo React Hook 触发当状态将要改变时,使用Alert 来通知用户,并向用户显示一些文本的View

import { useNetInfo, NetInfoState } from "@react-native-community/netinfo";
import {
  Alert,
  StyleSheet,
  Text,
  View,
} from "react-native";
...
const internetState: NetInfoState = useNetInfo();
...
useEffect(() => {
  if (internetState.isConnected === false) {
    Alert.alert(
      "No Internet! ❌",
      "Sorry, we need an Internet connection for MY_APP to run correctly.",
      [{ text: "Okay" }]
    );
  }
}, [internetState.isConnected]);
...
if (internetState.isConnected === false) {
  return (
    <View style={styles.centered}>
      <Text style={styles.title}>
        Please turn on the Internet to use MY_APP.
      </Text>
    </View>
  );
}
...
const styles = StyleSheet.create({
  centered: {
    alignItems: "center",
    flex: 1,
    justifyContent: "center",
  },
  title: {
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
});

PS. 我没有把它包含在 App.tsxnavigation/index.tsx 中,以避免代码重复。接下来尝试,我已将逻辑包含在每个 screen 中。对于 App.tsxnavigation/index.tsx 的情况,当互联网恢复时,用户将被重定向到应用程序的起始 screen,这不是我想要的。我希望,当有网络且恢复时,用户回到他们离开的那个屏幕。使用多个屏幕中的逻辑时,会触发多个 alerts :( 最后,我已将与 Alert 相关的逻辑包含在 App.tsx 中,而在每个 screen 中包含显示无互联网信息的 ViewAlert 只弹出一次,但最好也避免 View 的代码重复。如果您知道如何从代码库的一个位置执行此操作,请随时发布更新。非常感谢!


2

我正在使用react-native 0.66.3版本。

我已经在启动画面中添加了以下代码,当NetInfo返回“isConnected : false”时,我会显示“再试一次”按钮以检查网络连接。

如果网络连接成功,导航将转到主屏幕。

这是我的启动画面:

import React, { useEffect, useState } from "react";
...
import NetInfo from "@react-native-community/netinfo";

const Splash = (props) => {
  const [network, setNetwork] = useState('')
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    unsubscribe()
  }, []);

  function unsubscribe() {
    NetInfo.fetch().then(state => {
      setNetwork(state)
      setTimeout(function () {
        if (state.isConnected) {
          // any thing you want to load before navigate home screen
        } else {
          setLoading(false)
        }
      }, 500);
    })
  };



  return (
    <View style={{
      flex: 1,
      backgroundColor: global.bgBody,
      justifyContent: 'center',
      alignItems: 'center'
    }}>
      <Image
        source={Logo}
        style={{
          width: 150,
          height: 123,
        }}
      />
      {!network?.isConnected || loading ? <View style={{ marginTop: 30 }}>
        <Description text={`Please check your internet connection and try again`} />
        <Button
          title="Try Again"
          onPress={() => {
            setLoading(true)
            unsubscribe()
          }}
          loading={loading}
        />
      </View> : null}
    </View>
  );
};
export default Splash;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接