Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Bloothtooth LE while app is in background

I am building an iOS app with Xamarin, with this BLE plugin:

https://github.com/aritchie/bluetoothle

I'm just broadcasting a UUID via BLE, and it works. Here is my code:

var data = new Plugin.BluetoothLE.Server.AdvertisementData
            {
                LocalName = "MyServer",
            };

data.ServiceUuids.Add(new Guid("MY_UUID_HERE"));

await this.server.Start(data);

The only problem is that it stops broadcasting once I put the app in the background. And resumes again when I open the app again.

How can I let it continue to broadcast once it's in the background? I read the documentation here:

https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html

And it says that I have to use the CBCentralManager class to obtain the preservation and restoration feature (so I can keep broadcasting the UUID at all times), but I'm having a hard time translating this to Xamarin/C#.

EDIT

After researching some more, I read that I need to create an instance of CBCentralManager and implement WillRestoreState in the delegate. I did this in the AppDelegate:

[Register("AppDelegate")]
public class AppDelegate : MvxApplicationDelegate, ICBCentralManagerDelegate
{
    private IGattServer server = CrossBleAdapter.Current.CreateGattServer();
    private CBCentralManager cbCentralManager;

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        // irrelevant code...

        this.Ble();

        return true;
    }

    private async Task Ble()
    {
        try
        {
            await Task.Delay(5000); // wait for it to finish initializing so I can access BLE (it crashes otherwise)

            var options = new CBCentralInitOptions();
            options.RestoreIdentifier = "myRestoreIndentifier";
            this.cbCentralManager = new CBCentralManager(this,null,options);

            var data = new Plugin.BluetoothLE.Server.AdvertisementData
            {
                LocalName = "MyServer",
            };

            data.ServiceUuids.Add(new Guid("MY_UUID_HERE"));

            await this.server.Start(data);
        }
        catch (Exception e)
        {

        }
    }

    public void UpdatedState(CBCentralManager central)
    {
        //throw new NotImplementedException();
    }

    [Export("centralManager:willRestoreState:")]
    public void WillRestoreState(CBCentralManager central, NSDictionary dict)
    {
        //never gets called
    }

But it didn't make a difference for me. And the WillRestoreState method never gets called... I don't mind using a different plugin/library if I have to at this point...

EDIT 2

I just realized that the app is still broadcasting while it is in the background, I just don't see the service UUID anymore (in the web portal of the beacon that I'm testing with), I only see the phone's identifier.

like image 564
Drake Avatar asked Oct 29 '22 06:10

Drake


1 Answers

After doing tons of research, I found that it is simply an iOS restriction - you can not broadcast the UUID of a BLE service while your app is in the background. Background work is very restrictive in iOS.

EDIT to include Paulw11 comment (which is true): You can advertise a service, but it is advertised in a way that only another iOS device that is specifically scanning for that service UUID can see.

like image 155
Drake Avatar answered Nov 04 '22 08:11

Drake