iBeacon background monitoring stops working - ios

I have an app that monitors iBeacons entry/exit events. When it receives an event it forwards the event off to a server. The app continues to work (e.g., the server continues to receive updates) after the user minimizes and/or force closes it (so it works correctly in the background).
However, after a phone has been away from any iBeacons for a sufficient amount of time (e.g., overnight) and is brought near iBeacons again, the app stops receiving enter/exit updates until the user opens it up again (brings it into the foreground). If the user minimizes/closes the app at that point, updates continue to work correctly in the background.
Is anything that I need to do to allow long running monitoring updates in the background? After a while does iOS stop background monitoring?
Note: I am running iOS 9.3.1

iOS Apps are supposed to be able to detect beacons indefinitely in the background when they have been granted "always" location access.
This is the second report I have heard like this, so I wonder if it is a bug or a change in a new iOS version. Reporting your iOS version would be helpful.
One possibility: the network calls may be being blocked and not the beacon detections. You could test this hypothesis by adding NSLog statements to :
Log on beacon detection
Log on successful and unsuccessful connection to the server.
Once you add the above, reproduce the issue where you don't see events on your server. Then connect your phone to XCode and go to Devices, and look at the recent NSLog output to see:
Is there a line indicating the beacon was detected?
Was the server connection successful or not?
If you find it is the network connection that is failing, you may be able to correct the situation by requesting additional background network permissions.
EDIT: One other thing you might try when a detection is not made is launching a different beacon scanner app in the foreground like Locate. This will force an OS bluetooth scan and it might kick off your app's detection. If this works, it would tell you that bluetooth scanning had been suspended across the phone.

Related

Unable to perform a WiFi scan in the background

I'm attempting to rewrite an old app that gathers WiFi signal data and uses it for internal positioning. To be actually usable, it has to be able to do this while it is not the active app and/or while the screen is off.
Getting the WiFi scanning working was very straightforward, and as long as my app is active in the foreground I consistently get scan results every 4 seconds, indefinitely. But I'm running into problems with getting it to continue doing this in the background.
The moment my app is not active or I turn off the screen:
WifiManager.StartScan begins returning false.
My BroadcastReceiver's OnReceive method is no longer triggered.
WifiManager.ScanResults is empty - it doesn't even have old results in it.
These all resume working as expected once I switch back to the app or unlock my device, which is a Pixel 6a running Android 12.
From half a day of searching, I have already tried the following:
Running this as a Foreground Service with a persistent notification.
Acquiring a wake lock and wifi lock.
All adaptive battery features are disabled on the device.
Battery usage for the app is set to Unrestricted.
Wi-Fi scan throttling is disabled on the device.
adb has been used to disable doze on the device.
All the necessary permissions (as documented) are in the manifest, requested by the app, and have been allowed.
Confirmed the Foreground Service I start is still executing.
It's not clear if I am doing something incorrectly/missing something, or if I'm simply hitting an insurmountable restriction that Android is putting on WiFi scanning.
According to your description, the only casue I can think about is that you didn't get the Background Location Permission for your application.
At first, please check if the target version in your App is Android 10.0 or heigher or not. If so, you not only need to add the ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions but also the ACCESS_BACKGROUND_LOCATION permission and make sure you can access location in the background.
If the target verison is lower than Android 10.0, please check if you added the permission ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION in the AndroidManifest.xml or not. Then make sure the device show the dialog and you choose the selection which is accessing the location all the time.
For more information, please check the official document about accessing location in the background

Refresh iBeacon state

I am newbie with iBeacon and need some help. Already found some useful info from other topics but still searching for answers.
Is there a way to receive notification about my state at position right after app is killed or after I switch ON bluetooth? Now I got notifications only after state changes.
Example: I need to have notification when I got to point 'A'. But I got there and realized that my bluetooth is OFF. I switched bluetooth ON and didn't get anything because iBeacon thought I am 'INSIDE' from beginning. This happens when app is not foreground (but not 100% times, sometimes iBeacon 'rescan' and send his state again).
I need to somehow manually refresh iBeacon state and get methods didDetermineState or didRangeBeacons to work. I tried to stop and start monitoring after app is killed to forces the notification, but doesn't seem it works. I know there is a way to get this 'refresh' after turning ON display, but it could be perfect to also get it in other situations when needed.
Lots of location and beacon events can wake up an app that is running in the background, but relatively few events are sent to apps that have been killed via the task switcher or were never launched since boot.
The only bluetooth events capable of launching a non running app are:
didEnterRegion (for CLBeaconRegions)
didExitRegion (for CLBeaconRegions)
Other events received only by foreground/background running apps:
didDetermineStateForRegion
CoreBluetooth device discovery
CoreBluetooth power state changes
The last one is the event you care about, but it just won't be sent to apps that are not running. One alternative may be to rely on other location events like Significant Location Change, which launches a non-running app when the user moves "significantly" (e.g. to the next cell tower). You could register for these events and check Bluetooth state at that time. This may be the best you can do.

iOS Bluetooth monitoring without iBeacon monitoring

