Connectivity - Code

Indicates status of network connection availability [SOCL-Connectivity-02]

Examples

Here are examples which cover common programming needs.

πŸ“˜

Beamable SDK Examples

β€’ The following example code is available for download at GitHub.com/Beamable_SDK_Examples

In this ConnectivityServiceExample.cs, the UI shows the current state of the internet connectivity and updates automatically if any changes occur (ex. if the ethernet / Wi-Fi is manually disabled or enabled by the user).

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

namespace Beamable.Examples.Services.ConnectivityService
{
    /// <summary>
    /// Holds data for use in the <see cref="ConnectivityServiceExampleUI"/>.
    /// </summary>
    [System.Serializable]
    public class ConnectivityServiceExampleData
    {
        public List<string> OutputLogs = new List<string>();
        public bool HasConnectivity = false;
    }
   
    [System.Serializable]
    public class RefreshedUnityEvent : UnityEvent<ConnectivityServiceExampleData> { }
    
    /// <summary>
    /// Demonstrates <see cref="ConnectivityService"/>.
    /// </summary>
    public class ConnectivityServiceExample : MonoBehaviour
    {
        //  Events  ---------------------------------------
        [HideInInspector]
        public RefreshedUnityEvent OnRefreshed = new RefreshedUnityEvent();
        
        //  Fields  ---------------------------------------
        private BeamContext _beamContext;
        private ConnectivityServiceExampleData _data = new ConnectivityServiceExampleData();
    
        //  Unity Methods  --------------------------------
        protected void Start()
        {
            Debug.Log($"Start() Instructions...\n\n" +
                      " * Ensure Computer's Internet Is Active\n" +
                      " * Run The Scene\n" +
                      " * See Onscreen UI Show HasConnectivity = true\n" +
                      " * Ensure Computer's Internet Is NOT Active (e.g. Turn off wifi/ethernet)\n" +
                      " * See Onscreen UI Show HasConnectivity = false\n");

            SetupBeamable();
        }
        
        //  Methods  --------------------------------------
        private async void SetupBeamable()
        {
            _beamContext = BeamContext.Default;
            await _beamContext.OnReady;

            Debug.Log($"beamContext.PlayerId = {_beamContext.PlayerId}");

            // Observe ConnectivityService Changes
            _beamContext.Api.ConnectivityService.OnConnectivityChanged += ConnectivityService_OnConnectivityChanged;
            
            // Update UI Immediately
            bool hasConnectivity = _beamContext.Api.ConnectivityService.HasConnectivity;
            ConnectivityService_OnConnectivityChanged(hasConnectivity);
        }
        
        public void ToggleHasInternet()
        {
            _beamContext.Api.ConnectivityService.SetHasInternet(!_data.HasConnectivity);
        }

        public void Refresh()
        {
            string refreshLog = $"Refresh() ..." +
                                $"\n * HasConnectivity = {_data.HasConnectivity}" + 
                                $"\n * OutputLogs = {_data.OutputLogs.Count}\n\n";
            
            //Debug.Log(refreshLog);
            
            // Send relevant data to the UI for rendering
            OnRefreshed?.Invoke(_data);
        }
        
        //  Event Handlers  -------------------------------
        private void ConnectivityService_OnConnectivityChanged(bool hasConnectivity)
        {
            _data.HasConnectivity = hasConnectivity;
            
            _data.OutputLogs.Add($"HasConnectivity = {_data.HasConnectivity}");
            
            Refresh();
        }
    }
}

Disable Network Connection

Game makers can set a global disable to simulate not having wifi before BeamContext initialization.

private static void ForceDisableConnectivity()
{
    // to simulate network outage even if the device is online
    IConnectivityServiceExtensions.GlobalForceDisabled = true;
}

private async void SetupBeamable()
{
    ForceDisableConnectivity();

    _beamContext = BeamContext.Default;
    await _beamContext.OnReady;

    Debug.Log($"beamContext.PlayerId = {_beamContext.PlayerId}");

    // Observe ConnectivityService Changes
    _beamContext.Api.ConnectivityService.OnConnectivityChanged += ConnectivityService_OnConnectivityChanged;

    // Update UI Immediately
    bool hasConnectivity = _beamContext.Api.ConnectivityService.HasConnectivity;
    ConnectivityService_OnConnectivityChanged(hasConnectivity);
}

Custom Connectivity Service

From version 1.11 and above, you can override the IConnectivityChecker service via Dependency Injection and change how the connectivity logic works. The default implementation uses a polling approach and sends requests to Beamable's API Gateway.

In the code sample below, there is a custom implementation of IConnectivityService that pings a local server at "http://127.0.0.1:3000/ping".

using System;
using System.Collections;
using Beamable.Api.Connectivity;
using Beamable.Common;
using UnityEngine;
using UnityEngine.Networking;

public class CustomConnectivityService : IConnectivityService
{
    private bool _isConnected = true;
    public float PollingInterval => 5f;
    public bool HasConnectivity => _isConnected && !Disabled;
    public bool ForceDisabled { get; set; }
    public bool Disabled => ForceDisabled || IConnectivityServiceExtensions.GlobalForceDisabled;
    public event Action<bool> OnConnectivityChanged;
    
