-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Connectivity.shared.cs
163 lines (143 loc) · 5.67 KB
/
Connectivity.shared.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Networking;
namespace Microsoft.Maui.Networking
{
/// <summary>
/// The Connectivity API lets you monitor for changes in the device's network conditions, check the current network access, and determine how it is currently connected.
/// </summary>
public interface IConnectivity
{
/// <summary>
/// Gets the active connectivity types for the device.
/// </summary>
IEnumerable<ConnectionProfile> ConnectionProfiles { get; }
/// <summary>
/// Gets the current state of network access.
/// </summary>
NetworkAccess NetworkAccess { get; }
/// <summary>
/// Occurs when network access or profile has changed.
/// </summary>
event EventHandler<ConnectivityChangedEventArgs> ConnectivityChanged;
}
#nullable enable
/// <summary>
/// The Connectivity APIs lets you monitor for changes in the device's network conditions, check the current network access, and how it is currently connected.
/// </summary>
public static class Connectivity
{
/// <summary>
/// Gets the current state of network access.
/// </summary>
/// <remarks>
/// <para>Even when <see cref="NetworkAccess.Internet"/> is returned, full internet access is not guaranteed.</para>
/// <para>Can throw <see cref="PermissionException"/> on Android if <c>ACCESS_NETWORK_STATE</c> is not set in manifest.</para>
/// </remarks>
public static NetworkAccess NetworkAccess => Current.NetworkAccess;
/// <summary>
/// Gets the active connectivity types for the device.
/// </summary>
/// <remarks>Can throw <see cref="PermissionException"/> on Android if <c>ACCESS_NETWORK_STATE</c> is not set in manifest.</remarks>
public static IEnumerable<ConnectionProfile> ConnectionProfiles => Current.ConnectionProfiles.Distinct();
/// <summary>
/// Occurs when network access or profile has changed.
/// </summary>
/// <remarks>Can throw <see cref="PermissionException"/> on Android if <c>ACCESS_NETWORK_STATE</c> is not set in manifest.</remarks>
public static event EventHandler<ConnectivityChangedEventArgs> ConnectivityChanged
{
add => Current.ConnectivityChanged += value;
remove => Current.ConnectivityChanged -= value;
}
static IConnectivity? currentImplementation;
/// <summary>
/// Provides the default implementation for static usage of this API.
/// </summary>
public static IConnectivity Current =>
currentImplementation ??= new ConnectivityImplementation();
internal static void SetCurrent(IConnectivity? implementation) =>
currentImplementation = implementation;
}
#nullable disable
partial class ConnectivityImplementation : IConnectivity
{
event EventHandler<ConnectivityChangedEventArgs> ConnectivityChangedInternal;
// a cache so that events aren't fired unnecessarily
// this is mainly an issue on Android, but we can stiil do this everywhere
NetworkAccess currentAccess;
List<ConnectionProfile> currentProfiles;
public event EventHandler<ConnectivityChangedEventArgs> ConnectivityChanged
{
add
{
if (ConnectivityChangedInternal is null)
{
SetCurrent();
StartListeners();
}
ConnectivityChangedInternal += value;
}
remove
{
ConnectivityChangedInternal -= value;
if (ConnectivityChangedInternal is null)
StopListeners();
}
}
void SetCurrent()
{
currentAccess = NetworkAccess;
currentProfiles = new List<ConnectionProfile>(ConnectionProfiles);
}
void OnConnectivityChanged(NetworkAccess access, IEnumerable<ConnectionProfile> profiles)
=> OnConnectivityChanged(new ConnectivityChangedEventArgs(access, profiles));
void OnConnectivityChanged()
=> OnConnectivityChanged(NetworkAccess, ConnectionProfiles);
void OnConnectivityChanged(ConnectivityChangedEventArgs e)
{
if (currentAccess != e.NetworkAccess || !currentProfiles.SequenceEqual(e.ConnectionProfiles))
{
SetCurrent();
MainThread.BeginInvokeOnMainThread(() => ConnectivityChangedInternal?.Invoke(null, e));
}
}
}
/// <summary>
/// The current connectivity information from the change event.
/// </summary>
public class ConnectivityChangedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="ConnectivityChangedEventArgs"/> class.
/// </summary>
/// <param name="access">The current access of the network.</param>
/// <param name="connectionProfiles">The connection profiles changing correspondingto this event.</param>
public ConnectivityChangedEventArgs(NetworkAccess access, IEnumerable<ConnectionProfile> connectionProfiles)
{
NetworkAccess = access;
ConnectionProfiles = connectionProfiles;
}
/// <summary>
/// Gets the current state of network access.
/// </summary>
/// <remarks>
/// <para>Even when <see cref="NetworkAccess.Internet"/> is returned, full internet access is not guaranteed.</para>
/// <para>Can throw <see cref="PermissionException"/> on Android if <c>ACCESS_NETWORK_STATE</c> is not set in manifest.</para>
/// </remarks>
public NetworkAccess NetworkAccess { get; }
/// <summary>
/// Gets the active connectivity profiles for the device.
/// </summary>
public IEnumerable<ConnectionProfile> ConnectionProfiles { get; }
/// <summary>
/// Returns a string representation of the current values of <see cref="ConnectivityChangedEventArgs"/>.
/// </summary>
/// <returns>A string representation of this instance in the format of <c>NetworkAccess: {value}, ConnectionProfiles: [{value1}, {value2}]</c>.</returns>
public override string ToString() =>
$"{nameof(NetworkAccess)}: {NetworkAccess}, " +
$"{nameof(ConnectionProfiles)}: [{string.Join(", ", ConnectionProfiles)}]";
}
}