简体   繁体   中英

Execute DidRangeBeacons all the time in iOS 15 when user is in the range of beacon

[Expected behaviour: Specifically for iOS 15. iOS 14 or lower versions work fine]

I have an Xamarin.Forms iOS app where I am monitoring and ranging for BLE beacons. The goal is that being in foreground, background or killed state, when I enter a region, EnteredRegion() method should call and DidRangeBeacons() should start getting fired which fires once every second and it should never stop. When I leave region, ExitRegion() should be called and DidRangeBeacons should stop getting fired. If I close the app / kill the app, walk out of the region and walk in again, app should call EnteredRegion method and DidRangeBeacons() should start getting called and this method (DidRangeBeacons) should never stop as long as phone is in the range of the beacon.

[Current Functionality: With location Always permission provided]

Currently when app is totally closed/killed and if I walk into the region, EnteredRegion method executes and DidRange starts getting called. It executes for few seconds and stops when display goes off. It starts calling again when display is on again. Sometimes, it executes for one or two minutes and stops again. It starts again only when display turns on.

If I unlock the screen again and browse through phone, DidRangeBeacons stops executing. If lock the phone again and turn on the display, DidRangeBeacons starts executing again.

[Code]

public class AppDelegate : UIResponder, IUIApplicationDelegate
{

    [Export("window")]
    public UIWindow Window { get; set; }

    [Export("application:didFinishLaunchingWithOptions:")]
    public bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        // Override point for customization after application launch.
        // If not required for your application you can safely delete this method

        var bt = new BTManager();

        return true;
    }

    // UISceneSession Lifecycle

    [Export("application:configurationForConnectingSceneSession:options:")]
    public UISceneConfiguration GetConfiguration(UIApplication application, UISceneSession connectingSceneSession, UISceneConnectionOptions options)
    {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration.Create("Default Configuration", connectingSceneSession.Role);
    }

    [Export("application:didDiscardSceneSessions:")]
    public void DidDiscardSceneSessions(UIApplication application, NSSet<UISceneSession> sceneSessions)
    {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after `FinishedLaunching`.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }
}



public class BTManager : CLLocationManagerDelegate
{
    UNUserNotificationCenter center =  UNUserNotificationCenter.Current;
    UNMutableNotificationContent content = new UNMutableNotificationContent();
    AppleLocalNotificationManager notifcationmanager = new AppleLocalNotificationManager();

    CLLocationManager locationmanager;
    CLBeaconRegion region;

    public BTManager()
    {
        UNUserNotificationCenter.Current.RequestAuthorization(
            UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound,
            (approved, error) => { }
          );
        UNUserNotificationCenter.Current.Delegate = new AppleLocalNotificationManager();


        locationmanager = new CLLocationManager();
        locationmanager.Delegate = this;

        locationmanager.RequestAlwaysAuthorization();

        region = new CLBeaconRegion(new NSUuid("3ABFAA22-5624-11EA-8E2D-0242AC130003"), 0, 109,, "Region 1");

        region.NotifyOnEntry = true;
        region.NotifyOnExit = true;
        region.NotifyEntryStateOnDisplay = true;

    }


    public override void DidChangeAuthorization(CLLocationManager manager)
    {
        if (manager.AuthorizationStatus == CLAuthorizationStatus.AuthorizedAlways ||
             manager.AuthorizationStatus == CLAuthorizationStatus.AuthorizedWhenInUse ||
             manager.AuthorizationStatus == CLAuthorizationStatus.Authorized)
        {

            locationmanager.StartMonitoring(region);
            locationmanager.StartRangingBeacons(region);
            notifcationmanager.Send("Started monitoring from auth changed", "...", "0021");
        }
    }

    public override void DidDetermineState(CLLocationManager manager, CLRegionState state, CLRegion region)
    {
        if (state == CLRegionState.Inside)
        {
            var reg = region as CLBeaconRegion;
            
            notifcationmanager.Send("Inside State: ", reg.Uuid.ToString(), "1121");

        }
        else if (state == CLRegionState.Outside)
        {
            var reg = region as CLBeaconRegion;
            
            notifcationmanager.Send("Outside state: ", reg.Uuid.ToString(), "1151");

        }
        else
        {
            notifcationmanager.Send("Unknown state", "...", "131");
        }
    }

    public override void RegionEntered(CLLocationManager manager, CLRegion region)
    {
        var reg = region as CLBeaconRegion;
        if (reg != null)
        {
            notifcationmanager.Send("Entered Region", "...", "111");
        }

    }

    public override void RegionLeft(CLLocationManager manager, CLRegion region)
    {
        var reg = region as CLBeaconRegion;
        if (reg != null)
        {
            notifcationmanager.Send("Left Region", "...", "111");
        }
    }

    public override void DidRangeBeacons(CLLocationManager manager, CLBeacon[] beacons, CLBeaconRegion region)
    {
        notifcationmanager.Send("Ranged Beacons", "...", "121");
    }

   
}






public class AppleLocalNotificationManager : UNUserNotificationCenterDelegate
{
    public void Send(string title,string message,string id)
    {
        
        var content = new UNMutableNotificationContent
        {
            Title = title,
            Body = message,
            Sound = UNNotificationSound.Default,
           
        };
        UNNotificationRequest request = UNNotificationRequest.FromIdentifier(
          id,
          content,
          trigger: null
        );
        UNUserNotificationCenter.Current.AddNotificationRequest(
          request,
          error =>
          {
              
          }
        );
    }
   
    public override void WillPresentNotification(
      UNUserNotificationCenter center,
      UNNotification notification,
      Action<UNNotificationPresentationOptions> completionHandler
    )
    {
        completionHandler(UNNotificationPresentationOptions.Alert);
    }
    
}

I want DidRangeBeacons to execute in foreground, background and killed state all the time when user is in the range. Any suggestions how to fix it accordingly?

This is how ranging is designed on iOS -- you only get a few seconds of ranging time whenever you get a beacon region entry/exit event, the app comes to the foreground or background, or (with proper configuration) whenever the screen turns on.

It is possible to extend this ranging time with a background task and other tricks. See my blog post about it here . I'm not a Xamarin expert, so I cannot give specific instructions for setting up a background task on Xamarin to extend ranging. But the same techniques described in the blog post would apply.

EDIT: Here is a related answer that describes in greater detail how to set up unlimited ranging in the background on iOS. Again, these instructions are for native iOS code. Performing these tricks with an abstraction layer like Xamarin are difficult, because they are by design intended to work cross-platform and not easily allow you to do nitty-gritty platform specific configuration.

它在iOS15.2上还存在吗?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM