I am developing an iOS app kind of similar to functionality of Apple's air tag tracker app.
My app doing dead reckoning using CMPedometer and Accelerometer. Dead reckoning should start after receive a accurate gps location (I have enabled Location updates background mode)
There are some calculations execute at the same time to measure walking distance, calibration algorithms to dead reckoning and communicate with the target object via bluetooth once the user(app) is in communicating distance with the object.
In this case, target object act as Bluetooth central and App act as the bluetooth peripheral. So, I have enabled Acts as a Bluetooth LE accessory background mode as well.
Currently I have implemented the dead reckoning and calibrations. App working in the foreground. But the main requirement is to work in background also.
I have read few articles and documentation about iOS background modes and it seems very restricted to execute algorithm.
My intention is to start dead reckoning and algorithm based on a trigger from gps or bluetooth device.
At thing moment, I still haven't implement any codes for background processing, more of a feasibility study at the moment. As per my understanding Background fetch and Background processing both scheduled by the iOS, so these two ways will not help. Possible ways could be act upon a bluetooth trigger, act upon a location update or background push. Highly appreciated your thoughts on these approaches.
https://developer.apple.com/forums/thread/685525
https://developer.apple.com/videos/play/wwdc2020/10063/
https://developer.apple.com/documentation/xcode/configuring-background-execution-modes
Related
I am by no means an iOS developer, and am just hacking something basic together for myself. Sorry if this is too beginner of a question.
I'm trying to collect my own location data from my phone to my own back-end service. Looking around, I found a sample project to collect location info: https://github.com/chriseidhof/PostGPS/
From the looks of things, this project uses significant location update, so even though I changed my desired accuracy to 100 meters, the app will still only provide update when enough cell towers have changed.
Instead, I'm thinking of using geofencing (CLCircularRegion) by creating grids of 3x3 geofences with 500 meter radius (with maybe a 50 meter overlap between each region), and each time I exit the central region, a new set of 3x3 geofences gets generated.
My questions are as follows:
Is this (the deleting and re-fencing part) a correct use of geofencing on iOS?
Is this going to be more accurate than what I currently have?
Will this significantly negatively affect my battery life?
The problem with using geofencing is that you can't monitor more than 20 regions at a time(OS limitation). It's better to use significant location changes. It is triggered while you're in foreground or background and the location is updated if the cell tower has changed or you have opened the app while the app was not in memory. But this method will be triggered only in the intervals of 15 mins. So even if the cell tower changes rapidly, this method will be invoked only once in 15 mins.
So if you want to update the location in background keeping in mind the battery usage as well, use significant location api.
I would like to use iBeacon to detect the proximity to a hardware (emitting iBeacon signals) when the app runs in background.
Is there a way to get CLLocationManager to detect the location/proximity to an iBeacon whilst the app is running in background?
Does using iBeacon affect the iOS battery performance in a variable way depending on the transmission frequency of the iBeacon hardware? In other words, if we have an iBeacon that has a high transmission frequency will the iOS device drain more battery as it will be receiving more signal than when using an iBeacon with a lower transmission frequency?
Technically, it's possible to force ranging (estimating proximity) in the background on iOS. The problem is, that it has big impact on battery and potential user privacy implications, so it's unlikely that Apple would accept such an app into the App Store.
The proper (as in recommended by Apple) way for an app to interact with beacons in the background, is with region monitoring: simply detecting whether the user is in range of a beacon. If you want to force background ranging though, there's a short guide for that: https://community.estimote.com/hc/en-us/articles/203914068-Is-it-possible-to-use-beacon-ranging-in-the-background-
Cheers.
There are two different ways to use iBeacons - checking for region changes, or checking proximity to beacons.
In the background, you can't poll a beacon for proximity directly, you must instead use startMonitoringForRegion: to monitor for the crossing of the region boundary. Once that boundary is detected, your app will wake up to process in the background and handle what you want it to handle.
The application:didFinishLaunchingWithOptions: dictionary contains a key that indicates your app was launched due to a location event.
The transmission frequency of the beacon only affects the battery life of the beacon.
I'm trying to understand how you are supposed to detect proximity changes in the background.
The only window I get to range is when I enter a region, but this might be pretty far away.
I would like to present something when the user enters "near" or "immidiate", but if you get "didEnterRegion" at far, than stand around, then approach the beacon, you don't get any more ranging time, because you are still in the same region.
Is there a way to either extend the "ranging" time to let the user get near the beacon, or can you make "enterRegion" happen at a different proximity than "far"?
Background ranging time is limited to a few seconds as Charles says in his answer.
If you need to delay action until you are in the immediate region, then you must use iBeacons that allow you to reduce the transmit power so the transmission radius is smaller. The RadBeacon product from RadiusNetworks has this configurability for this exact purpose.
If you configure a RadBeacon for minimum transmit power, your phone will not detect it until it is a few feet away, sending you the entry event and starting your limited ranging window at that time.
Full disclosure: I am Chief Engineer for Radius Networks.
This walkthrough shows how to do what you're asking. I'm in the process of adapting and testing it for iOS 8, but the resulting app works well on iOS 7, pushing local notifications whenever the proximity changes.
In the best practices section in Apple's Getting Started with iBeacon guide it mentions that ranging API should not be used in the background.
• Ranging API are not expected to be used in the background. For best results, ranging should
be used when your app is frontmost and the user is interacting with your app.
Could be a shortcut to app rejection, so take caution.
Given this, you shouldn't really be expected to determine proximity when in the background. I'm also employing the low signal technique, but it becomes a little trickier to differentiate between beacons when you only use one monitored region for multiple beacons...
What's possible with iBeacons in background is pretty limited.
What you can do is monitor regions in the background (which gives you the didEnter / didExitRegion events).
You can also switch on ranging for the beacon and, for the 10 or so seconds after you get a beacon enter / exit event from region monitoring you will also get ranging info (i.e. the immediate / near / far data).
Perhaps you could trigger a local notification at that point to try to get the user to bring your app into foreground - then you'd be able to get the ranging data. If not then, based on my tests, you're only going to get the 10 seconds of ranging data.
To your question about adjusting the ranging time or adjusting the enterRegion proximity - no, these aren't possible in the current version of iOS.
I have been playing around with various test apps that detect when the device enters or leaves the iBeacon's region but my question is are there any apps that will detect when a beacon is turned on?
The reason I ask is that if I sit in the same room as my iPhone and remove the battery from the beacon then re-insert it the none of the apps that I have tried so far trigger a region entered response.
Please excuse my non tech question as until I can find out if this type of detection is possible I haven't yet fully immersed myself in the coding as it may not be suitable for my application.
Think about it from your phone's perspective: Powering down an iBeacon looks exactly the same as moving out of its transmitter range. Likewise powering up an iBeacon looks exactly the same as entering its transmitter range.
The way that the iOS CoreLocation monitoring callbacks work (didEnterRegion / didExitRegion) is exactly the same for the two cases above.
I suspect the reason you aren't seeing a didEnterRegion callback when you power on your iBeacon is because you didn't leave it unpowered long enough. It takes time for iOS CoreLocation to decide the phone exited a region, and it generally won't tell you that you entered a region if it thinks it never left it.
Two suggestions to make this easier for you.
When doing testing like this, always verify you get a didExitRegion indication before expecting a didEnterRegion event. (Add NSLog lines to your appDelegate to help you see this.)
Turn on ranging for iBeacons whenever you set up monitoring for iBeacons. This makes the time needed to detect region transitions much faster when you are in the foreground.
More information on the time it takes to detect region transitions can be found in this blog post.
I had similar experiences and assume the phone checks for new beacon only when you move around. That makes sense from an energy saving perspective and the main use case of beacons.
To detect a beacon when it's powered on is possible, if the CLLocationManager object is currently ranging for the beacon, and it's already in range.
The thing to understand here is the difference between region monitoring and beacon ranging.
Some apps only start with region monitoring, ranging only when a region is entered, and stop ranging when the region is exited.(taking the batteries out will cause the region to be exited) When you put the batteries back in, the beacon in this case is not detected because ranging has been stopped.
When your app launches start ranging with startRangingBeaconsInRegion: method and don't stop this anywhere in your code.
I have a requirement like the motion of the device in vehicle while driving should be detected when the application is in background. When the motion is detected the app should start automatically and move to foreground from background in iOS 7. I read that it is possible using CMMotionActivity Manager but have no exact clue to implement this functionality.