iOS: detect app users nearby - ios

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.

Related

Can I connect two iPhone by using the iBeacon technology?

I really haven't read into much about iBeacons beyond the fact that they are low energy bluetooth transmitters that are able to detect nearby proximity devices. I am aware that there are beacon devices such as estimote that allows users to get prompts when entering their proximity. However, I am wondering if two iPhones can act as both beacons and receivers at the same time. So is possible for User A to be able to connect to User B when he arrives in a particular distance of the person?
By connect what I mean is for some sort of interaction to occur.
(e.g. Notifying User A that User B is nearby or exchanging messages that these users would like to send to people that comes in their proximity)
Thanks guys.
Yes, iPhones can both act as iBeacons and receive iBeacon signals. But they can only act as an iBeacon when the transmitting app is in the foreground.
What you suggest is all possible, but it is important to note that the iBeacon concept is connectionless. It is a one way transmission of a simple identifier from beacon to receiver. If you want to make a connection and exchange data, you need a separate mechanism like the internet or a non-iBeacon Bluetooth connection.

CoreBluetooth to detect accessory proximity (whilst app in background)

I would like to use CoreBluetooth to detect the proximity to a hardware (emitting BLE signals) when the app runs in background.
The first step is activating BLE background mode in the capabilities tab. This will allow the app to receive BLE signals also when running in background. Now, the second step would be to write the code to detect the proximity to the BLE peripheral.
Looking at the iOS developer Bluetooth guide (at page 45/46) I found:
CBCentralManagerScanOptionAllowDuplicatesKey constant as a scan option
when calling the scanForPeripheralsWithServices:options: method. When
you do, a discovery event is generated each time the central receives
an advertising packet from the peripheral. Turning off the default
behavior can be useful for certain use cases, such as initiating a
connection to a peripheral based on the peripheral’s proximity (using
the peripheral received signal strength indicator (RSSI) value). T
Is this the correct direction for this?
In terms of iOS device battery usage, is this approach less efficient than using iBeacon?
Yes, it is a valid approach to use CoreBluetooth as you describe. You can get a callback for each packet you detect in the foreground (and in the background for non-manufacturer advertisements). You can then read the RSSI as an indicator of proximity.
Whether you want to use CoreBluetooth or use iBeacons with CoreLocation, the battery usage is similar in most foreground ranging cases.
If using CoreBluetooth, you probably don't want to keep getting callbacks for every packet indefinitely in the background, because it would drain the battery faster. CoreLocation iBeacon APIs limit you to 10 seconds of ranging in the background for each wakeup event to help save battery.
If you see your app ranging for longer periods in the background using CoreBluetooth you may want to add your own logic to protect against battery drain.

Implement BLE scan in the background in iOS

I have a query regarding Scanning of the BLE devices in an iOS app.
Use case of our app is to share the location of a set of BLE devices assigned to each user continuously to a particular server for every 15 minutes time interval, irrespective of the state of the app (except terminated state may be).
About our BLE device, it transmits the advertisement data once for every 4 second interval.
We tried using the "uses Bluetooth LE accessory" background mode and continuously we were able to scan the BLE devices using the scanForPeripharal method in CBCentralManager with the UUIDs of the BLE devices.
We were able to get the list of scanned devices even in the background.
But when we lock the device and the screen becomes inactive/turned off, we are unable to get the list of scanned devices.
In another solution, we tried using the background fetch but it is very inconsistent(practically it never gets called in the given time interval).
We need a solution using which we should be able to do the following,
For every 15 minutes time interval.
scan the BLE peripherals around our vicinity.
Get the current location of the user.
Share it with a MQTT server.
A couple of options:
If you have a custom BLE device anyway, you could modify it to send a stream of iBeacon advertisements periodically, say a burst of 10 packets every 15 minutes. An app looking for the iBeacon using CoreLocation would wake up in the background every 15 minutes and you could then read your other advertisements with CoreBluetooth.
You could make your app request location background modes, and request fine location updates. This may allow you to get BLE device discoveries after receiving callbacks for location update events. The disadvantage is that you would need to satisfy the AppStore reviewers that your app is a consumer navigation app to get it in the AppStore.

Detecting beacons via iBeacon Monitoring & Ranging vs CoreBluetooth scanForPeripheralsWithServices

