Bluetooth Advertises in peripheral mode, even after the app is closed

Hi all,

In our use case the iOS mobile device is peripheral, that advertises in order to be found by our hardware device that is in central role.


Since iOS 13 we struggle with a very strange behaviour:


When the app is closed, we programatically stop advertising, but it is reactivated by the iOS. From then on the mobile device advertises endlessly. This causes some trouble when our hardware device is nearby, as it cannot connect, because the app is not running.


The only thing that helps to stop advertising is to disable bluetooth in the system settings. Even using the control center does not stop advertising.

Is there a place to configure this behaviour in a way, that advertising will kept stopped?


Kind Regards

David

Replies

>Since iOS 13 we struggle with a very strange behaviour:


Things changed w/iOS 13.x. Confirm your app is compliant with the new user notification requirements. This might be your main issue.


>Is there a place to configure this behaviour in a way, that advertising will kept stopped?


Centrals (your hardware) scan for peripherals that are advertising*. I don't think you want the OS to stop it's own advertising, even if your testing shows that helps your app get thru. I think your app needs to stand it's ground.


Show your code for backgrounding. Also, what does your BT device actually do? Are you required to be in the MFi Program?


*From the docs:

Centrals and Peripherals Are the Key Players in Core Bluetooth

In Bluetooth low energy communication, there are two key players: the central and the peripheral. Each player has a different role. A peripheral typically has data that is needed by other devices. A central typically uses the information served up by a peripheral to accomplish some task. For example, a digital thermostat equipped with Bluetooth low energy technology might provide the temperature of a room to an iOS app that then displays the temperature in a user-friendly way.


Each player performs a different set of tasks when carrying out its role. Peripherals make their presence known by advertising the data they have over the air. Centrals scan for nearby peripherals that might have data they’re interested in. When a central discovers such a peripheral, the central requests to connect to the peripheral and begins exploring and interacting with the peripheral’s data. The peripheral is responsible for responding to the central in appropriate ways.

Hi David,
I do experience the same behaviour. I did notice that the advertising package changes from:
Code Block
advertisementData {
kCBAdvDataIsConnectable = 1;
kCBAdvDataRxPrimaryPHY = 0;
kCBAdvDataRxSecondaryPHY = 0;
kCBAdvDataServiceUUIDs = (
<my UUID service>
);
kCBAdvDataTimestamp = "617187146.149648";
kCBAdvDataTxPowerLevel = 12;
}

to:
Code Block
advertisementData {
kCBAdvDataHashedServiceUUIDs = (
<my UUID service>
);
kCBAdvDataIsConnectable = 1;
kCBAdvDataRxPrimaryPHY = 0;
kCBAdvDataRxSecondaryPHY = 0;
kCBAdvDataTimestamp = "617187146.524474";
kCBAdvDataTxPowerLevel = 12;
}


where the kCBAdvDataHashedServiceUUIDs string is the CBAdvertisementDataOverflowServiceUUIDsKey constant. Which is the same behaviour that I see when the advertising app does the transition from the foreground to the background.

just to ads something on top of it, when the advertising app does the transition from the background to the foreground, the advertising changes again to something I don't expect:

Code Block
{
kCBAdvDataHashedServiceUUIDs = (
<my UUID service>
);
kCBAdvDataIsConnectable = 1;
kCBAdvDataRxPrimaryPHY = 0;
kCBAdvDataRxSecondaryPHY = 0;
kCBAdvDataServiceUUIDs = (
<my UUID service>
);
kCBAdvDataTimestamp = "617105621.560463";
kCBAdvDataTxPowerLevel = 12;
}


Now, if I stop advertising I get the same advertising I observe when the advertising is going on in the background (it shouldn't advertise at all because I stopped it):

Code Block
advertisementData {
kCBAdvDataHashedServiceUUIDs = (
<my UUID service>
);
kCBAdvDataIsConnectable = 1;
kCBAdvDataRxPrimaryPHY = 0;
kCBAdvDataRxSecondaryPHY = 0;
kCBAdvDataTimestamp = "617187146.524474";
kCBAdvDataTxPowerLevel = 12;
}


In both scenarios, a scanning iOS device will detect my app (either after being killed or after the startadv-fg-bg-stopadv dance) as an iOS app advertising in background.

I do understand that your case is a bit different, because you have a custom hardware scanning.

Did you manage to find a solution? I tried to clean up on killing (removing published services and stopping the advertising) but I did not manage to solve the issue.

Enrico


Hi Enrico,

Did you manage to find a solution? I tried to clean up on killing
(removing published services and stopping the advertising) but I did not
manage to solve the issue.

We worked around the issue using the fact kCBAdvDataServiceUUID is just present when the app is in foreground. Our central device just connect if the kCBAdvDataServiceUUID is present.

What I found out is that the advertising is somehow related to iCloud. On a clean iOS device not bonded to any Apple-ID the start / stop advertising works as expected.


Regards,
Tobias
well, this issue has been discussed a lot. I also reported this to Apple as a bug, but they seem not to be actively change that. The cause of this issue is that all the applications in your iphone shares the same overflowserviceuuid area, including the default bluetooth in your iphone's settings. That means if your app override the overflow area in GATT stack(by moving to the background), this uuid will take effective even you kill your app, because your default bluetooth is still working by using this shared overflow area, that is why other phones will can find you. Also, there are few workarounds to fix this, depends on the business scenarios.
Hi Tobias,


We worked around the issue using the fact kCBAdvDataServiceUUID is just present when the app is in foreground. Our central device just connect if the kCBAdvDataServiceUUID is present.

In this situation the central device will not try to connect to the app when it is advertising in background, because it can't tell if the app is in background or killed/closed. It that correct?

Thank you
Enrico