Skip to content

Commit

Permalink
Fix broadcast receiver register on android 14.0/34+ (#18520)
Browse files Browse the repository at this point in the history
* Fix broadcast receiver register on android 14.0/34+

This adds a new helper method for registering broadcast receivers, which takes a bool for exporting the service or not, and on API 34 and higher, it calls the newer overload which takes the `ReceiverFlags` and passes the corresponding `NotExported` or `Exported` value to the bool parameter of the util method.

This allows us to call the right overload if we are on API 34 (Android 14.0) or newer where the declaration is required.

Also some older GetLocale()/SetLocale() methods are removed which were unused.

* Move new method to make diff more readable

* this seems not needed

* add tests

---------

Co-authored-by: Matthew Leibowitz <[email protected]>
  • Loading branch information
Redth and mattleibow authored Nov 14, 2023
1 parent 8bc2a2f commit 6ec214f
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 42 deletions.
10 changes: 5 additions & 5 deletions src/Essentials/src/Battery/Battery.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ partial class BatteryImplementation : IBattery
void StartEnergySaverListeners()
{
powerReceiver = new EnergySaverBroadcastReceiver(OnEnergySaverChanged);
Application.Context.RegisterReceiver(powerReceiver, new IntentFilter(PowerManager.ActionPowerSaveModeChanged));
PlatformUtils.RegisterBroadcastReceiver(powerReceiver, new IntentFilter(PowerManager.ActionPowerSaveModeChanged), false);
}

void StopEnergySaverListeners()
Expand Down Expand Up @@ -50,7 +50,7 @@ void StartBatteryListeners()
Permissions.EnsureDeclared<Permissions.Battery>();

batteryReceiver = new BatteryBroadcastReceiver(OnBatteryInfoChanged);
Application.Context.RegisterReceiver(batteryReceiver, new IntentFilter(Intent.ActionBatteryChanged));
PlatformUtils.RegisterBroadcastReceiver(batteryReceiver, new IntentFilter(Intent.ActionBatteryChanged), false);
}

void StopBatteryListeners()
Expand All @@ -74,7 +74,7 @@ public double ChargeLevel
Permissions.EnsureDeclared<Permissions.Battery>();