    public  Promise SetHasInternet(bool hasInternet)
    {
        var promise = new Promise();
        
        if (!Disabled)
        {
            _isConnected = hasInternet;
            OnConnectivityChanged?.Invoke(hasInternet);
        }
        
        promise.CompleteSuccess();
        return promise;
    }

    public Promise ReportInternetLoss()
    {
        Debug.LogError("Internet connection lost");
        return SetHasInternet(false);
    }

    public void OnReconnectOnce(Action onReconnection)
    {
        if (HasConnectivity) onReconnection.Invoke();
    }

    public void OnReconnectOnce(ConnectionCallback promise, int order = 0)
    {
        if (HasConnectivity) _ = promise();
    }

    // For testing locally, go to Edit > Project Settings > Player > Other Settings
    // Then set Allow downloads over HTTP = Allowed in development builds
    public IEnumerator PingServer()
    {
        const string url = "http://127.0.0.1:3000/ping";
        using var webRequest = UnityWebRequest.Get(url);
        
        // Send the request asynchronously
        yield return webRequest.SendWebRequest();
        
        if (webRequest.result == UnityWebRequest.Result.Success)
        {
            // Request was successful, and you can handle the response data here.
            var responseText = webRequest.downloadHandler.text;
            Debug.Log("Response: " + responseText);
            // raise connectivity event status to true
            OnConnectivityChanged?.Invoke(!Disabled);
        }
        else
        {
            // Request failed; handle the error.
            Debug.LogError("Request failed: " + webRequest.error);
            // raise connectivity event status to false
            if (!Disabled) OnConnectivityChanged?.Invoke(false);
        }
    }
}

This code demonstrated how to override the existing IConnectivityService

[BeamContextSystem]
public class Registrations
{
	[RegisterBeamableDependencies]
	public static void Build(IDependencyBuilder builder)
	{
		builder.RemoveIfExists<IConnectivityChecker>();
		builder.AddSingleton<IConnectivityChecker, CustomConnectivityService>();
	}
}

Load this code into a scene to see the custom implementation in action.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Beamable;
using Beamable.Api.Connectivity; // add this to docs
using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// Holds data for use in the <see cref="ConnectivityServiceUI"/>.
/// </summary>
[Serializable]
public class ConnectivityServiceData
{
    public List<string> OutputLogs = new List<string>();
    public bool HasConnectivity = false;
}

[Serializable]
public class RefreshedUnityEvent : UnityEvent<ConnectivityServiceData> { }

/// <summary>
/// Demonstrates <see cref="CustomConnectivityService"/>.
/// </summary>
public class CustomConnectivityServiceExample : MonoBehaviour
{
    //  Events  ---------------------------------------
    [HideInInspector]
    public RefreshedUnityEvent OnRefreshed = new();
    
    //  Fields  ---------------------------------------
    private BeamContext _beamContext;
    private ConnectivityServiceData _data = new();
    private IConnectivityService _connectivityService;
    
    //  Properties  -----------------------------------
    public ConnectivityServiceData Data => _data;

    //  Unity Methods  --------------------------------
    protected async void Start()
    {
        Debug.Log($"Start() Instructions...\n\n" +
                  " * Ensure Computer's Internet Is Active\n" +
                  " * Run The Scene\n" +
                  " * See Onscreen UI Show HasConnectivity = true\n" +
                  " * Ensure Computer's Internet Is NOT Active (e.g. Turn off wifi/ethernet)\n" +
                  " * See Onscreen UI Show HasConnectivity = false\n");

        SetupConnectivityService(new CustomConnectivityService());
        await SetupBeamable();
        StartCoroutine(PingCustomServerPolling());
    }

    private IEnumerator PingCustomServerPolling()
    {
        if (_connectivityService is not CustomConnectivityService service) yield break;
        while (true)
        {
            StartCoroutine(service.PingServer());
            yield return new WaitForSeconds(service.PollingInterval);
        }
    }

    //  Methods  --------------------------------------
    private void SetupConnectivityService(IConnectivityService connectivityService) =>
        _connectivityService = connectivityService;

    private async Task SetupBeamable()
    {
        _beamContext = BeamContext.Default;
        await _beamContext.OnReady;

        Debug.Log($"beamContext.PlayerId = {_beamContext.PlayerId}");

        // Observe ConnectivityService Changes
        _connectivityService.OnConnectivityChanged += ConnectivityService_OnConnectivityChanged;
    }
    
    public void ToggleHasInternet()
    {
        _connectivityService.SetHasInternet(!_data.HasConnectivity);
    }

    public void Refresh()
    {
        string refreshLog = $"Refresh() ..." +
                            $"\n * HasConnectivity = {_data.HasConnectivity}" + 
                            $"\n * OutputLogs = {_data.OutputLogs.Count}\n\n";
        
        Debug.Log(refreshLog);
        
        // Send relevant data to the UI for rendering
        OnRefreshed?.Invoke(_data);
    }
    
    //  Event Handlers  -------------------------------
    private void ConnectivityService_OnConnectivityChanged(bool hasConnectivity)
    {
        _data.HasConnectivity = hasConnectivity;
        
        _data.OutputLogs.Add($"HasConnectivity = {_data.HasConnectivity}");
        
        Refresh();
    }
}