I’m creating a .NET MAUI utility that makes use of iBeacon to unlock a door when the person approaches a beacon. In accordance with the documentation, StartRangingBeacons works solely when the app is energetic, whereas StartMonitoring ought to nonetheless perform even when the app is within the background or the iPhone is locked. Nevertheless, I’m going through a problem: RegionEntered and RegionLeft occasions are usually not being triggered as anticipated when the app is within the background or when the cellphone is locked.
- Why are RegionEntered and RegionLeft occasions not triggered whereas utilizing iBeacon monitoring within the background on iOS?
- How can I be certain that iBeacon detection works reliably when the app is within the background or the cellphone is locked?
- Is it attainable to set off BLE scanning utilizing Plugin.BLE upon beacon detection within the background?
My present method:
- I exploit CoreLocation for iBeacon monitoring and detection.
- When the RegionEntered occasion is triggered, I wish to begin scanning with Plugin.BLE to ascertain a reference to the detected beacon.
- BLE communication works superb when the app is energetic, however I’m struggling to make sure dependable operation within the background.
Thanks
Service class:
utilizing CoreLocation;
utilizing Basis;
namespace EntercamPass.Platforms.iOS.Companies;
public class BeaconManager : CLLocationManagerDelegate
{
protected static BeaconManager _instance;
protected static readonly object _lock = new object();
protected readonly CLLocationManager _locationManager;
protected CLBeaconRegion _beaconRegion;
protected static bool _isScanning;
protected const string BLE_SERVICE_UID = "0000fff0-454e-5445-5243-414d2d424c45";
protected const string BEACON_REGION = "com.entercam.go.beacon";
public BeaconManager()
{
_locationManager = new CLLocationManager
{
Delegate = this,
AllowsBackgroundLocationUpdates = true,
PausesLocationUpdatesAutomatically = false
};
_locationManager.RequestAlwaysAuthorization();
_beaconRegion = new CLBeaconRegion(new NSUuid(BLE_SERVICE_UID), BEACON_REGION)
{
NotifyEntryStateOnDisplay = true,
NotifyOnEntry = true,
NotifyOnExit = true
};
}
public static BeaconManager Occasion
{
get
{
lock (_lock)
{
return _instance ??= new BeaconManager();
}
}
}
public void CheckAndUpdateServiceState()
{
if (CLLocationManager.Standing == CLAuthorizationStatus.AuthorizedAlways)
{
StartScanning();
}
else
{
Console.WriteLine("Не хватает разрешений на использование местоположения.");
StopScanning();
}
}
non-public void StartScanning()
{
if (_isScanning) return;
_isScanning = true;
_locationManager.StartMonitoring(_beaconRegion);
_locationManager.StartRangingBeacons(_beaconRegion);
Console.WriteLine("Began scanning for beacons.");
}
non-public void StopScanning()
{
if (_isScanning == false) return;
_isScanning = false;
_locationManager.StopMonitoring(_beaconRegion);
_locationManager.StopRangingBeacons(_beaconRegion);
Console.WriteLine("Stopped scanning for beacons.");
}
public void OnAppDidEnterBackground()
{
Console.WriteLine("App entered background. Monitoring continues.");
CheckAndUpdateServiceState();
}
public void OnAppWillEnterForeground()
{
Console.WriteLine("App will enter foreground. Resuming ranging.");
CheckAndUpdateServiceState();
}
public override void DidDetermineState(CLLocationManager supervisor, CLRegionState state, CLRegion area)
{
Console.WriteLine($"Определено состояние: {state} для региона {area.Identifier}");
if (state == CLRegionState.Inside && area is CLBeaconRegion beaconRegion1)
{
_locationManager.StartRangingBeacons(beaconRegion1);
Console.WriteLine("Began ranging beacons inside area.");
}
else if (state == CLRegionState.Exterior && area is CLBeaconRegion beaconRegion2)
{
_locationManager.StopRangingBeacons(beaconRegion2);
Console.WriteLine("Stopped ranging beacons exterior area.");
}
}
public override void RegionEntered(CLLocationManager supervisor, CLRegion area)
{
Console.WriteLine($"Entered area: {area.Identifier}");
if (area is CLBeaconRegion beaconRegion)
{
//_locationManager.StartRangingBeacons(beaconRegion);
Console.WriteLine("Began ranging beacons.");
}
}
public override void RegionLeft(CLLocationManager supervisor, CLRegion area)
{
Console.WriteLine($"Left area: {area.Identifier}");
if (area is CLBeaconRegion beaconRegion)
{
_locationManager.StopRangingBeacons(beaconRegion);
Console.WriteLine("Stopped ranging beacons.");
}
}
public override void DidRangeBeacons(CLLocationManager supervisor, CLBeacon[] beacons, CLBeaconRegion area)
{
if (beacons.Size > 0)
{
foreach (var beacon in beacons)
{
Console.WriteLine($"Beacon detected: UUID={beacon.ProximityUuid}, Main={beacon.Main}, Minor={beacon.Minor}, RSSI={beacon.Rssi}");
}
}
else
{
Console.WriteLine("No beacons detected.");
}
}
public override void Failed(CLLocationManager supervisor, NSError error)
{
base.Failed(supervisor, error);
Console.WriteLine($"Location Supervisor error: {error.LocalizedDescription}");
}
public override void LocationUpdatesPaused(CLLocationManager supervisor)
{
base.LocationUpdatesPaused(supervisor);
Console.WriteLine($"LocationUpdatesPaused:");
}
public override void DidFailRangingBeacons(CLLocationManager supervisor, CLBeaconIdentityConstraint beaconConstraint, NSError error)
{
base.DidFailRangingBeacons(supervisor, beaconConstraint, error);
Console.WriteLine($"DidFailRangingBeacons");
}
public override void MonitoringFailed(CLLocationManager supervisor, CLRegion? area, NSError error)
{
base.MonitoringFailed(supervisor, area, error);
Console.WriteLine($"MonitoringFailed: {error.ToString()}");
}
}
Information.plist:
LSRequiresIPhoneOS
UIDeviceFamily
1
2
UIRequiredDeviceCapabilities
bluetooth-le
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
XSAppIconAssets
Belongings.xcassets/appicon.appiconset
CFBundleIdentifier
com.entercam.go
UIBackgroundModes
processing
fetch
location
bluetooth-central
bluetooth-peripheral
NSLocationWhenInUseUsageDescription
Это приложение требует доступ к вашему местоположению для работы с BLE устройствами.
NSLocationAlwaysUsageDescription
Это приложение требует постоянного доступа к вашему местоположению для работы с BLE устройствами.
NSLocationAlwaysAndWhenInUseUsageDescription
Это приложение требует доступ к вашему местоположению как в активном, так и в фоновом режиме для работы с BLE устройствами.
NSBluetoothAlwaysUsageDescription
Это приложение требует доступ к Bluetooth для обнаружения устройств.
NSBluetoothPeripheralUsageDescription
Мы используем Bluetooth для связи с устройствами.
NSUserNotificationUsageDescription
Это приложение требует доступ для отправки уведомлений.
MauiProgram:
utilizing CommunityToolkit.Maui;
utilizing EntercamPass.Instruments;
utilizing Microsoft.Extensions.Logging;
utilizing Shiny;
namespace EntercamPass;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder()
.UseMauiApp()
.UseMauiCommunityToolkit()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Common.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
fonts.AddFont("MaterialIcons-Common.ttf", "MaterialIconsRegular");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
#if ANDROID
builder.Companies.AddSingleton();
#endif
#if IOS
builder.Companies.AddSingleton(Platforms.iOS.Companies.BeaconManager.Occasion);
#endif
GlobalExceptionHandler.Init();
MauiApp mauiApp = builder.Construct();
return mauiApp;
}
}