From 0175072fb6730ebdbbc75cf931be07607bf02796 Mon Sep 17 00:00:00 2001 From: James Montemagno Date: Thu, 3 Dec 2020 11:01:00 -0800 Subject: [PATCH] Implement the new ConnectivityManager.NetworkCallback for N+ --- .../Connectivity/Connectivity.android.cs | 74 ++++++++++++++++++- .../Platform/Platform.android.cs | 2 + 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/Xamarin.Essentials/Connectivity/Connectivity.android.cs b/Xamarin.Essentials/Connectivity/Connectivity.android.cs index 40909ea86..21123f6c2 100644 --- a/Xamarin.Essentials/Connectivity/Connectivity.android.cs +++ b/Xamarin.Essentials/Connectivity/Connectivity.android.cs @@ -11,22 +11,46 @@ namespace Xamarin.Essentials public partial class Connectivity { static ConnectivityBroadcastReceiver conectivityReceiver; + static Intent connectivityIntent = new Intent(Platform.EssentialsConnectivityChanged); + static EssentialsNetworkCallback networkCallback; static void StartListeners() { Permissions.EnsureDeclared(); - conectivityReceiver = new ConnectivityBroadcastReceiver(OnConnectivityChanged); + var filter = new IntentFilter(); + if (Platform.HasApiLevelN) + { + RegisterNetworkCallback(); + filter.AddAction(Platform.EssentialsConnectivityChanged); + } + else + { #pragma warning disable CS0618 // Type or member is obsolete - Platform.AppContext.RegisterReceiver(conectivityReceiver, new IntentFilter(ConnectivityManager.ConnectivityAction)); + filter.AddAction(ConnectivityManager.ConnectivityAction); #pragma warning restore CS0618 // Type or member is obsolete + } + + conectivityReceiver = new ConnectivityBroadcastReceiver(OnConnectivityChanged); + + Platform.AppContext.RegisterReceiver(conectivityReceiver, filter); } static void StopListeners() { if (conectivityReceiver == null) return; + + try + { + UnregisterNetworkCallback(); + } + catch + { + Debug.WriteLine("Connectivity receiver already unregistered. Disposing of it."); + } + try { Platform.AppContext.UnregisterReceiver(conectivityReceiver); @@ -39,6 +63,50 @@ static void StopListeners() conectivityReceiver = null; } + static void RegisterNetworkCallback() + { + if (!Platform.HasApiLevelN) + return; + + var manager = Platform.ConnectivityManager; + if (manager == null) + return; + + var request = new NetworkRequest.Builder().Build(); + networkCallback = new EssentialsNetworkCallback(); + manager.RegisterNetworkCallback(request, networkCallback); + } + + static void UnregisterNetworkCallback() + { + if (!Platform.HasApiLevelN) + return; + + var manager = Platform.ConnectivityManager; + if (manager == null || networkCallback == null) + return; + + manager.UnregisterNetworkCallback(networkCallback); + + networkCallback?.Dispose(); + networkCallback = null; + } + + class EssentialsNetworkCallback : ConnectivityManager.NetworkCallback + { + public override void OnAvailable(Network network) => Platform.AppContext.SendBroadcast(connectivityIntent); + + public override void OnLost(Network network) => Platform.AppContext.SendBroadcast(connectivityIntent); + + public override void OnCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) => Platform.AppContext.SendBroadcast(connectivityIntent); + + public override void OnUnavailable() => Platform.AppContext.SendBroadcast(connectivityIntent); + + public override void OnLinkPropertiesChanged(Network network, LinkProperties linkProperties) => Platform.AppContext.SendBroadcast(connectivityIntent); + + public override void OnLosing(Network network, int maxMsToLive) => Platform.AppContext.SendBroadcast(connectivityIntent); + } + static NetworkAccess IsBetterAccess(NetworkAccess currentAccess, NetworkAccess newAccess) => newAccess > currentAccess ? newAccess : currentAccess; @@ -245,7 +313,7 @@ public ConnectivityBroadcastReceiver(Action onChanged) => public override async void OnReceive(Context context, Intent intent) { #pragma warning disable CS0618 // Type or member is obsolete - if (intent.Action != ConnectivityManager.ConnectivityAction) + if (intent.Action != ConnectivityManager.ConnectivityAction && intent.Action != Platform.EssentialsConnectivityChanged) #pragma warning restore CS0618 // Type or member is obsolete return; diff --git a/Xamarin.Essentials/Platform/Platform.android.cs b/Xamarin.Essentials/Platform/Platform.android.cs index 12ea7e397..074da7c72 100644 --- a/Xamarin.Essentials/Platform/Platform.android.cs +++ b/Xamarin.Essentials/Platform/Platform.android.cs @@ -27,6 +27,8 @@ public static partial class Platform public static event EventHandler ActivityStateChanged; + internal const string EssentialsConnectivityChanged = "com.xamarin.essentials.ESSENTIALS_CONNECTIVITY_CHANGED"; + internal const int requestCodeFilePicker = 11001; internal const int requestCodeMediaPicker = 11002; internal const int requestCodeMediaCapture = 11003;