-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Battery.shared.cs
executable file
·310 lines (261 loc) · 9.07 KB
/
Battery.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#nullable enable
using System;
namespace Microsoft.Maui.Devices
{
/// <summary>
/// Methods and properties for battery and charging information of the device.
/// </summary>
/// <remarks>
/// <para>Platform specific remarks:</para>
/// <para>- Android: <c>Battery_Stats</c> permission must be set in manifest.</para>
/// <para>- iOS: Simulator will not return battery information, must be run on device.</para>
/// <para>- Windows: None.</para>
/// </remarks>
public interface IBattery
{
/// <summary>
/// Gets the current charge level of the device from 0.0 to 1.0.
/// </summary>
/// <remarks>Returns -1 if no battery exists.</remarks>
double ChargeLevel { get; }
/// <summary>
/// Gets the charging state of the device.
/// </summary>
BatteryState State { get; }
/// <summary>
/// Gets the current power source for the device.
/// </summary>
BatteryPowerSource PowerSource { get; }
/// <summary>
/// Gets the current energy saver status of the device.
/// </summary>
EnergySaverStatus EnergySaverStatus { get; }
/// <summary>
/// Occurs when battery properties change.
/// </summary>
event EventHandler<BatteryInfoChangedEventArgs> BatteryInfoChanged;
/// <summary>
/// Occurs when the energy saver status changes.
/// </summary>
event EventHandler<EnergySaverStatusChangedEventArgs> EnergySaverStatusChanged;
}
/// <summary>
/// Methods and properties for battery and charging information of the device.
/// </summary>
public static class Battery
{
/// <summary>
/// Gets the current charge level of the device from 0.0 to 1.0.
/// </summary>
/// <remarks>Returns -1 if no battery exists.</remarks>
public static double ChargeLevel => Default.ChargeLevel;
/// <summary>
/// Gets the charging state of the device.
/// </summary>
public static BatteryState State => Default.State;
/// <summary>
/// Gets the current power source for the device.
/// </summary>
public static BatteryPowerSource PowerSource => Default.PowerSource;
/// <summary>
/// Gets the current energy saver status of the device.
/// </summary>
public static EnergySaverStatus EnergySaverStatus => Default.EnergySaverStatus;
/// <summary>
/// Event trigger when battery properties have changed.
/// </summary>
public static event EventHandler<BatteryInfoChangedEventArgs> BatteryInfoChanged
{
add => Default.BatteryInfoChanged += value;
remove => Default.BatteryInfoChanged -= value;
}
/// <summary>
/// Occurs when the energy saver status changes.
/// </summary>
public static event EventHandler<EnergySaverStatusChangedEventArgs> EnergySaverStatusChanged
{
add => Default.EnergySaverStatusChanged += value;
remove => Default.EnergySaverStatusChanged -= value;
}
static IBattery? defaultImplementation;
/// <summary>
/// Provides the default implementation for static usage of this API.
/// </summary>s
public static IBattery Default =>
defaultImplementation ??= new BatteryImplementation();
internal static void SetDefault(IBattery? implementation) =>
defaultImplementation = implementation;
}
partial class BatteryImplementation : IBattery
{
event EventHandler<BatteryInfoChangedEventArgs>? BatteryInfoChangedInternal;
event EventHandler<EnergySaverStatusChangedEventArgs>? EnergySaverStatusChangedInternal;
public event EventHandler<BatteryInfoChangedEventArgs> BatteryInfoChanged
{
add
{
if (BatteryInfoChangedInternal == null)
StartBatteryListeners();
BatteryInfoChangedInternal += value;
}
remove
{
BatteryInfoChangedInternal -= value;
if (BatteryInfoChangedInternal == null)
StopBatteryListeners();
}
}
public event EventHandler<EnergySaverStatusChangedEventArgs> EnergySaverStatusChanged
{
add
{
if (EnergySaverStatusChangedInternal == null)
StartEnergySaverListeners();
EnergySaverStatusChangedInternal += value;
}
remove
{
EnergySaverStatusChangedInternal -= value;
if (EnergySaverStatusChangedInternal == null)
StopEnergySaverListeners();
}
}
// a cache so that events aren't fired unnecessarily
// this is mainly an issue on Android, but we can stiil do this everywhere
static double currentLevel;
static BatteryPowerSource currentSource;
static BatteryState currentState;
void SetCurrent()
{
currentLevel = ChargeLevel;
currentSource = PowerSource;
currentState = State;
}
void OnBatteryInfoChanged(double level, BatteryState state, BatteryPowerSource source)
=> OnBatteryInfoChanged(new BatteryInfoChangedEventArgs(level, state, source));
void OnBatteryInfoChanged()
=> OnBatteryInfoChanged(ChargeLevel, State, PowerSource);
void OnBatteryInfoChanged(BatteryInfoChangedEventArgs e)
{
if (currentLevel != e.ChargeLevel || currentSource != e.PowerSource || currentState != e.State)
{
SetCurrent();
BatteryInfoChangedInternal?.Invoke(null, e);
}
}
void OnEnergySaverChanged()
=> OnEnergySaverChanged(EnergySaverStatus);
void OnEnergySaverChanged(EnergySaverStatus saverStatus)
=> OnEnergySaverChanged(new EnergySaverStatusChangedEventArgs(saverStatus));
void OnEnergySaverChanged(EnergySaverStatusChangedEventArgs e)
=> EnergySaverStatusChangedInternal?.Invoke(null, e);
}
/// <summary>
/// Describes possible states of the battery.
/// </summary>
public enum BatteryState
{
/// <summary>Battery state could not be determined.</summary>
Unknown = 0,
/// <summary>Battery is actively being charged by a power source.</summary>
Charging = 1,
/// <summary>Battery is not plugged in and discharging.</summary>
Discharging = 2,
/// <summary>Battery is full.</summary>
Full = 3,
/// <summary>Battery is not charging or discharging, but in an inbetween state.</summary>
NotCharging = 4,
/// <summary>Battery does not exist on the device.</summary>
NotPresent = 5
}
/// <summary>
/// Enumerates power sources with which the device and battery can be powered or charged.
/// </summary>
public enum BatteryPowerSource
{
/// <summary>Power source can not be determined.</summary>
Unknown = 0,
/// <summary>Power source is the battery and is currently not being charged.</summary>
Battery = 1,
/// <summary>Power source is an AC Charger.</summary>
AC = 2,
/// <summary>Power source is a USB port.</summary>
Usb = 3,
/// <summary>Power source is wireless.</summary>
Wireless = 4
}
/// <summary>
/// Enumerates states that the energy saver van have on the device.
/// </summary>
public enum EnergySaverStatus
{
/// <summary>Status of energy saving is unknown.</summary>
Unknown = 0,
/// <summary>Energy saving is on.</summary>
On = 1,
/// <summary>Energy saving is off.</summary>
Off = 2
}
/// <summary>
/// Event arguments containing the current reading of <see cref="IBattery"/>.
/// </summary>
public class BatteryInfoChangedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="BatteryInfoChangedEventArgs"/> class.
/// </summary>
/// <param name="level">The current level of the battery.</param>
/// <param name="state">The state of the battery.</param>
/// <param name="source">The source of the battery.</param>
public BatteryInfoChangedEventArgs(double level, BatteryState state, BatteryPowerSource source)
{
ChargeLevel = level;
State = state;
PowerSource = source;
}
/// <summary>
/// Gets the current charge level of the device from 0.0 to 1.0.
/// </summary>
public double ChargeLevel { get; }
/// <summary>
/// Gets the charging state of the device.
/// </summary>
public BatteryState State { get; }
/// <summary>
/// Gets the current power source for the device.
/// </summary>
public BatteryPowerSource PowerSource { get; }
/// <summary>
/// Returns a string representation of this instance of <see cref="BatteryInfoChangedEventArgs"/>.
/// </summary>
/// <returns>A string representation of this instance in the format of <c>ChargeLevel: {value}, State: {value}, PowerSource: {value}</c>.</returns>
public override string ToString() =>
$"{nameof(ChargeLevel)}: {ChargeLevel.ToString()}, " +
$"{nameof(State)}: {State}, " +
$"{nameof(PowerSource)}: {PowerSource}";
}
/// <summary>
/// Event arguments when the energy saver status changes.
/// </summary>
public class EnergySaverStatusChangedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="EnergySaverStatusChangedEventArgs"/> class.
/// </summary>
/// <param name="saverStatus">The current status of the event.</param>
public EnergySaverStatusChangedEventArgs(EnergySaverStatus saverStatus)
{
EnergySaverStatus = saverStatus;
}
/// <summary>
/// Gets the current status of energy saver mode.
/// </summary>
public EnergySaverStatus EnergySaverStatus { get; }
/// <summary>
/// Returns a string representation of this instance of <see cref="EnergySaverStatusChangedEventArgs"/>.
/// </summary>
/// <returns>A string representation of this instance in the format of <c>EnergySaverStatus: {value}</c>.</returns>
public override string ToString() =>
$"{nameof(EnergySaverStatus)}: {EnergySaverStatus}";
}
}