I am trying to create an app that wakes up to background mode whenever it detects a new peripheral that advertises a pre-defined service. I want the wakeup to happen even if the user minimized the app, the app was suspended, the app was killed by the user or the app was killed by the system. Obviously I also want the app to be accepted to the app store (so don't suggest solutions like adding all possible UIBackgroundModes and run in the background forever...).
I can add bluetooth-central to the UIBackgroundModes because my app fits the description here - it needs to communicate with a peripheral in the background.
I found some documentation here about State Preservation and Restoration. It describes a scenario where an app connects to a bluetooth door lock, and the connection breaks because the user went far away from the door. From what I understand, when the user returns to the door and the iPhone detects the door lock (by its MAC address, I suppose), it reconnects to the door lock and wakes up the app in Background mode (please correct me if I am wrong).
I don't want to preserve a connection to the peripheral (and waste its battery). I want the app to run scanForPeripheralWithServices that will wake up the app when a new peripheral is detected, even if the app was killed\suspended by the user\system.
I found a relevant answer here to a different question, saying I could simulate an app-termination-by-the-OS using kill(getpid(), SIGKILL); and then, if my app uses State Preservation & Restoration, it should wake up (right?).
When my app detects a new\old peripheral, I want it to create a quick connection, read some characteristics and disconnect. Unforetunately this is not possible with iBeacon Monitoring that does not give a Peripheral object (only a region). I know I can detect the peripheral by running scanForPeripheralsWithServices after my app enters the iBeacon region, but this feels strange - a direct continuous scanForPeripheralsWithServices that survives suspension & kill, would make much more sense.
Any ideas?
If you know for sure that this is not possible, and depending on iBeacon Monitoring is the only way, please let me know.
The key part of the question is:
I want the app to run scanForPeripheralWithServices that will wake up the app when a new peripheral is detected, even if the app was killed\suspended by the user\system.
Unfortunately, this is not possible with CoreBluetooth alone. If the user kills an app, it will not get new OS launch events from CoreBluetooth unless the user manually launches the app again.
Fortunately, CoreLocation does not have this restriction. Since iOS 7.1, it will launch a killed app to notify it of a Bluetooth beacon detection. This would allow you a few seconds of background running time to scan for peripherals.

How does Venmo bring an app into the foreground in iOS for their iBeacon feature?

From http://blog.venmo.com/hf2t3h4x98p5e13z82pl8j66ngcmry/2014/7/8/introducing-background-nearby-with-ibeacons, they suggest that they were able to forcibly bring app into the foreground:
"Whenever a device enters a beacon region, it briefly launches the Venmo app into the foreground in order to broadcast its peer identifier over the MPC framework, thus establishing a Nearby connection. In other words, whenever our users open Venmo to pay or charge the people they are around, they can instantly emit a beacon signal that momentarily wakes up their friends’ devices to connect and populate the user's Nearby drawer."
Every post on here about this suggests this isn't possible. Can someone explain?
I suspect that "foreground" is a simplification and that Venmo actually takes advantage of the iOS location background capabilities (the iOS location background mode is also applicable to iBeacon); meaning the app doesn't actually enter the foreground, but is launched into the background to complete the necessary tasks even if the app has been terminated.
Here's a bit of info from the docs about iBeacon background usage: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW7

Launch my app from bluetooth iBeacon connection (Private API)

I am creating a private distribution app and I am wondering if it is possible, using any methods or private API's, to open my app when a bluetooth connection has been made.
What I have discovered so far is that with iOS 7 and the ability to use iBeacons you can enter into bluetooth proximity and you can have your app send a notification to allow the user to then open the app.
What I am hoping to do then is have the app running in the background and listen for an iBeacon connection and, if one has been made, actually launch the app without the users control instead of just sending a notification.
I realize this would never be allowed publically, however is there anything private I can look at to achieve this without jailbreaking? I know to launch some apps you can do [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; however I want my app to listen for an iBeacon and then open itself up.
Is there any way or work around to achieve this?
Moving app from background to foreground without user interaction is pain in the ass. Sorry, don't have a solution, just want to share some information:
I asked the same question here and posted a bounty on it and got no good response:
Show some UI from background in audio player or VOIP app on iOS
At some moment I found a solution with the help of another person. It was based on usage of GSEvent (sending clicks to UI). You can look following questions. However, as I know, in iOS 7 these API became protected by entitlement. So, this method is dead (most likely).
Using GraphicsServices.h/GSEvent as well as compiling CLI iPhone tools with Xcode
Use GSEvent to send touch event,but it's invalid.
Simulating System Wide Touch Events on iOS
iPhone, how to fire a button event in programmatically
Apps can use region monitoring to be notified when the user crosses geographic boundaries or when the user enters or exits the vicinity of a beacon. While a beacon is in range of the user’s device, apps can also monitor for the relative distance to the beacon.
In iOS, regions associated with your app are tracked at all times, including when your app is not running. If a region boundary is crossed while an app is not running, that app is relaunched into the background to handle the event. Similarly, if the app is suspended when the event occurs, it is woken up and given a short amount of time (around 10 seconds) to handle the event. When necessary, an app can request more background execution time.
For detailed info:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html#//apple_ref/doc/uid/TP40009497-CH9-SW1
There are two scenarios: you either want users to be able to do something with your device other then use your app, or you want them to always be locked into your app.
In the former case you should trust user. Just show the push, timer or location notification and let them decide to launch the app or not.
In the latter case just lock the device using guided access mode.

Resources