[Android] Avoid possible crash using essentials Battery (#18386)

* Avoid crash using Battery from essentials

* Enabled nullable on droid BatteryImplementation

* Update src/Essentials/src/Battery/Battery.android.cs

Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>

* Updated test naming

---------

Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
This commit is contained in:
Javier Suárez 2023-12-01 11:43:59 +01:00 коммит произвёл GitHub
Родитель 62a1b2cb18
Коммит 8546f63eea
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 31 добавлений и 10 удалений

Просмотреть файл

@ -1,3 +1,5 @@
#nullable enable
using System;
using Android.App;
using Android.Content;
@ -8,13 +10,13 @@ namespace Microsoft.Maui.Devices
{
partial class BatteryImplementation : IBattery
{
static PowerManager powerManager;
static PowerManager? powerManager;
static PowerManager PowerManager =>
static PowerManager? PowerManager =>
powerManager ??= Application.Context.GetSystemService(Context.PowerService) as PowerManager;
BatteryBroadcastReceiver batteryReceiver;
EnergySaverBroadcastReceiver powerReceiver;
BatteryBroadcastReceiver? batteryReceiver;
EnergySaverBroadcastReceiver? powerReceiver;
void StartEnergySaverListeners()
{
@ -32,7 +34,7 @@ namespace Microsoft.Maui.Devices
{
System.Diagnostics.Debug.WriteLine("Energy saver receiver already unregistered. Disposing of it.");
}
powerReceiver.Dispose();
powerReceiver?.Dispose();
powerReceiver = null;
}
@ -63,7 +65,7 @@ namespace Microsoft.Maui.Devices
{
System.Diagnostics.Debug.WriteLine("Battery receiver already unregistered. Disposing of it.");
}
batteryReceiver.Dispose();
batteryReceiver?.Dispose();
batteryReceiver = null;
}
@ -76,6 +78,9 @@ namespace Microsoft.Maui.Devices
using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
using (var battery = PlatformUtils.RegisterBroadcastReceiver(null, filter, false))
{
if(battery is null)
return -1; // Unknown
var level = battery.GetIntExtra(BatteryManager.ExtraLevel, -1);
var scale = battery.GetIntExtra(BatteryManager.ExtraScale, -1);
@ -96,6 +101,9 @@ namespace Microsoft.Maui.Devices
using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
using (var battery = PlatformUtils.RegisterBroadcastReceiver(null, filter, false))
{
if (battery is null)
return BatteryState.Unknown;
var status = battery.GetIntExtra(BatteryManager.ExtraStatus, -1);
switch (status)
{
@ -123,6 +131,9 @@ namespace Microsoft.Maui.Devices
using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
using (var battery = PlatformUtils.RegisterBroadcastReceiver(null, filter, false))
{
if (battery is null)
return BatteryPowerSource.Unknown;
var chargePlug = battery.GetIntExtra(BatteryManager.ExtraPlugged, -1);
if (chargePlug == (int)BatteryPlugged.Usb)
@ -143,7 +154,7 @@ namespace Microsoft.Maui.Devices
[BroadcastReceiver(Enabled = true, Exported = false, Label = "Essentials Battery Broadcast Receiver")]
class BatteryBroadcastReceiver : BroadcastReceiver
{
Action onChanged;
readonly Action? onChanged;
public BatteryBroadcastReceiver()
{
@ -152,14 +163,14 @@ namespace Microsoft.Maui.Devices
public BatteryBroadcastReceiver(Action onChanged) =>
this.onChanged = onChanged;
public override void OnReceive(Context context, Intent intent) =>
public override void OnReceive(Context? context, Intent? intent) =>
onChanged?.Invoke();
}
[BroadcastReceiver(Enabled = true, Exported = false, Label = "Essentials Energy Saver Broadcast Receiver")]
class EnergySaverBroadcastReceiver : BroadcastReceiver
{
Action onChanged;
readonly Action? onChanged;
public EnergySaverBroadcastReceiver()
{
@ -168,7 +179,7 @@ namespace Microsoft.Maui.Devices
public EnergySaverBroadcastReceiver(Action onChanged) =>
this.onChanged = onChanged;
public override void OnReceive(Context context, Intent intent) =>
public override void OnReceive(Context? context, Intent? intent) =>
onChanged?.Invoke();
}
}

Просмотреть файл

@ -55,6 +55,16 @@ namespace Microsoft.Maui.Essentials.DeviceTests
Assert.Equal(EnergySaverStatus.Off, Battery.EnergySaverStatus);
}
[Fact]
public void Unsubscribe_BatteryInfoChanged_Does_Not_Crash()
{
// TODO: the test runner app (UI version) should do this, until then...
if (!HardwareSupport.HasBattery)
return;
Battery.BatteryInfoChanged -= (sender, args) => { };
}
[Fact]
public async Task EnergySaverStatusChanged_Does_Not_Crash()
{