There is a lot of confusion regarding the restrictions that are applied by the iOS on apps that want to scan BLE beacons\peripherals.
After reading several blogs and Stack Overflow answers, I want to see if I understand all the issues correctly. Please correct me if there is anything I misunderstood or missed. I refer only to iOS 7 and above, and focus on detection and not connection (Can you connect to a CLBeacon using the iBeacon Monitoring & Ranging API?).
The options for the beacons are clear - Use a general purpose BLE peripheral or use a BLE peripheral that advertises in the iBeacon format (Also, a non-standard peripheral can advertise in the iBeacon format in the adv-packet and a different format in the scan-response packet).
General Restrictions
iBeacon Ranging will let you know which beacons are around you. You must specify the ProximityUUID that the beacons advertise beforehand (no "general" scanning). didRangeBeacons will be called every second with an array of CLBeacon objects that were found recently. The distance from the beacon and its accuracy are calculated by the iOS using some confidential algorithm that only Apple's developers really know (The algorithm is based on the rssi values and the rssi-at-1-meter calibration byte that the beacon advertises). You can also use iBeacon Monitoring to call a delegate every time you enter or exit a region - again you must specify the ProximityUUID that you are looking for (you can also specify a major & minor). "Exiting a region" is defined by some time of not receiving any advertisement, and therefore cannot be immediate. The number of regions that can be ranged\monitored simultaneously per device is limited to 20 - This means that if other apps do monitoring\ranging at the same time, your app may not be able to monitor\range (right?).
CoreBluetooth - You can also detect other ad-structures in the beacon's advertisement. If the beacon advertises in iBeacon format too, you cannot see the iBeacon fields (ProximityUUID, major, minor...), despite the fact that they are sent under a standard "Manufacturer Specific" ad-structure that you can see in other cases.
Running in the Foreground - The less restricted use-case:
iBeacon Ranging and Monitoring - no further restrictions.
CoreBluetooth - Passing nil in the serviceUUIDs of scanForPeripheralsWithServices will scan for all peripherals. Passing CBCentralManagerScanOptionAllowDuplicatesKey as YES in the options will make the didDiscoverPeripheral to be called multiple times for the same peripheral\beacon (I assume that using a timer you detect the advertisement was not received for some time and assume that the user exited the "region").
Running in the Background - The more restricted use-case:
iBeacon Ranging will not work directly. iBeacon Monitoring will call didEnterRegion and give the app runtime of 6 seconds - in which you can start Ranging (for example, to detect major & minor). The detection may not be immediate since iOS turns scanning on and off to preserve the battery power. If you enter a region of multiple beacons with the same ProximityUUID, and you monitor this UUID without a specific major and\or minor, didEnterRegion will be called when you start receiving the signal from the first beacon - however, if you did not exit the region of the first beacon and you also entered the region of a second beacon the app will not be woken up again (didEnterRegion will not be called again) so you cannot start ranging to detect the second beacon's major & minor. The app cannot simply pop up to the foreground, but can create local notifications and other background operations.
CoreBluetooth - According to Core Bluetooth Background Processing scanForPeripheralsWithServices can run in the background using, but you must specify at least one serviceUUID. didDiscoverPeripheral will be given a runtime of 10 seconds. Using CBCentralManagerScanOptionAllowDuplicatesKey will not work - didDiscoverPeripheral will be called once for every peripheral. Therefore, you cannot detect "exit" from the region and "re-entry". I suppose you can use a non-standard BLE peripheral that changes its MAC address to overcome this issue. The app cannot simply pop up to the foreground, but can create local notifications and other background operations. The detection may not be immediate since iOS turns scanning on and off to preserve the battery power.
Running after the app is killed
iBeacon Monitoring - Works! Even if the user killed the app or the device was restarted.
CoreBluetooth - The app will be woken up if it was killed by the iOS (due to inactivity or memory constraints). However, if the user explicitly killed the app it won't be woken up (which makes the first case hard to test). I don't know what happens after a device restart...
Does anyone have more experience with these restrictions? Can scanForPeripheralsWithServices be used as a better alternative to iBeacon Monitoring in some use-cases?
Thanks!
You are mostly right with your description. Just two clarifications:
The 20 region limit is not per device, it is app-specific. No matter what other apps are doing on the mobile device, your app is still allowed to monitor up to 20 regions by iOS. That said, there are likely hardware limits that are device-specific on how many regions can be monitored in the background with hardware assistance. These limits are undocumented. If you surpass these undocumented limits, it will probably take a lot longer to detected beacons in the background. (Although that said, there is no OS guarantee of when the detections come, anyway.)
You cannot connect to a CLBeacon using Monitoring and Ranging APIs. These APIs only work with BLE advertising packets, which are connectionless.
Yes, it is possible to use scanForPeripheralsWithServices as an alternative. This is what Gimbal beacons do in order to implement a proprietary system. There are real disadvantages, however, in terms of background detection time and reliability.

iOS: Connecting to BLE device when 20+ such devices are in the room?

I'm developing an iOS app that connects to a certain type of BLE device, but I'm writing the code in a room that has 20+ such devices sitting around, powered up. I consistently find that in the morning, I can connect to my personal device just fine, but as the day wears on, it becomes impossible to connect to my device, as if the 20+ other devices have woken up somehow and are blocking my signal. No one is using most of these devices; they're just sitting on tables. Is this a known bug? Is Apple working on it?
Are all the devices Advertising?
If they are advertising with say 20ms then it could be difficult to hear all. There are "only" 3 advertising channels to share between all devices. The connection happens on the same channels (the peripheral listens after it's own advertising to hear if someone want to connect).
It has nothing to do with Apple CoreBluetooth. In my experience CoreBluetooth can handle around 20 devices after connection has succeeded and the activity has moved to the traffic channels.
1) Try using a slower advertising interval. This should work okay if your app is in the foreground.
2) Use a BLE sniffer (TI USB dongle is fine) and see if connections fail on protocol level, then it is not CoreBluetooth's fault.
3) Only advertise with fast interval when needed or you really really need a fast discovery.
As a rule of thumb apple needs up to 55 advertisements in background mode to see a device when it's the only one visible. So if you really need around 1.1second discovery then you might need 20ms advertisement interval, else use 100ms or even more (see Apple advertising interval guidelines for the exact number that will optimise discovery)
100ms gives so much more capacity and not too bad discovery.
1-2s gives a much longer battery lifetime and will be found in 1-2 minutes if your app is in the background. This would be quite fine for eyeBeacons in malls or the like while you might want 100-200ms in smaller areas.

Resources