How to determine how close two iPhones are to each other? - ios

I'm working on an app that needs to have the ability to locate other iphones nearby. Precise location isn't necessary, but they should be in a 30ft radius.
Note: all of this has to happen in the background.
The options, as I see it, are:
Use Bluetooth. Develop a BT connection protocol that allows the app to send and receive data (just text) in the background. I would use iBeacons, but I understand they cannot transmit/advertise in the background.
Use GPS: This works in the background, no problem. However, the accuracy is sketchy, and in doors its much worse.
The questions I have, for the more experienced ios programmers, are this:
Does an app that uses bluetooth, or any kind of bluetooth, always need to have the bluetooth on? And can it request that the user do so?
If iPhone GPS gets the location wrong, does it show the same wrong location on another iPhone right next to it? I have no need for the actual position of the user...if the locations are "wrong" but they are the same I can tell they are close and that's enough for me.
Any help at all would be appreciated! Thanks!

#1,
Bluetooth : scanForPeripheralsWithServices method returns list of nearby bluetooth enabled devices.
Refer: [https://developer.apple.com/library/mac/samplecode/HeartRateMonitor/Listings/HeartRateMonitor_HeartRateMonitorAppDelegate_m.html][1]
#2, In indoor, GPS returns Last known location until it will get new location

Related

New ibeacons not detected in my app

I am developing a beacon detection application and at the moment works very well for kontakt brand beacons.
The client has sent me some new beacons that i have never seen and I have searched with google but i can't find what brand they can be.
The following information related to this beacon they gave me:
uuid: fda50693-a4e2-4fb1-afcf-c6eb07647825
pass: 000000
name: ion_beacon00021
major: 16789
minor: 24532
I have transformed my code to monitor both uuid without making it work
for (index, beaconID) in beaconsIds.enumerated() {
let beaconUUID = UUID(uuidString: beaconID)!
let identifier = "BLERegionBeacon \(index)"
let beaconRegion = CLBeaconRegion(proximityUUID: beaconUUID, identifier: identifier)
self.locationManager?.startMonitoring(for: beaconRegion)
self.locationManager?.startRangingBeacons(in: beaconRegion)
}
func configureLocationManager() {
self.locationManager = CLLocationManager()
self.locationManager!.delegate = self
self.locationManager!.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager!.distanceFilter = kCLDistanceFilterNone;
self.locationManager!.activityType = CLActivityType.automotiveNavigation;
for region in self.locationManager!.monitoredRegions {
self.locationManager?.stopMonitoring(for: region)
}
if CLLocationManager.authorizationStatus() != CLAuthorizationStatus.authorizedAlways {
self.locationManager?.requestAlwaysAuthorization()
}
self.locationManager!.startUpdatingLocation()
}
When not finding how to make this new ibeacon work I have resorted to third party applications (like MyBeacon, Detector, Beacon Demonstrator, Locate) to get validate if the information I have of this beacon is correct, but in no application I have been able to make it detect this ibeacon.
I bought a new battery to make sure it was not as simple as that, but neither. :'(
I had the idea to use any application that detects bluetooth devices and I found BLE Scanner. With this application i was lucky and could realize that at least the name that i have of the beacon is correct, but not found any related to major or minor or pass. I also thought that the long id seen there could be correct and that the I had was not... But I discarded it because when I connected the brand kontakt also gave me a different uuid.
ISCONNECTABLE Jumps between YES and NO.
When i use BLE Scanner to detect beacons Kontakt show me addional info called SERVICEDATA and ISCONNECTABLE still in YES.
- Is there anything else that needs to be done to detect these beacons?
- Anyone have any idea what may be going on?
Thank you very much
EDIT
Following the help of davidgyoung, I could realize that the Locate application if it works but only in its version for android. And in fact correctly returns the information I had been given from that beacon at first.
I found that these beacons with configurable using an application called BeaconFlyer and there I realized the reason for being that password that had sent me. I was able to change the uuid although strangely I just put numbers and no letters. I changed it by 32 zeros following the same pattern of 8-4-4-4-12. I still get no results in IOS but works on android, even after changing the uuid.
It is possible that some brands need to be certified to be detected by iOS devices and that the android do not have these restrictions.
EDIT 2
Considering all these details, it seems that the problem is IOS and not android, so it occurred to me that maybe if I created a simple android project just to test the functionality of the beacons, I should be able to detect it.
The test was done by registering this UUID f7826da6-4fa2-4e98-8024-bc5b71e0893e which is the one that has always works for me and with which I detect without any problem the beacons markkontakt.
To my surprise I detect it without problem even without registering the UUID that I have for this brand. It is very strange considering that only register 1 UUID that was the mark kontakt
If you are detecting another beacon with the same code, then the simplest explanation is that the ProxmityUUID you were given is wrong.
You won't be able to determine the correct ProximityUUID from BLE Scanner on iOS, as iOS blocks access to iBeacon advertisements unless you know the ProximityUUID up front. If you can get your hands on an Android device you can use the Locate app to see any beacon regardless of its identifiers. https://play.google.com/store/apps/details?id=com.radiusnetworks.locate&hl=en You can use this to find out what it is actually sending. There are similar apps for MacOS as well if you have access to a Mac.
It is quite clear that your client sent you "beacons" and not necessarily "iBeacons". As davidyoung pointed out, what constitutes an iBeacon is specified (quite strictly) by Apple. Download the specs from there and have a look, if you are so inclined.
I have used several BLE scanners to check what uuid, major, and minor numbers various brand iBeacons I worked with have, among them the mentioned BLE scanner. I think the specification does not prevent somehow putting additional services into an iBeacon, which results in different brand iBeacons potentially showing slightly different info in different scanners.
However, what you show in the screenshot and the fact that the isconnectable field switches values make me think that these beacons are not correctly working.
There will be no way to make them work on iOS that way then. You can write your own Bluetooth protocol code to do stuff with them, but that then won't rely on Apple's iBeacon mechanics. This will mean the nice stuff like region monitoring even while the app is suspended and so on won't work. It's also probably more battery draining and in general more work.
I am as said not a Bluetooth expert, but learned this much: UUIDs are all over the specs. The UUID you (and Apple) refer to is a part of the data packet the iBeacon is supposed to send, but I have also seen BLE services in general being identified by UUIDs in (non-Apple) reference documents. This can get confusing when you scan such a beacon and see UUIDs (or at least strings that look like ones) in several places. So even if the beacons you have follow the spec (or can be configured to do so somehow) my guess is that someone screwed up. For example, they could have edited (maybe even with a hardwired connection and tool) the wrong UUID, not setting the one you need to use, but accidentally overwriting the part that specifies the device as an iBeacon (byte 5 and 6 of the data packet come to mind), making it impossible for you to use them.
As an advice I would suggest the following: If your client is interested in actual iBeacon functionality, tell them they should buy correct beacons. the kontakt ones are actually quite good. I've tested cheap china knockoffs and would advise against those, as they quickly become unreliable. It might be tempting to save a few bucks at first, but if you need to constantly replace beacons in the long run that becomes more expensive in the end.
One other theory about what might be happening:
A beacon advertisement packet implementing iBeacon must have Apple's manufacturer code 004c in order to be detected by iOS. Android has no such restriction. If this beacon is sending a different manufacturer code it would explain why only Android can detect it.
How do you find out if this is true? You need to see the raw bytes of the advertisement somehow.
The beacon brand is Iotton and it's looks like the one we sell:
https://www.beaconzone.co.uk/ibeacon/ton9108
It's unlikely the Kontakt app is showing the Iotton beacon because the local name is incorrect. It's more likely your Kontakt beacon - turn it off for now. With this or any beacon, the best app for getting the UUID and seeing if the beacon is working is Nordic nRF Connect.
Are you sure you have set the delegate on CLLocationManager? The code doesn't show it, so unless this is somewhere above or below, you'll need to add:
self.locationManager?.delegate = self
Then make sure your class implements CLLocationManagerDelegate the didRange(beacons: region:) method to get callbacks.
If you think you already have this set up, showing that code might reveal something else that is missing preventing it from working.

In ios, is it possible to know if the GPS location is not being updated?

I'm creating an app that allows the user to navigate with a map when offline (no internet connection or wifi available), and I want to let the user know if the gps location not being updated. I know I can get the last updated location timestamp and the accuracy, but is it possible to know if the gps has no reception?
No, there's no public interface for finding out about the state of specific location hardware such as the GPS receiver.
The Location Manager abstracts all that away, so that developers can get location and accuracy information without worrying about whether the device used GPS, Wifi, iBeacons, cell tower locations, Loran-C, celestial navigation, etc. to determine the location. This is generally a very good thing because it means that your apps work on all devices regardless of whether they have GPS, and will continue to work (and maybe even work better) on new devices that might use other technology. But it also means that you don't get to ask the question "is the device receiving a GPS signal right now?"
Is it possible to know if the GPS location is not being updated?
No. It doesn't seem possible given the available API.
There are a few things about GPS to consider, if you haven't already. It is technically possible to receive a location update from CLLocationManager when you're "offline" but it will depend on several things:
If your device actually has GPS hardware. Some don't.
If you have line of sight to GPS satellites. There's a difference between GPS and A-GPS
Those true GPS updates will come much less frequently because of the way GPS works, but it should work.
... but is it possible to know if the gps has no reception
Based on the way GPS works (as best I understand it) you either turn the radio on/off (-startUpdatingLocation/-stopUpdatingLocation) with the Location Services API and you either get locations more frequently with A-GPS or infrequently with pure GPS when you don't have a network signal. I don't think the Location Services API has a way of telling you "I don't have a GPS signal at all."

Core Location, iBeacon & Region Monitoring

I am looking to make an App similar to that of the iOS reminders app. Where a user can essentially set reminders to go off when a user has entered or left a certain area.
I am new to iOS app development and have been doing some research into what might be needed but I am getting a bit confused and was wondering if someone could clarify a few things for me.
From my understanding:
Core Location is used to get your current location details
iBeacon is used to set your device as a Beacon for others to discover
Region Monitoring is used to monitor for when you enter a specific region
Am I correct in my assumptions? If not could someone please correct me. Also am I looking at the right kits that will help me achieve this?
What I would like to do is have a table of saved records that are triggered individually when they enter or leave there specified locations. (Do I use Region Monitoring for this)
Also how would I make this app still run in the background, once it is closed, and still trigger events (like the iOS Reminders App).
I have found a few basic tutorials that help me get my current location with CoreLocation but does anyone know of any other tutorials that might help me out? Or know themselves how I can go about accomplishing this.
Would really appreciate some help. Thanks!
I think that the best choice for your app is using Region Monitoring:
You could register up to 20 regions;
iOS will launch your app automatically if iPhone enters the observed region.
From Apple docs:
If a region crossing occurs while your iOS app is not running, the
system automatically wakes it up (or relaunches it) in the background
so that it can process the event. When relaunched, all of the regions
you configured previously are made available in the monitoredRegions
property of any location manager objects you create.
An app can register up to 20 regions at a time. In order to report
region changes in a timely manner, the region monitoring service
requires network connectivity.

Bluetooth iOS Pairing

I have a fitness app that is already in the app store and now I want to implement a bluetooth device that users can purchase if they wish. This is my first time dealing with bluetooth and after reading "Core Bluetooth Programming Guide", I have the following questions.
My app contains information that my bluetooth device requires simply to display the data. If I'm not mistaken, this makes the app the "Peripheral" because it has the data. The bluetooth device wants the data from the app so that makes the bluetooth device the "Central". Am I correct about this?
Finally, here is where I get confused. The bluetooth device has a button that I want when pressed to trigger the app to get the app to send new values to the bluetooth device. Is this possible? The reason I ask because in this scenario, would this now mean that the bluetooth device is the peripheral and the app is the central? If yes, will I have to break the current connection between the two in order to switch their roles (manager, and peripheral)?
Thank you in advance, really appreciate it!
Ted
As you have control over coding the app and coding the device, you can make it work either way around (Assuming the device is to be used specifically with your app and nothing else).
Both central and peripheral have methods to read and write data from/to the peripheral.
Without more information on the data and how often it's updated, it's difficult to suggest the best way to do it.
You say your device will have a button that will tell the app to send data over to it, well the app won't need to send anything it simply keeps values up to date then your button would tell your device to read the latest value.
Or (Again without knowing the purpose this may not suit) you do away with the button completely and your device subscribes to a characteristic in the app and is notified every time the value is changed by the app.

bluetooth low energy advertising packet and topology

I want to advertise a single id lets say "stackoverflow1" on a ble device. So people close to the sensor can get this message (welcome to wwdc2012) as popups on the iPhone. That's it! meaning that there is no update on the value or anything else in other words I just want to know which room I came in. In another room there's another sensor adversing "stackoverflow2".
Now the question is, should I put the rooms' sensor (advertiser) as Peripherals and visitors' iPhones as Centrals?
If your answer is yes, can I send this Id in advertising packet? i.e. can I skip connection to the room's peripheral? Please guide me a little but on this
Thanks
Yes, the iPhones should be centrals and the in-room device should be a peripheral. It's perfectly fine to put enough data in the advertisement that the iOS app can do something useful after simply seeing the peripheral advertised without actually connecting to it. That way, multiple centrals/phones can detect proximity at once without a single phone tying up an exclusive connection to the device. Instead of specifying the room in the service name, you should be able to put it in the advertisement data for the device, giving them all the same service name. That way the iOS app doesn't need to know the completely list of rooms (i.e. services) in advance and they can be added to without changing the app.
In short, the gist of what you described should work fine, and seems like a sound approach to me.
You can include information in the advertisement from the peripheral as "Manufacturer Specific" data. Then the iOS application can get it from the advertisement data dictionary using the CBAdvertisementDataManufacturerDataKey.

Resources