ConnectivityPollManager.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. /// <summary>
  6. /// This component is responsible for continously checking if there is an internet connection.
  7. /// This is done by first checking the Application.internetReachability. But this can give false
  8. /// positives, e.g. connected to a wifi router but does not have an actual internet connection.
  9. /// So the next step is pinging PING_DESTINATION every TIME_BETWEEN_PINGS seconds.
  10. /// If the ping fails for FAILED_PINGS_DISCONNECTION_TRIGGER times, it means it has gone offline.
  11. /// Whenever the connectivity changes, a ConnectivityChange notification is fired.
  12. /// </summary>
  13. public class ConnectivityPollManager : MonoBehaviour
  14. {
  15. static bool _hasInternet;
  16. public static bool HasInternet { get { return _hasInternet; } }
  17. private const string PING_DESTINATION = "https://game.gamatic.com/ping_do_not_delete.html";
  18. const float TIME_BETWEEN_PINGS = 3; //seconds
  19. //sometimes the ping just fails every once in a while, so we should do multiple pings just to make sure
  20. const int FAILED_PINGS_DISCONNECTION_TRIGGER = 3;
  21. bool _hasPingedDestination;
  22. string _address;
  23. int _failedPings;
  24. void Start()
  25. {
  26. StartCoroutine(CheckForConnectivityCoroutine());
  27. }
  28. IEnumerator CheckForConnectivityCoroutine()
  29. {
  30. while (true)
  31. {
  32. bool isNetworkReachable = (Application.internetReachability != NetworkReachability.NotReachable);
  33. //If the api says that it is reachable, we need to test further by pinging a proper connection
  34. if (isNetworkReachable)
  35. {
  36. yield return StartCoroutine(TestConnectionCoroutine());
  37. if (_hasPingedDestination != _hasInternet)
  38. {
  39. if (!_hasPingedDestination)
  40. {
  41. ++_failedPings;
  42. if (_failedPings >= FAILED_PINGS_DISCONNECTION_TRIGGER)
  43. {
  44. AVDebug.Log("Went offline");
  45. _hasInternet = false;
  46. CoreNotificationCenter.Post(CoreNotificationType.ConnectivityChange, _hasPingedDestination);
  47. }
  48. else
  49. {
  50. AVDebug.Log("Ping missed");
  51. }
  52. }
  53. else
  54. {
  55. AVDebug.Log("Back online");
  56. _hasInternet = true;
  57. _failedPings = 0;
  58. CoreNotificationCenter.Post(CoreNotificationType.ConnectivityChange, _hasPingedDestination);
  59. }
  60. }
  61. } else
  62. {
  63. //Network was not reachable
  64. if (_hasInternet)
  65. {
  66. AVDebug.Log("Went offline (airplane mode/wifi off?)");
  67. _hasInternet = false;
  68. CoreNotificationCenter.Post(CoreNotificationType.ConnectivityChange, _hasPingedDestination);
  69. }
  70. }
  71. yield return new WaitForSeconds(TIME_BETWEEN_PINGS);
  72. }
  73. }
  74. //Inspired from http://forum.unity3d.com/threads/68938-How-can-you-tell-if-there-exists-a-network-connection-of-any-kind
  75. //Its result is stored in _hasPingedDestination, since coroutines cannot return a value directly
  76. IEnumerator TestConnectionCoroutine()
  77. {
  78. _hasPingedDestination = false;
  79. WWW www = new WWW(PING_DESTINATION);
  80. yield return www;
  81. if (www.error == null)
  82. {
  83. _hasPingedDestination = true;
  84. }
  85. }
  86. }