Check for internet connectivity from Unity
Asked Answered
A

10

18

I have a Unity project which I build for Android and iOS platforms. I want to check for internet connectivity on Desktop, Android, and iOS devices. I've read about three different solutions:

  1. Ping something (for example Google) - I totally dislike such decision, and I've read about mistakes on Android.

  2. Application.internetReachability - According to Unity's documentation, this function will only determine that I have a POSSIBILITY of connecting to the Internet (it doesn't guarantee a real connection).

  3. Network.TestConnection() - If I have no Internet connection, my application fails. So this isn't correct either.

How can I determine whether I have internet connectivity from within Unity?

Anthemion answered 7/12, 2015 at 16:42 Comment(7)
Why would Network.TestConnection() cause your application to fail? Seems like a little error handling would easily catch that.Hatti
Please link to the mentioned "mistakes" with the pinging approach?Dentate
@RonBeyer , if I use Network.TestConnection(), and have no Internet Connection, my Application fails with following exception: 'Cannot resolve connection tester address, you must be connected to the internet before performing this or set the address to something accessible to you.' I copied cope from docs.unity3d.com/ScriptReference/Network.TestConnection.htmlAnthemion
@AnnaKuleva If Network.TestConnection() only throws the exception when there is no internet, just wrap it in a try-catch. Error means no internet, and no error means you can look at the test results.Dentate
@RonBeyer There are a lot of topics were people try to catch this exception) I haven't seen any ready answer yet. If you give me a link with the answer, I would said "Thank you".Anthemion
@SamB , I need one solution for two different platforms (if it's possible). How to do it for ios-platform, I've already known.Anthemion
This is definitely not a duplicate of the linked question. This question is asking about how to check for connectivity using C# from within Unity3D on PC, Android and iOS. The proposed duplicate is asking how to check for connectivity using Objective-C from the iOS SDK, using Cocoa Touch. These are two completely separate programming languages and technology stacks.Misjudge
M
13

I don't actually believe that Network.TestConnection() is the right tool for this job. According to the documentation, it looks to me like it's meant for testing if NAT is working and your client is publicly reachable by IP, but what you want to check for is whether you have general internet connectivity.

Here is a solution that I found on Unity Answers by user pixel_fiend, which simply tests a website to see if the user has connectivity. One benefit of this code is that it uses IEnumerator for asynchronous operation, so the connectivity test won't hold up the rest of your application:

IEnumerator checkInternetConnection(Action<bool> action){
     WWW www = new WWW("http://google.com");
     yield return www;
     if (www.error != null) {
         action (false);
     } else {
         action (true);
     }
 } 
 void Start(){
     StartCoroutine(checkInternetConnection((isConnected)=>{
         // handle connection status here
     }));
 }

You can change the website to whatever you want, or even modify the code to return success if any one of a number of sites are reachable. AFAIK there is no way to check for true internet connectivity without trying to connect to a specific site on the internet, so "pinging" one or more websites like this is likely to be your best bet at determining connectivity.

Misjudge answered 7/12, 2015 at 18:16 Comment(9)
How to call Action<bool> action ? using what ?Inedited
@HahaTTpro Using StartCoroutine(checkInternetConnection((isConnected)=>{/* handle connection status here */}));Misjudge
Thank for answer @Maximillian. However, it is not I want. I mean "what is the namespace of Action<bool>". It is System.Action<bool>.Inedited
@HahaTTpro Yes that's correct, it is System.Action. More info: https://mcmap.net/q/9639/unity-what-is-system-actionMisjudge
Will this work on IOS too?Pretzel
@AlirezaJamali WWW inherits from CustomYieldInstruction, so yes, it does support yield return. See the Unity docs on WWW, which itself uses yield return in its example.Misjudge
@MikePandolfini Asynchronicity is not a function of which thread code runs on. This code makes an asynchronous request, and this code runs on the main thread. From Unity docs: "It’s best to use coroutines if you need to deal with long asynchronous operations, such as waiting for HTTP transfers, asset loads, or file I/O to complete."Misjudge
@MikePandolfini This code works asynchronously in the respect that it defines an asynchronous trigger - in this case, a web response. Oxford describes "asynchronous" as "of or requiring a form of computer control timing protocol in which a specific operation begins upon receipt of an indication (signal) that the preceding operation has been completed," which describes this situation well. Furthermore, "async functions" are often not asynchronous threadwise as you suggest - see JS for example. The Unity documentation page that I cited uses language consistent with all that. Hope this helps.Misjudge
@MaximillianLaumeister yes, the yield return www; portion of the code you copied there is asynchronous. Remaining operations will block the main thread.Enamelware
P
9
public static IEnumerator CheckInternetConnection(Action<bool> syncResult)
{
    const string echoServer = "http://google.com";

    bool result;
    using (var request = UnityWebRequest.Head(echoServer))
    {
        request.timeout = 5;
        yield return request.SendWebRequest();
        result = !request.isNetworkError && !request.isHttpError && request.responseCode == 200;
    }
    syncResult(result);
}
Paganini answered 19/8, 2019 at 9:15 Comment(0)
O
4
void Start()
{
    StartCoroutine(CheckInternetConnection(isConnected =>
    {
        if (isConnected)
        {
            Debug.Log("Internet Available!");
        }
        else
        {
            Debug.Log("Internet Not Available");
        }
    }));
}

IEnumerator CheckInternetConnection(Action<bool> action)
{
    UnityWebRequest request = new UnityWebRequest("http://google.com");
    yield return request.SendWebRequest();
    if (request.error != null) {
        Debug.Log ("Error");
        action (false);
    } else{
        Debug.Log ("Success");
        action (true);
    }
}

Since WWW has deprecated, UnityWebRequest can be used instead.

Odelet answered 26/5, 2020 at 15:48 Comment(1)
it may work but it has a logical/cost problem. It loads the whole page to check whether the connection is established or not because it does this by sending a GET request, but in this case(for connectivity check) Head request is enough(like @KirillBelonogov answer) because we don't need to load or render the page to the user.Villanovan
H
3

Ping 8.8.8.8 instead of sending a GET unity already provides the tool for that:

Ping

The ping operation is asynchronous and a ping object can be polled for status using Ping.isDone. When a response is received it is in Ping.time.

Windows Store Apps: A stream socket is used to mimic ping functionality, it will try to open a connection to specified IP address using port 80. For this to work correctly, InternetClient capability must be enabled in Package.appxmanifest.

Android: ICMP sockets are used for ping operation if they're available, otherwise Unity spawns a child process /system/bin/ping for ping operations. To check if ICMP sockets are available, you need to read the contents for /proc/sys/net/ipv4/ping_group_range. If ICMP sockets are available, this file should contain an entry for 0 2147483647.

using UnityEngine;
using System.Collections.Generic;
 
public class PingExample : MonoBehaviour
{
    bool isConnected = false;
    private IEnumerator Start()
    {
        while(true)
        {
            var ping = new Ping("8.8.8.8");
 
            yield return new WaitForSeconds(1f);
            while (!ping.isDone) 
            {
                isConnected = false;
                yield return null;
            }
            isConnected = true;
            Debug.Log(ping.time);
        }
    }
}
Hellbox answered 22/4, 2022 at 19:22 Comment(5)
note: ping.IsDone is false at first few frames after the new Ping request,Hellbox
For a game that is constantly online, while(ping.isDone) can be useful, but it's not a good way to get the connection's state of a device. The reason is that the "new Ping()" call will halt the remaining of the function until it's sent and it will only be sent once the Internet is available, meaning that the loop will hold still and never tell the app that there's no internet.Paulson
unity Ping does not halt the remaining of the function it's asynchronous as stated in documentation docs.unity3d.com/ScriptReference/Ping.html , as for "it will only be sent once the Internet is available" that's the whole point, it won't be able to send and thus IsDone() returns false so you know there's no internetHellbox
You're not wrong, but you forget the crucial point that the device may not be able to know if it's properly connected or only set on a gateway (like on a public Wifi which requires a login to use.) the Pint() call will be sent in such case and will never return. You don't understand the asynchronous aspect of it. The function that calls it won't continue if the Ping doesn't return a proper value. As an asynchronous call, it means that other scripts and update() methods will keep running.Paulson
I don't think you understand the meaning of asynchronous when you say "The function that calls it won't continue", why do you need that specific thread that Ping uses to continue? it's not the main thread, not the UI thread, your app does not halt so it's an asynchronous method/function, you can also manually set a timeout so you know it took so much to return, I myself use multiple method specially the one in your answer but I use Ping first and other as alternativeHellbox
J
1

i know this is old, but maybe can help you.

public bool CheckInternetConnection(){
    return !(Application.internetReachability == NetworkReachability.NotReachable)
}
Janenejanenna answered 2/6, 2018 at 7:20 Comment(5)
Is it working on mobile devices with Android and iOS?Nuristan
yes, i tested, this is work on all devices and platformsJanenejanenna
Did you read the question? It says right there that this is insufficient. The documentation says this only suggests there is a network available, not that the network has connectivity. For example, wifi connection to a router but the router has no external connection. There's even a duplicate downvote answer.Ribonuclease
Application.internetReachability is not for actual connectionSnocat
The result of Application.internetReachability will not depend if the device has access or not to the Internet (if it's connected), but if it has the components required to access the Internet. For example, if you use it on a PC, it will always return "Reachable Via Local Area Network" for as long as the PC has a Network adapter (which is, nowadays, installed on the motherboard). Smartphones will only return "Reachable via Carrier Data Network" if there's a SIM card installed. Even if the device is offline, it will still return Reachable Via Carrier Data" if there's a SIM card installed.Paulson
X
1

I necro this post just for sharing experience on the 'pinging' approach: I've made a (nodejs) package years ago that was polling a simple url call to check connectivity (default url = google.com), everything was working fine. Until that day where a user who had downloaded my package came to me with this: he was using my package on hundreds of computer on his company, all reaching the default url many times per minutes (default = every second!), it resulted on his company ip banned by google for suspicious activity! So be careful with this approach depending on the context it's gonna be used!

Xanthic answered 4/11, 2023 at 15:41 Comment(0)
G
0

I've created an Android's library that can be used as Unity's plugin for this purpose. If anyone's interested it's available under https://github.com/rixment/awu-plugin

As for the iOS version unfortunately I don't have enough of knowledge in this area. It would be nice if someone could extend the repo to include the iOS version too.

Giraudoux answered 17/3, 2020 at 9:10 Comment(0)
P
0

With the latest version of Unity, WWW has become obsolete, hence you need to use WebRequest.

This is the bit of codes I'm using to check if the user is online:

private string HtmlLookUpResult_Content;
private char[] HtmlLookUpResult_Chars;
private StreamReader HtmlLookUpResult_Reader;
private bool HtmlLookUpResult_isSuccess;
private HttpWebRequest HtmlLookUpResult_Request;
private HttpWebResponse HtmlLookUpResult_Response;
public bool CheckIfOnline()
{
    HtmlLookUpResult_Content = UniversalEnum.String_Empty;
    HtmlLookUpResult_Request = (HttpWebRequest)WebRequest.Create(UniversalEnum.WebHtml_isOnline);
    HtmlLookUpResult_Request.Timeout = 5000;
    try
    {
        using (HtmlLookUpResult_Response = (HttpWebResponse)HtmlLookUpResult_Request.GetResponse())
        {
            HtmlLookUpResult_isSuccess = (int)HtmlLookUpResult_Response.StatusCode < 299 && (int)HtmlLookUpResult_Response.StatusCode >= 200;
            if (HtmlLookUpResult_isSuccess)
            {
                using (HtmlLookUpResult_Reader = new StreamReader(HtmlLookUpResult_Response.GetResponseStream()))
                {
                    HtmlLookUpResult_Chars = new char[1];
                    HtmlLookUpResult_Reader.Read(HtmlLookUpResult_Chars, 0, 1);
                    HtmlLookUpResult_Content += HtmlLookUpResult_Chars[0];
                }
            }
        }
    }
    catch
    {
        HtmlLookUpResult_Content = UniversalEnum.String_Empty;
    }
    if (HtmlLookUpResult_Content != UniversalEnum.String_Empty)
    {
        return true;
    }
    else
    {
        return false;
    }
}

If you would like to know if the user is just online, you can get the result just from the boolean HtmlLookUpResult_isSuccess in the code. But, in reality, you most likely want to confirm the user has also access to your server or whatever remote system you use in your project, right? Which is what the remaining of the code does.

In case you wonder what UniversalEnum is, in my code, it's a separate non-Monobehavior script that contains all persistent variables (like strings and hashes) I'm planning on reusing in my project. For short:

UniversalEnum.String_Empty = "";

UniversalEnum.WebHtml_isOnline = "http://www.ENTER_YOUR_WEBSITE_HERE.com/games-latestnews/isOnline.html"

That isOnline.html file is, as you can see, a file in the folder "games-latestnews" in the HTML_content of my hosted website and it contains only [1] as it content. It has no header, no actual content and is pretty much like a .txt file set online. I'm using this method also because I can add new news to my game by just adding new HTML page in that folder. I'm also surrounding the content check with a Try{} so that if ANYTHING fails, it returns the Catch{} value and then by comparing if the content (a string) is an empty string or contain anything, we know if the user is both online and if he/she has access to your website.

On good example of why you would want to check that the user has both access to the net AND to your website is if the user is using a limited network such as what you might find at a school. If a school decided to ban your website due to whatever reason, just looking up if the connection is possible will return a false positive since it wouldn't access the actual webpage anyway.

Paulson answered 4/10, 2022 at 6:58 Comment(0)
F
0

// Below Code Working Perfect for Me for Three Cases Which includes all above solution in single script==>

 private string pingUrl = "https://google.com"; // Replace with a reliable server
 public static bool isInternetConnected = false;
 float checkInterval = 3f; // Adjust the interval as needed (e.g., 10 seconds)

 private void Start()
 {
     StartCoroutine(CheckConnectionLoop());
 }

 /// <summary>
 /// Repetative Coroutine for Checking Internet Connectivity at given time Time Interval
 /// </summary>
 /// <returns></returns>
 IEnumerator CheckConnectionLoop()
 {
     while (true)
     {
         CheckConnection();
         yield return new WaitForSeconds(checkInterval);
     }
 }

 /// <summary>
 /// Method to Check Various Internet Connectivity Status Cases
 /// </summary>
 void CheckConnection()
 {
     switch (Application.internetReachability)
     {
         case NetworkReachability.NotReachable:
             isInternetConnected = false;
             SwitchInternetConnectionPanel();
             break;

         case NetworkReachability.ReachableViaCarrierDataNetwork:
             isInternetConnected = true;
             StartCoroutine(ConfirmConnection());
             break;

         case NetworkReachability.ReachableViaLocalAreaNetwork:
             isInternetConnected = true;
             StartCoroutine(ConfirmConnection());
             break;
     }
 }

 /// <summary>
 /// Coroutine to Confirm Valid Internet Connection Even if there is any Active Network Found
 /// </summary>
 /// <returns></returns>
 IEnumerator ConfirmConnection()
 {
     using (UnityWebRequest request = UnityWebRequest.Get(pingUrl))
     {
         yield return request.SendWebRequest();

         isInternetConnected = request.isDone && request.result == UnityWebRequest.Result.Success;
         SwitchInternetConnectionPanel();
     }
 }

 /// <summary>
 /// Method to Switch No Internet Popup Panel by checking bool
 /// </summary>
 void SwitchInternetConnectionPanel()
 {
     if (isInternetConnected)
     {
         Debug.Log("Confirmed internet connection!");
        // You can Hide the No Internet Popup If it is already open due to no internet 
        // Write your desire code for Internet available
     }
     else
     {
         Debug.Log("Confirmed: No internet connection!");
         // OpenNoInternetPopupPanel(); 
         // You Can Open - No Internet Popup or Write Desire Code for No Internet 
     }
 }
Farflung answered 11/7, 2024 at 13:28 Comment(1)
Can you add some explanations about your codes.Demonography
D
-2

You can check network connection using this code

if(Application.internetReachability == NetworkReachability.NotReachable){
       Debug.Log("Error. Check internet connection!");
}
Diagraph answered 5/4, 2020 at 9:59 Comment(1)
see for check conn, and its type -> docs.unity3d.com/ScriptReference/… However in regards to internetReachability: "Do not use this property to determine the actual connectivity. E.g. the device can be connected to a hot spot, but not have the actual route to the network." docs.unity3d.com/ScriptReference/…Gratification

© 2022 - 2025 — McMap. All rights reserved.