My iOS app has BLE beacons detection in it. Which means If user has bluetooth and location on and if user enters the range of a beacon, system automatically awakes the app If it was not running (killed state).
This was working fine on iOS 14 and below. Yesterday I updated my device to iOS 15 and app no longer gets awoken while entering a ble beacon region even If I have enabled "Always" location permission in the settings.
Any thoughts ?
My tests show that iOS 15 successfully launching an app from a stopped state into the background on beacon region entry.
Test steps:
Install this app on my phone with iOS 14.8: https://github.com/davidgyoung/CoreLocationRegionLaunchDemo
Run the app, grant notification and location always permissions.
Go to settings and verify location permission is always
Turn on a beacon, verify an entry notification arrives. Then turn off the beacon, verify the exit notification arrives.
Reboot the phone. Wait 5 minutes. Turn on the beacon, then verify the entry notification arrives. Turn off the beacon and verify the exit notification arrives.
Upgrade to iOS 15.
Wait 5 mintues.
Turn on a beacon. Verify an entry notification arrives.
See screenshots -- sorry they are ugly, but I have to finish the giant download of XCode 13 before I can send screenshots directly to my computer.
After trial/error, testing, and conversations with Apple, I can confirm it's not a bug with region monitoring, it's a bug with Apple's new prewarming feature in iOS 15.
In a nutshell, iOS 15 will half-launch apps silently in the background that iOS believes the person will use. In our testing this happens about every half hour. It makes app launching feel faster because a bunch of the app is already loaded and ready to go.
If Apple prewarms your app, and the user doesn't fully launch it, and then a region monitor needs to notify your app, it won't happen. That's sometimes region monitoring alerts your app and sometimes it doesn't. If your app is "cold", it will work. If your app is in memory, it will work. If your app is in this prewarm state, you are dead in the water.
Rebooting the whole phone works, because you're evicting any app in a prewarmed state.
I have it from Apple that this is really multiple bugs, some fixed and some not yet. The notes in the iOS 15.2 betas also specifically mention this likely affects HealthKit too.
The solution that works around the bug is to detect in main.m when Apple is prewarming your app and exit. This doesn't permit your app to launch when Apple prewarms and forces your app to fully boot when the time comes.
Here's the code for inside the main() method inside main.m. Note that it's prudent to add an iOS version detection so when Apple does fix this it can eventually be phased out and removed.
double systemVersion = [[UIDevice currentDevice] systemVersion].doubleValue;
if (systemVersion >= 15.0) {
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
BOOL prewarmed = false;
for (NSString *key in environment.allKeys) {
if ([key.lowercaseString containsString:#"prewarm"]) {
prewarmed = true;
break;
}
}
if (prewarmed) {
exit(0);
}
}
It's weird, in my case, reboot seems to solve the problem.
Related
We are developing an app that should respond to an iBeacon and circular regions in the background.
Sometimes it works perfectly, but sometimes the beacon and circular region enter/exit stop suddenly.
In the app, we are using(in background mode)
Significant location updates
Beacon region monitoring
Circular region monitoring
Continuous location updates for some actions
Any idea? It seems to me that in the background regions detection sometimes stopped working suddenly
Could it be the problem?
After trial/error, testing, and conversations with Apple, I can confirm it's not a bug with region monitoring, it's a bug with Apple's new prewarming feature in iOS 15.
In a nutshell, iOS 15 will half-launch apps silently in the background that iOS believes the person will use. In our testing this happens about every half hour. It makes app launching feel faster because a bunch of the app is already loaded and ready to go.
If Apple prewarms your app, and the user doesn't fully launch it, and then a region monitor needs to notify your app, it won't happen. That's sometimes region monitoring alerts your app and sometimes it doesn't. If your app is "cold", it will work. If your app is in memory, it will work. If your app is in this prewarm state, you are dead in the water.
I have it from Apple that this is really multiple bugs, some fixed and some not yet. The notes in the iOS 15.2 betas also specifically mention this likely affects HealthKit too.
The solution that works around the bug is to detect in main.m when Apple is prewarming your app and exit. This doesn't permit your app to launch when Apple prewarms and forces your app to fully boot when the time comes.
Here's the code for inside the main() method inside main.m. Note that it's prudent to add an iOS version detection so when Apple does fix this it can eventually be phased out and removed.
double systemVersion = [[UIDevice currentDevice] systemVersion].doubleValue;
if (systemVersion >= 15.0) {
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
BOOL prewarmed = false;
for (NSString *key in environment.allKeys) {
if ([key.lowercaseString containsString:#"prewarm"]) {
prewarmed = true;
break;
}
}
if (prewarmed) {
exit(0);
}
}
There have been two recent reports of region monitoring failing on iOS 15:
IOS 15 Ibeacon monitoring
iOS 15 does not awake app while entering BLE beacon region
The above are for CLBeaconRegion monitoring, but whatever problem exists may apply to CLCircularRegions as well.
I tried doing a controlled test in my answer to the second question above to reproduce this across an iOS 15 upgrade. I could not reproduce the problem. So this does not appear to be a universal issue.
You might try rebooting or reinstalling your app to see if these changes make a difference. Any updates based on the results of these tests would be welcome.
I have developed IBeacon App. When the app is in background mode and I enter the beacon region the UILocalNotification is triggered. But the thing is that if I kill the app the notification still triggers. I use locationMgr.RequestAlwaysAuthorization (); to catch the location change when the app is in background. I have written background-safe task to enlarge my background time on iPhone.
I have tried to use UIApplication.SharedApplication.ApplicationState but it returns true when the app is in background only, not terminated.
I use locationMgr.RequestAlwaysAuthorization (); since DidEnterRegion is called only with location set to ALWAYS.
In a word I am searching for the solution how to monitor EnterRegion&ExitRegion only in background and active mode. NOT WHEN THE APP IS KILLED
Before iOS 7.1 this was the default behavior of iOS, and everybody complained about it. Since iOS 7.1, beacon monitoring will launch apps even if they are killed.
What you need is a way to detect if an app has previously been killed when it is launched again so you can suppress notifications. Unfortunately, I am unaware of any way to do this.
There are several reasons why an app would be terminated (not running):
because the user actively terminated it (double-tap on home button, swipe app up)
because the OS needed the memory, and terminated it
because the OS updated the app, and terminated it
because the device was rebooted, and the app was not launched yet
Do you want to avoid notifications in all cases, or only in the first one?
If you want to avoid notifications in all cases, you can try removing the local notification in your AppDelegate's applicationWillTerminate: method (or an observer for the UIApplicationWillTerminateNotification notification):
- (void)applicationWillTerminate:(UIApplication *)application
{
[application cancelLocalNotification:<insert here the notification you saved>];
}
(you may alternatively use cancelAllLocalNotifications, or search for the notification using scheduledLocalNotifications).
If you only want to avoid those notifications in the first case, I'm afraid I'm not aware of any way to detect the user having actively terminated the app.
I built a reminders app, it wont work in background mode, and warns reminders via push notification.
But starting from the moment the User turn off your device (iphone or ipad) and turn on, my app is not this more in background mode, in which case reminders are no longer advised.
In this case, I like to find a way to make my app starts with the device but in background mode (the same happens with windows programs, android apps, and osx programs).
You are focusing on the wrong question. The question you should focus on is, "How do I ensure that my app's reminders will be delivered to my users even after a device restart?"
The answer is to set a Local Notification with a future delivery date, at the point the reminder is created, which of course is while your app is running. There is no need for your app to be running, in either the background or the foreground, for this notification to then be delivered at the specified time.
check project setting in .plist set UIApplicationExitsOnSuspend is YES
all day I tested the monitoring of beacons my app does. in general it works ok:
notifications in foreground work
notifications in background work
BUT
after a reboot it doesn't work until I launch ANY app that uses BluetoothLE
after I do that it works fine for my app as well!
But if I set UIBackgroundMode location in my plist though, my app gets region notifications just fine even after a reboot.
So... is that it? or whats the deal here? :D
this is under ios 7.1.1 btw
The code is very minimal:
https://github.com/RadiusNetworks/ibeacon-background-demo/blob/master/BackgroundDemo/BDAppDelegate.m
I did two things:
First, I reduced the time it took the app to launch >> mainly by doing stuff only when the app moves to the foreground. That was Step 1 but for the real app I was working on that alone was only half the solution
I then found out that the application in question tried to access the keychain in the background while the device was locked I moved that to a later point too and BING it worked!
I know there are several threads related this question.
At moment for me the answer is not clear.
If the app has been terminated by user (by swiping it up in the task view) and the iphone enter in a region where there is an ibeacon, the os can send a local notification to the user?
As of iOS 7.0.x this is true. If the user kills the app from the task switcher, it cannot run in the background or receive geofencing/iBeacon region notifications until the user starts it again.
"If you close an app that has been configured to receive background notifications, it won't receive them until it has been reopened." -- Apple knowledge base.
If you have an Apple developer account, you can read a more explicit statement of this in a forum answer to a similar question by an Apple employee.
There is some speculation that this may change in iOS 7.1. See here.
EDIT: It is confirmed this has changed in iOS 7.1