// Copyright (c) Microsoft Corporation. All rights reserved. // Portions derived from React Native: // Copyright (c) 2015-present, Facebook, Inc. // Licensed under the MIT License. using Newtonsoft.Json.Linq; using ReactNative.Bridge; using ReactNative.Modules.Core; using Windows.Networking.Connectivity; namespace ReactNativeCommunity.NetInfo { /// /// Module that monitors and provides information about the connectivity /// state of the device. /// public class RNCNetInfoModule : ReactContextNativeModuleBase, ILifecycleEventListener { // These constants need to match the strings defined in types.ts private const string CONNECTION_TYPE_CELLULAR = "cellular"; private const string CONNECTION_TYPE_ETHERNET = "ethernet"; private const string CONNECTION_TYPE_NONE = "none"; private const string CONNECTION_TYPE_UNKNOWN = "unknown"; private const string CONNECTION_TYPE_WIFI = "wifi"; private const string CONNECTION_TYPE_OTHER = "other"; private const string CELLULAR_GENERATION_2G = "2g"; private const string CELLULAR_GENERATION_3G = "3g"; private const string CELLULAR_GENERATION_4G = "4g"; private const string CELLULAR_GENERATION_NONE = null; private const string CELLULAR_GENERATION_UNKNOWN = null; private readonly INetworkInformation _networkInfo; /// /// Instantiates the . /// /// The React context. public RNCNetInfoModule(ReactContext reactContext) : this(new DefaultNetworkInformation(), reactContext) { } /// /// Instantiates the . /// /// The network information. /// The React context. public RNCNetInfoModule(INetworkInformation networkInfo, ReactContext reactContext) : base(reactContext) { _networkInfo = networkInfo; } /// /// Gets the name of the native module. /// public override string Name { get { return "RNCNetInfo"; } } /// /// Gets the current connectivity state of the app. /// /// The interface from which to obtain the information (not currently supported) /// A promise to resolve the request. [ReactMethod] public void getCurrentState(String requestedInterface, IPromise promise) { promise.Resolve(CreateConnectivityEventMap()); } /// /// Called when the application host is destroyed. /// public void OnDestroy() { } /// /// Called when the application host is resumed. /// public void OnResume() { _networkInfo.Start(); _networkInfo.NetworkStatusChanged += OnStatusChanged; } /// /// Called when the application host is suspended. /// public void OnSuspend() { _networkInfo.NetworkStatusChanged -= OnStatusChanged; _networkInfo.Stop(); } /// /// Called when the React instance is initialized. /// public override void Initialize() { Context.AddLifecycleEventListener(this); } private JObject CreateConnectivityEventMap() { var eventMap = new JObject(); // Add the connection type information var type = GetConnectivityType(); eventMap.Add("type", type); // Add the connection state information var isConnected = GetIsConnected(); eventMap.Add("isConnected", isConnected); // Add the details, if there are any JObject details = null; if (isConnected) { details = new JObject(); var isConnectionExpensive = GetIsConnectionExpensive(); details.Add("isConnectionExpensive", isConnectionExpensive); if (type == CONNECTION_TYPE_CELLULAR) { var cellularGeneration = GetCellularGeneration(); details.Add("cellularGeneration", cellularGeneration); } } eventMap.Add("details", details); return eventMap; } private string GetConnectivityType() { var profile = _networkInfo.GetInternetConnectionProfile(); if (profile == null) { return CONNECTION_TYPE_NONE; } switch (profile.ConnectionType) { case NetworkConnectionType.Unknown: return CONNECTION_TYPE_UNKNOWN; case NetworkConnectionType.None: return CONNECTION_TYPE_NONE; case NetworkConnectionType.Cellular: return CONNECTION_TYPE_CELLULAR; case NetworkConnectionType.Ethernet: return CONNECTION_TYPE_ETHERNET; case NetworkConnectionType.Wifi: return CONNECTION_TYPE_WIFI; case NetworkConnectionType.Other: return CONNECTION_TYPE_OTHER; default: return CONNECTION_TYPE_UNKNOWN; } } private string GetCellularGeneration() { var profile = _networkInfo.GetInternetConnectionProfile(); if (profile == null) { return CELLULAR_GENERATION_NONE; } switch (profile.CellularGeneration) { case CellularGeneration.Unknown: return CELLULAR_GENERATION_UNKNOWN; case CellularGeneration.None: return CELLULAR_GENERATION_NONE; case CellularGeneration.Generation2: return CELLULAR_GENERATION_2G; case CellularGeneration.Generation3: return CELLULAR_GENERATION_3G; case CellularGeneration.Generation4: return CELLULAR_GENERATION_4G; default: return CELLULAR_GENERATION_UNKNOWN; } } private bool GetIsConnected() { var profile = _networkInfo.GetInternetConnectionProfile(); return profile != null && profile.ConnectivityLevel != NetworkConnectivityLevel.None; } private bool GetIsConnectionExpensive() { var profile = _networkInfo.GetInternetConnectionProfile(); if (profile == null) { return false; } var connectionCost = profile.ConnectionCost; return connectionCost == NetworkCostType.Fixed || connectionCost == NetworkCostType.Variable; } private void OnStatusChanged(object ignored) { var connectivity = CreateConnectivityEventMap(); Context.GetJavaScriptModule() .emit("netInfo.networkStatusDidChange", CreateConnectivityEventMap()); } } }