Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

GH-583: [api-fix] Power / Battery #591

Merged
merged 3 commits into from
Nov 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions DeviceTests/DeviceTests.Shared/Battery_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,11 @@ public void Charge_Power()

Assert.NotEqual(BatteryPowerSource.Unknown, Battery.PowerSource);
}

[Fact]
public void App_Is_Not_Lower_Power_mode()
{
Assert.Equal(EnergySaverStatus.Off, Battery.EnergySaverStatus);
}
}
}
14 changes: 0 additions & 14 deletions DeviceTests/DeviceTests.Shared/Power_Tests.cs

This file was deleted.

1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ The following cross-platform APIs are available in Xamarin.Essentials:
* [Open Browser](https://docs.microsoft.com/xamarin/essentials/open-browser)
* [Orientation Sensor](https://docs.microsoft.com/en-us/xamarin/essentials/orientation-sensor)
* [Phone Dialer](https://docs.microsoft.com/xamarin/essentials/phone-dialer)
* [Power](https://docs.microsoft.com/en-us/xamarin/essentials/power)
* [Preferences](https://docs.microsoft.com/xamarin/essentials/preferences)
* [Screen Lock](https://docs.microsoft.com/xamarin/essentials/screen-lock)
* [Secure Storage](https://docs.microsoft.com/xamarin/essentials/secure-storage)
Expand Down
6 changes: 3 additions & 3 deletions Samples/Samples/ViewModel/BatteryViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ public BatteryViewModel()

public BatteryPowerSource PowerSource => Battery.PowerSource;

public EnergySaverStatus EnergySaverStatus => Power.EnergySaverStatus;
public EnergySaverStatus EnergySaverStatus => Battery.EnergySaverStatus;

public override void OnAppearing()
{
base.OnAppearing();

Battery.BatteryChanged += OnBatteryChanged;
Power.EnergySaverStatusChanged += OnEnergySaverStatusChanged;
Battery.EnergySaverStatusChanged += OnEnergySaverStatusChanged;
}

public override void OnDisappearing()
{
Battery.BatteryChanged -= OnBatteryChanged;
Power.EnergySaverStatusChanged -= OnEnergySaverStatusChanged;
Battery.EnergySaverStatusChanged -= OnEnergySaverStatusChanged;

base.OnDisappearing();
}
Expand Down
60 changes: 57 additions & 3 deletions Xamarin.Essentials/Battery/Battery.android.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,51 @@
using System;
using Android.Content;
using Android.OS;
using Debug = System.Diagnostics.Debug;

namespace Xamarin.Essentials
{
public static partial class Battery
{
static BatteryBroadcastReceiver batteryReceiver;
static EnergySaverBroadcastReceiver powerReceiver;

static void StartEnergySaverListeners()
{
if (!Platform.HasApiLevel(BuildVersionCodes.Lollipop))
return;

powerReceiver = new EnergySaverBroadcastReceiver(OnEnergySaverChanged);
Platform.AppContext.RegisterReceiver(powerReceiver, new IntentFilter(PowerManager.ActionPowerSaveModeChanged));
}

static void StopEnergySaverListeners()
{
if (!Platform.HasApiLevel(BuildVersionCodes.Lollipop))
return;

try
{
Platform.AppContext.UnregisterReceiver(powerReceiver);
}
catch (Java.Lang.IllegalArgumentException)
{
System.Diagnostics.Debug.WriteLine("Energy saver receiver already unregistered. Disposing of it.");
}
powerReceiver.Dispose();
powerReceiver = null;
}

static EnergySaverStatus PlatformEnergySaverStatus
{
get
{
var status = false;
if (Platform.HasApiLevel(BuildVersionCodes.Lollipop))
status = Platform.PowerManager?.IsPowerSaveMode ?? false;

return status ? EnergySaverStatus.On : EnergySaverStatus.Off;
}
}

static void StartBatteryListeners()
{
Expand All @@ -25,7 +63,7 @@ static void StopBatteryListeners()
}
catch (Java.Lang.IllegalArgumentException)
{
Debug.WriteLine("Battery receiver already unregistered. Disposing of it.");
System.Diagnostics.Debug.WriteLine("Battery receiver already unregistered. Disposing of it.");
}
batteryReceiver.Dispose();
batteryReceiver = null;
Expand All @@ -44,7 +82,7 @@ static double PlatformChargeLevel
var scale = battery.GetIntExtra(BatteryManager.ExtraScale, -1);

if (scale <= 0)
return -1;
return 1.0;

return (double)level / (double)scale;
}
Expand Down Expand Up @@ -119,4 +157,20 @@ public BatteryBroadcastReceiver(Action onChanged) =>
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;

public EnergySaverBroadcastReceiver()
{
}

public EnergySaverBroadcastReceiver(Action onChanged) =>
this.onChanged = onChanged;

public override void OnReceive(Context context, Intent intent) =>
onChanged?.Invoke();
}
}
18 changes: 18 additions & 0 deletions Xamarin.Essentials/Battery/Battery.ios.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ public static partial class Battery
{
static NSObject levelObserver;
static NSObject stateObserver;
static NSObject saverStatusObserver;

static void StartEnergySaverListeners()
{
saverStatusObserver = NSNotificationCenter.DefaultCenter.AddObserver(NSProcessInfo.PowerStateDidChangeNotification, PowerChangedNotification);
}

static void StopEnergySaverListeners()
{
saverStatusObserver?.Dispose();
saverStatusObserver = null;
}

static void PowerChangedNotification(NSNotification notification)
=> MainThread.BeginInvokeOnMainThread(OnEnergySaverChanged);

static EnergySaverStatus PlatformEnergySaverStatus =>
NSProcessInfo.ProcessInfo?.LowPowerModeEnabled == true ? EnergySaverStatus.On : EnergySaverStatus.Off;

static void StartBatteryListeners()
{
Expand Down
9 changes: 9 additions & 0 deletions Xamarin.Essentials/Battery/Battery.netstandard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,14 @@ static void StopBatteryListeners() =>

static BatteryPowerSource PlatformPowerSource =>
throw new NotImplementedInReferenceAssemblyException();

static void StartEnergySaverListeners() =>
throw new NotImplementedInReferenceAssemblyException();

static void StopEnergySaverListeners() =>
throw new NotImplementedInReferenceAssemblyException();

static EnergySaverStatus PlatformEnergySaverStatus =>
throw new NotImplementedInReferenceAssemblyException();
}
}
56 changes: 56 additions & 0 deletions Xamarin.Essentials/Battery/Battery.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public static partial class Battery
{
static event EventHandler<BatteryChangedEventArgs> BatteryChangedInternal;

static event EventHandler<EnergySaverStatusChangedEventArgs> EnergySaverStatusChangedInternal;

// 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;
Expand All @@ -18,6 +20,8 @@ public static partial class Battery

public static BatteryPowerSource PowerSource => PlatformPowerSource;

public static EnergySaverStatus EnergySaverStatus => PlatformEnergySaverStatus;

public static event EventHandler<BatteryChangedEventArgs> BatteryChanged
{
add
Expand All @@ -44,6 +48,29 @@ public static event EventHandler<BatteryChangedEventArgs> BatteryChanged
}
}

public static event EventHandler<EnergySaverStatusChangedEventArgs> EnergySaverStatusChanged
{
add
{
var wasRunning = EnergySaverStatusChangedInternal != null;

EnergySaverStatusChangedInternal += value;

if (!wasRunning && EnergySaverStatusChangedInternal != null)
StartEnergySaverListeners();
}

remove
{
var wasRunning = EnergySaverStatusChangedInternal != null;

EnergySaverStatusChangedInternal -= value;

if (wasRunning && EnergySaverStatusChangedInternal == null)
StopEnergySaverListeners();
}
}

static void SetCurrent()
{
currentLevel = Battery.ChargeLevel;
Expand All @@ -65,6 +92,15 @@ static void OnBatteryChanged(BatteryChangedEventArgs e)
BatteryChangedInternal?.Invoke(null, e);
}
}

static void OnEnergySaverChanged()
=> OnEnergySaverChanged(EnergySaverStatus);

static void OnEnergySaverChanged(EnergySaverStatus saverStatus)
=> OnEnergySaverChanged(new EnergySaverStatusChangedEventArgs(saverStatus));

static void OnEnergySaverChanged(EnergySaverStatusChangedEventArgs e)
=> EnergySaverStatusChangedInternal?.Invoke(null, e);
}

public enum BatteryState
Expand All @@ -86,6 +122,13 @@ public enum BatteryPowerSource
Wireless
}

public enum EnergySaverStatus
{
Unknown,
On,
Off
}

public class BatteryChangedEventArgs : EventArgs
{
internal BatteryChangedEventArgs(double level, BatteryState state, BatteryPowerSource source)
Expand All @@ -106,4 +149,17 @@ public override string ToString() =>
$"{nameof(State)}: {State}, " +
$"{nameof(PowerSource)}: {PowerSource}";
}

public class EnergySaverStatusChangedEventArgs : EventArgs
{
internal EnergySaverStatusChangedEventArgs(EnergySaverStatus saverStatus)
{
EnergySaverStatus = saverStatus;
}

public EnergySaverStatus EnergySaverStatus { get; }

public override string ToString() =>
$"{nameof(EnergySaverStatus)}: {EnergySaverStatus}";
}
}
26 changes: 20 additions & 6 deletions Xamarin.Essentials/Battery/Battery.uwp.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
namespace Xamarin.Essentials
using Windows.System.Power;

namespace Xamarin.Essentials
{
public static partial class Battery
{
static void StartEnergySaverListeners() =>
PowerManager.EnergySaverStatusChanged += ReportEnergySaverUpdated;

static void StopEnergySaverListeners() =>
PowerManager.EnergySaverStatusChanged -= ReportEnergySaverUpdated;

static void ReportEnergySaverUpdated(object sender, object e)
=> MainThread.BeginInvokeOnMainThread(OnEnergySaverChanged);

static void StartBatteryListeners() =>
DefaultBattery.ReportUpdated += ReportUpdated;

Expand All @@ -19,7 +30,7 @@ static double PlatformChargeLevel
get
{
var finalReport = DefaultBattery.GetReport();
var finalPercent = -1.0;
var finalPercent = 1.0;

var remaining = finalReport.RemainingCapacityInMilliwattHours;
var full = finalReport.FullChargeCapacityInMilliwattHours;
Expand All @@ -39,15 +50,15 @@ static BatteryState PlatformState

switch (report.Status)
{
case Windows.System.Power.BatteryStatus.Charging:
case BatteryStatus.Charging:
return BatteryState.Charging;
case Windows.System.Power.BatteryStatus.Discharging:
case BatteryStatus.Discharging:
return BatteryState.Discharging;
case Windows.System.Power.BatteryStatus.Idle:
case BatteryStatus.Idle:
if (ChargeLevel >= 1.0)
return BatteryState.Full;
return BatteryState.NotCharging;
case Windows.System.Power.BatteryStatus.NotPresent:
case BatteryStatus.NotPresent:
return BatteryState.NotPresent;
}

Expand Down Expand Up @@ -75,5 +86,8 @@ static BatteryPowerSource PlatformPowerSource
}
}
}

static EnergySaverStatus PlatformEnergySaverStatus =>
PowerManager.EnergySaverStatus == Windows.System.Power.EnergySaverStatus.On ? EnergySaverStatus.On : EnergySaverStatus.Off;
}
}
Loading