using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
using (var battery = Application.Context.RegisterReceiver(null, filter))
using (var battery = PlatformUtils.RegisterBroadcastReceiver(null, filter, false))
{
var level = battery.GetIntExtra(BatteryManager.ExtraLevel, -1);
var scale = battery.GetIntExtra(BatteryManager.ExtraScale, -1);
Expand All @@ -94,7 +94,7 @@ public BatteryState State
Permissions.EnsureDeclared<Permissions.Battery>();

using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
using (var battery = Application.Context.RegisterReceiver(null, filter))
using (var battery = PlatformUtils.RegisterBroadcastReceiver(null, filter, false))
{
var status = battery.GetIntExtra(BatteryManager.ExtraStatus, -1);
switch (status)
Expand All @@ -121,7 +121,7 @@ public BatteryPowerSource PowerSource
Permissions.EnsureDeclared<Permissions.Battery>();

using (var filter = new IntentFilter(Intent.ActionBatteryChanged))
using (var battery = Application.Context.RegisterReceiver(null, filter))
using (var battery = PlatformUtils.RegisterBroadcastReceiver(null, filter, false))
{
var chargePlug = battery.GetIntExtra(BatteryManager.ExtraPlugged, -1);

Expand Down
2 changes: 1 addition & 1 deletion src/Essentials/src/Connectivity/Connectivity.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void StartListeners()

conectivityReceiver = new ConnectivityBroadcastReceiver(OnConnectivityChanged);

Application.Context.RegisterReceiver(conectivityReceiver, filter);
PlatformUtils.RegisterBroadcastReceiver(conectivityReceiver, filter, false);
}

void StopListeners()
Expand Down
55 changes: 19 additions & 36 deletions src/Essentials/src/Platform/PlatformUtils.android.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#nullable enable
using System;
using Android.App;
using Android.Content;
Expand Down Expand Up @@ -25,13 +26,28 @@ internal static int NextRequestCode()
return requestCode;
}

internal static Intent? RegisterBroadcastReceiver(BroadcastReceiver? receiver, IntentFilter filter, bool exported)
{
#if ANDROID34_0_OR_GREATER
if (OperatingSystem.IsAndroidVersionAtLeast(34))
{
var flags = exported ? ReceiverFlags.Exported : ReceiverFlags.NotExported;
return Application.Context.RegisterReceiver(receiver, filter, flags);
}
#endif
return Application.Context.RegisterReceiver(receiver, filter);
}

internal static bool HasSystemFeature(string systemFeature)
{
var packageManager = Application.Context.PackageManager;
foreach (var feature in packageManager.GetSystemAvailableFeatures())
if (packageManager is not null)
{
if (feature?.Name?.Equals(systemFeature, StringComparison.OrdinalIgnoreCase) ?? false)
return true;
foreach (var feature in packageManager.GetSystemAvailableFeatures())
{
if (feature?.Name?.Equals(systemFeature, StringComparison.OrdinalIgnoreCase) ?? false)
return true;
}
}
return false;
}
Expand All @@ -51,38 +67,5 @@ internal static bool IsIntentSupported(Intent intent, string expectedPackageName

return intent.ResolveActivity(pm) is ComponentName c && c.PackageName == expectedPackageName;
}

internal static Java.Util.Locale GetLocale()
{
var resources = Application.Context.Resources;
var config = resources.Configuration;

#if __ANDROID_24__
if (OperatingSystem.IsAndroidVersionAtLeast(24))
return config.Locales.Get(0);
#endif

#pragma warning disable CS0618 // Type or member is obsolete
return config.Locale;
#pragma warning restore CS0618 // Type or member is obsolete
}

internal static void SetLocale(Java.Util.Locale locale)
{
Java.Util.Locale.Default = locale;
var resources = Application.Context.Resources;
var config = resources.Configuration;
#pragma warning disable CS0618 // Type or member is obsolete
#pragma warning disable CA1422 // Validate platform compatibility
#pragma warning disable CA1416 // Validate platform compatibility
if (OperatingSystem.IsAndroidVersionAtLeast(24))
config.SetLocale(locale);
else
config.Locale = locale;
resources.UpdateConfiguration(config, resources.DisplayMetrics);
#pragma warning restore CA1422 // Validate platform compatibility
#pragma warning restore CA1416 // Validate platform compatibility
#pragma warning restore CS0618 // Type or member is obsolete
}
}
}
33 changes: 33 additions & 0 deletions src/Essentials/test/DeviceTests/Tests/Battery_Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Maui.Devices;
using System.Threading.Tasks;
using Xunit;

namespace Microsoft.Maui.Essentials.DeviceTests
Expand Down Expand Up @@ -53,5 +54,37 @@ public void App_Is_Not_Lower_Power_mode()
{
Assert.Equal(EnergySaverStatus.Off, Battery.EnergySaverStatus);
}

[Fact]
public async Task EnergySaverStatusChanged_Does_Not_Crash()
{
Battery.EnergySaverStatusChanged += Battery_EnergySaverStatusChanged;

// just ensure there is no need for the OS to "respond" to a new subscription
await Task.Delay(1000);

Battery.EnergySaverStatusChanged -= Battery_EnergySaverStatusChanged;

static void Battery_EnergySaverStatusChanged(object sender, EnergySaverStatusChangedEventArgs e)
{
// do nothing
}
}

[Fact]
public async Task BatteryInfoChanged_Does_Not_Crash()
{
Battery.BatteryInfoChanged += Battery_BatteryInfoChanged;

// just ensure there is no need for the OS to "respond" to a new subscription
await Task.Delay(1000);

Battery.BatteryInfoChanged -= Battery_BatteryInfoChanged;

static void Battery_BatteryInfoChanged(object sender, BatteryInfoChangedEventArgs e)
{
// do nothing
}
}
}
}
16 changes: 16 additions & 0 deletions src/Essentials/test/DeviceTests/Tests/Connectivity_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ public void Distict_Connection_Profiles()
Assert.Equal(profiles.Count(), profiles.Distinct().Count());
}

[Fact]
public async Task ConnectivityChanged_Does_Not_Crash()
{
Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;

// just ensure there is no need for the OS to "respond" to a new subscription
await Task.Delay(1000);

Connectivity.ConnectivityChanged -= Connectivity_ConnectivityChanged;

static void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
{
// do nothing
}
}

[Fact]
public async Task Test()
{
Expand Down

0 comments on commit 6ec214f

Please sign in to comment.