I'm trying to use an iOS BLE device as BLE peripheral which also advertises in background.
I already figured out how to advertise in background and got it detected by another device looking for the specific bluetooth UUDID.
Unfortunately the advertiser-info is not transmitted when the app is in background. Is there a way to send a short string or something else device specific when the app is in background? It would be ok if the app would be woken up for a short period (if this is possible).
The advertised services are removed from the advertisement packages when the app is backgrounded. Only foreground scanning iOS devices will be able to obtain the services.
The advertised services are arbitrary UUIDs. You can easily figure out some encoding to store characters in them. However, this has several caveats, like
the general scheme is usually that the scanner finds your peripheral by the service UUIDS. If the data can be anything, then this is tricky.
the peripheral will not be able to change the advertisement data while backgrounded.
I suggest you not try to trick around with the system. Rather plan for connecting to the peripheral for a short time and sending the data to the central during this interval.
Related
I am currently using CoreBluetooth to scan for peripherals. Every 30 seconds it sends its packet of information to the cloud by using a Timer. This is working good in foreground. I would like this exact operation to function seamlessly in the background too.
I have declared a CBUUID ahead of time for it seek out the designated peripheral in the background. Upon entering background mode, the scan stops functioning after 10~ seconds. How do I continually make the scan operate continue in the background?
I was looking into Bluetooth State Preservation, would this alleviate the issue? Should it also not be on the main thread?
After the packets are advertised I would like them stored in memory. I am aware the DiscoverPeripherals logs the peripherals... is it possible to log the RSSI and additional peripheral data in chronological order and have it an operation take affect per an interval? I was looking at BGProcessingTask to fire off a function in the background. Would a better approach be to use CoreData to store the memory and clear it after? Best/easy suggestion is appreicated.
I have changed the CBUUID to the right peripheral for centralManager.scanForPeripherals(withServices: [uuid], options: nil)
with uuid being the CBUUID. That seem to be allowing the peripheral to be detected in the background. It stopped logging the scan after a short period of time. Right when I put the app in background, it functions properly for a bit. I theorize it could just be calling it on the same thread and it may not be operating in the background all together. I did test this by changing the the withServices to nil, the result was that the operating was not being logged at all once I closed to the background.
I was expecting the operation to continually be scanning on the basis of the Timer every period, after the period is up it would send it the cloud just how it was doing it in the foreground.
There are lots of restrictions on iOS apps when they are not in the foreground. Once an app moves from the foreground it is suspended and can only execute in the background for specific reasons and for limited durations.
In general, anything based on a Timer will not fire when the app is not in the foreground.
Some Core Bluetooth events are delivered while your app is in the background:
Pending connect operations can complete with a corresponding delivery to your app.
Peripheral disconnections will be delivered to your app
GATT Notify/Indicate operations from a connected peripheral will be delivered to your app.
Discovery of new peripherals advertising a service that you are specifically scanning for will be delivered to your app.
It is this last behaviour that you are relying on.
While you have done the right thing by specifying the specific service you are interested in, your plans are being thwarted by the fact that Core Bluetooth will not deliver repeated discovery notifications for a particular peripheral.
When your app is in the foreground you can use the CBCentralManagerAllowDuplicatesKey option to request a discovery notification each time a peripheral advertisement is seen, even if an advertisement from that peripheral has been seen before. This option has no effect when your app is not in the background.
The best way to gather data on a periodic basis from a peripheral (whether in the background or foreground) is for that peripheral to send its data via Notify/Indicate, however you seem to be trying to scan for the existence of peripherals rather than gather specific data from them, so this may not work for you.
When one of the supported Core Bluetooth background events occurs and your app has been jettisoned, State restoration allows your app to respond after iOS relaunches your app. It will not help you in this case.
It probably isn't possible to do what you want, at least not without changing the behaviour of your peripheral.
I work on iOS application which is using BLE for communication with our custom made BLE unit.
We want to send specific commands via BLE to the unit automatically.
When user is near unit and specific criteria are met, the app should connect to the unit, "login" the user, send command via BLE and disconnect right away.
These specific criteria are based on manufacturer data from advertisement (i.e. the unit is in "available to login" state when manufacturer data has last byte 0x01, when it's "NOT available to login", last byte is 0x00).
In foreground, this mechanism works flawlessly.
We want to do this even when app is in background or terminated (swipe up in dashboard on iPhone).
The mechanism we have implemented:
the unit has capability of acting as iBeacon
when unit is NOT available for login, the iBeacon is OFF
when it IS available for login, the iBeacon will turn ON and wakes up application, upon that the BLE scan will start in background mode
background mode setting is bluetooth-central
Problem here is that no matter what I tried, the advertisement:
sometimes it's not discovered at all (looks like it's timing issue?)
when it's discovered, it does NOT contain manufacturer data
Did anyone come across something similar?
Any help is appreciated and have a nice day!
An app simply cannot read raw BLE manufacturer advertisement data when in the background on iOS -- the operating system prohibits it.
Two exceptions to this rule:
iBeacon, which itself is implemented as a specific type of manufacturer advertisement. An app can detect iBeacons in the background on iOS, although only four bytes of readable data (encoded in the major and minor fields) are fully usable. If you can modify your device to send information this way, it will do what you want. However you must use CoreLocation APIs to detect iBeacon, as CoreBluetooth does not allow reading manufacturer data from iBeacon advertisements. If you do use CoreLocation, you cannot use the detections to establish a Bluetooth connection with CoreBluetooth as the two APIs are sandboxed.
Overflow Area advertisements. Backgrounded iOS apps can read these special types of manufacturer advertisements when in the background but only if the screen is turned on. (It is often possible to force the screen on at specific times by sending a local notification.) See my blog post here for more info: http://www.davidgyoungtech.com/2020/05/07/hacking-the-overflow-area
An alternative to detecting manufacturer advertisements is to use BLE Service advertisements with attached data. For this to work, you'd need to define a 16 bit or 128 bit GATT Service UUID and send out an advert with attached data bytes. Eddystone beacon formats work this way, and allow detection in the background on iOS. This is probably the best approach if you can alter the BLE hardware.
I need my app to act as a BLE beacon, even when it is in the background.
I've already made the beacon part - works fine when I'm using the app.
The problem is I've never made anything run in the background before, and not sure what the limitations are - if I will be allowed to let the app act as a beacon in the background.
Was wondering if this is possible or not (both technically, as well according to App Store rules)
Is this technically possible ? Can my app act as a beacon, even when the app is not in the foreground.
Is it within App Store rules ?
Unfortunately, iOS apps cannot emit iBeacon advertisements unless they are in the foreground. If you program your app to advertise iBeacon frames, as soon as the screen turns off or the app is not visible, iOS changes the advertising format to a special generic background advertisement that does not match the iBeacon format.
This proprietary background advertisement is useless for identification of a device. It is designed for connection to BLE GATT services from other iOS devices. Unless you want to advertise a connectable BLE GATT service to other iOS devices this advertisement has little value. EDIT: There is a way to make use of this advertisement. See below.
Apple's documentation describes this limitation here in the section titled "The bluetooth-peripheral Background Execution Mode":
you should be aware that advertising while your app is in the background operates differently than when your app is in the foreground. In particular, when your app is advertising while in the background:
The CBAdvertisementDataLocalNameKey advertisement key is ignored, and the local name of peripheral is not advertised.
All service UUIDs contained in the value of the CBAdvertisementDataServiceUUIDsKey advertisement key are placed in a special “overflow” area; they can be discovered only by an iOS device that is explicitly scanning for them.
If all apps that are advertising are in the background, the frequency at which your peripheral device sends advertising packets may decrease.
It may not be obvious that the above causes iBeacon transmissions to break, but I assure you that is absolutely a consequence.
Read my blog post here for more information on how to put useful beacon data into this background "Overflow Area" advertisement.
I want to build and app which can detect other iPhones with my app within 65 feet range. As I understand I have the following choices:
Use Bluetooth to check periodically whether there is device with my app in the range. Send list of found devices to the server. The problem here is battery consumption. Is it true that Bluetooth will be disabled after some period of time automatically?
Can I use BLE technology for this purpose? If so, do you know what devices support BLE?
What is the best option on your opinion? Did I miss some other option?
Thanks
UPDATE
I plan to run search every 20 seconds or even more often.
There is no simple answer to this problem.
Bluetooth has 2 flavors: "Regular" bluetooth, used for hands-free devices, headphones, and the like, and BLE (Bluetooth Low Energy)
Regular bluetooth devices must be paired. (I'm less familiar with regular bluetooth than BLE, so take my explanation of this bit with a grain of salt.) In order to be paired they have to be put into "discoverable" mode, which broadcasts their ID. That is a battery-draining and only done briefly. It's not an "always on" solution.
BLE has a range of up to 60 meters, so it should meet your need in that regard.
BLE devices can "advertise" as a "peripheral" for extended periods. Other Bluetooth devices can act as a "central" and ask to be notified when certain peripheral devices are detected. I'm not sure if you can make an iOS device advertise (broadcast) as a BLE peripheral while it's in the background and/or if the device is locked, but it will certainly advertise while it's running. I'm pretty sure you can register to be notified when you detect a certain BLE peripheral from the background, but not positive.
iBeacons are a specific use of BLE with some extra limitations and some extra abilities. An iBeacon is a dirt-simple transmitter that sends a UUID plus a major and minor value and a signal strength calibration value periodically (usually once a second.) You can't add any other data to an iBeacon transmission. iOS can only act as an iBeacon transmitter when the app is in the foreground. If your app moves to the background, it stops transmitting. Period.
However, you can listen for iBeacon signals even from the background. AND, if you've registered as a listener for an iBeacon and the system terminates your app due to low memory, the system still listens for those beacons on your behalf. If iOS detects a beacon you're listening for, you get re-launched if needed, and notified in the background. You can then post a local notification to get the user's attention.
iBeacons are probably your best bet, but you will need your users to be actively running your app in the foreground in order to transmit a signal. That will drain your user's battery fairly quickly.
One possible solution would to have have every single device send their locations to your server every predetermined time period (more frequent the better but more resource intensive). Then, query the data from the server and get the location of all the devices near you.
Keep in mind, that this probably won't be very useful for real-time data collection. For example, if you want to send data every 30 seconds or so, this isn't a good option.
Use this option if you want to get data every 15-20 minutes or so.
my app using scanForPeripheralsWithServices: to scan BLE device,the argument is specified servicesUUIDs array, sometimes could discover peripheral quickly,but sometimes need to wait for a moment.And my app is session backgrounding.Then,how can I discoverPeripherals as quickly as possible on background.
When the app is in the background iOS is enabling Bluetooth from time to time and it is not always listening. This is to save battery and because the WiFi and Bluetooth share the same antenna and cannot send at the same time. To make it discover your peripheral as fast as possible you should if you have access to peripheral implementation, make sure the peripheral advertises itself as often as possible. I believe Apple recommends at least once each 20th ms.