17

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?

Mikepote
  • 6,042
  • 3
  • 34
  • 38
Anna Kuleva
  • 179
  • 1
  • 1
  • 3
  • 5
    Why would `Network.TestConnection()` cause your application to fail? Seems like a little error handling would easily catch that. – Ron Beyer Dec 07 '15 at 16:43
  • 1
    Please link to the mentioned "mistakes" with the pinging approach? – SimpleVar Dec 07 '15 at 16:47
  • @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 http://docs.unity3d.com/ScriptReference/Network.TestConnection.html – Anna Kuleva Dec 07 '15 at 16:59
  • 2
    @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. – SimpleVar Dec 07 '15 at 17:03
  • @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". – Anna Kuleva Dec 07 '15 at 17:05
  • @SamB , I need one solution for two different platforms (if it's possible). How to do it for ios-platform, I've already known. – Anna Kuleva Dec 07 '15 at 17:08
  • 3
    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. – Maximillian Laumeister Dec 08 '15 at 19:02

8 Answers8

12

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.

Maximillian Laumeister
  • 19,884
  • 8
  • 59
  • 78
  • How to call Action action ? using what ? – Haha TTpro Apr 25 '16 at 10:01
  • @HahaTTpro Using `StartCoroutine(checkInternetConnection((isConnected)=>{/* handle connection status here */}));` – Maximillian Laumeister Apr 25 '16 at 17:18
  • Thank for answer @Maximillian. However, it is not I want. I mean "what is the namespace of Action". It is System.Action. – Haha TTpro Apr 26 '16 at 15:15
  • @HahaTTpro Yes that's correct, it is System.Action. More info: http://answers.unity3d.com/questions/335953/what-is-systemaction.html – Maximillian Laumeister Apr 26 '16 at 17:05
  • Will this work on IOS too? – Naresh Bisht Feb 22 '22 at 15:52
  • 1
    @AlirezaJamali WWW inherits from CustomYieldInstruction, so yes, it does support `yield return`. See [the Unity docs on WWW](https://docs.unity3d.com/ScriptReference/WWW.html), which itself uses `yield return` in its example. – Maximillian Laumeister Dec 14 '22 at 19:13
  • @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](https://docs.unity3d.com/Manual/Coroutines.html): "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." – Maximillian Laumeister Dec 14 '22 at 19:19
  • @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. – Maximillian Laumeister Dec 16 '22 at 01:49
  • @MaximillianLaumeister yes, the yield return www; portion of the code you copied there is asynchronous. Remaining operations will block the main thread. – Mike Pandolfini Dec 17 '22 at 03:41
8
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);
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Kirill Belonogov
  • 414
  • 4
  • 14
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.

Arkar Min Tun
  • 605
  • 8
  • 12
1

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

public bool CheckInternetConnection(){
    return !(Application.internetReachability == NetworkReachability.NotReachable)
}
kamiyar
  • 177
  • 1
  • 12
  • Is it working on mobile devices with Android and iOS? – Skylin R Oct 16 '19 at 06:15
  • 1
    yes, i tested, this is work on all devices and platforms – kamiyar Oct 17 '19 at 13:48
  • 1
    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. – user99999991 Jul 28 '20 at 01:50
  • 1
    Application.internetReachability is not for actual connection – Saad Anees Nov 09 '20 at 10:52
  • 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. – user3345048 Jul 25 '22 at 18:16
1

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);
        }
    }
}
Alireza Jamali
  • 302
  • 2
  • 6
  • 17
  • note: ping.IsDone is false at first few frames after the new Ping request, – Alireza Jamali Apr 22 '22 at 20:59
  • 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. – user3345048 Jul 25 '22 at 18:28
  • unity Ping does not halt the remaining of the function it's asynchronous as stated in documentation https://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 internet – Alireza Jamali Nov 23 '22 at 16:22
  • 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. – user3345048 Nov 24 '22 at 18:53
  • 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 alternative – Alireza Jamali Nov 25 '22 at 09:14
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.

Eric
  • 1,685
  • 1
  • 17
  • 32
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.

user3345048
  • 361
  • 3
  • 3
-2

You can check network connection using this code

if(Application.internetReachability == NetworkReachability.NotReachable){
       Debug.Log("Error. Check internet connection!");
}
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81
  • see for check conn, and its type -> https://docs.unity3d.com/ScriptReference/NetworkReachability.ReachableViaLocalAreaNetwork.html 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." https://docs.unity3d.com/ScriptReference/Application-internetReachability.html – Sergio Solorzano May 27 '20 at 07:56