As stated clearly in Apple docs, beacon ranging can be done in background for a short period of time only, say up to 10 seconds by default or up to 3 minutes with the help of background task expiration handler. As per my app's use case, app needs to do beacon ranging for every 15 mins until user exits the region. I am thinking of using background push notification(silent push notification) for this purpose(assuming data connection is available on the device always). So the flow goes like this, upon user entering the region, app calls the server with device token, server sends silent push notification for every 15 minutes. Once app received push notification, it does beacon ranging within allowed period of time if needed. Question I have here is whether using push notification in background mode to do ranging is legal, will I face any issues during app store submission.
Note: Also I need to enable BLE background mode for the app, to read some characteristics from some BLE devices.
Technically you can do it, but Apple mostly rejects such app. One important thing you have to consider is that, if the app is manually killed by the user and not running in the background, then the app won't wake up with silent push notification. There is a workaround if you have VoIP push notifications it will wake the app even from the terminated state. But you might need strong reason while pushing it to AppStore.
If you misuse one of the background modes, the app will probably be rejected, saying that, I don't think silent push notifications were meant for: keep an iOS app in "Background" state by sending it a silent push notification every few minutes.
another thing is that silent push notifications are rate limited as described http://asciiwwdc.com/search?q=push+notification, so I'm not sure if they will be sent every few minutes.
Apple says that;
Silent notifications are not meant as a way to keep your app awake in
the background, nor are they meant for high priority updates. APNs
treats silent notifications as low priority and may throttle their
delivery altogether if the total number becomes excessive. The actual
limits are dynamic and can change based on conditions, but try not to
send more than a few notifications per hour.
You might want to see this article. The user talks about apps that use silent notification for triggering location tracking. But eventually it's a hack that Apple may reject some time in the future, so it's best to have a contingency plan. FWIW so far I haven't heard anyone reporting rejection.
So the official answer is don't do it, as for the why you can refer to Ashish's answer. The unofficial answer is if you can't change your business logic then do it at your own risk.
The iOS application I'm working on does the exact same thing with the exception that I'm using recording instead of a Beacon. Recording by iOS standards gives more issues in pushing the app to the app store.
But Apple did not reject this app. Although we still are facing some issues but they don't relate to your problem.
You can follow such a tutorial for further help apart from the answer you were looking for : iOS Push Notification Demysitfied
Also, I've done firing of local notifications, while the application is in the background. BLE even works if the app is killed by the system, when the OS receives some communication from your peripheral or central, iOS wakes your app up and executes the desired function, before putting your app back to sleep.
Related
I need to extend my app functionality with push notifications. The desired outcome would be to send silent notifications which will trigger the creation of local notifications.
I read about this silent notifications and they seem to be very unreliable.
First of all according to this:
"If something force quits or kills the app, the system discards the held notification.".
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app the silent notification can be discarded. From my understanding force quit means that you double tap on home screen button and swipe up the app, right?
Secondly, according to this https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app apple doesn't recommend to send more than 3-4 silent notifications per hour. Do you have any experience with this behaviour? if you send 15 notification on an hour how many did you get?
If what I wrote above is true, then what alternative I have to silent notifications?
I believe remote notifications (of type alert, for example) are not affected by my two points above, right? Even if you force kill the app you will still get them.
I know there are so some stack overflow questions that covers parts of this topics but they are pretty old.
I understand that Silent Notifications and Remote Notifications are different things. The silent is just a regular Push Notification that doesn't generate any kind of alert to the user, it goes directly to the Notification Center, but there's still a hidden notification somewhere. Notice that the docs doesn't mention silent anywhere.
Now Remote Notifications are the real deal for your needs. This kind of notification doesn't produce any kind of alert to the end user, its just a payload that is passed into your AppDelegate methods, that way you can generate asynchronous calls to your app to inform that some external event happened, and take some action about it, like updating your local database.
The thing is, Remote Notifications rely on the same APNS infrastructure, and Apple doesn't guarantee the delivery of notifications. Although the failure rate tends to be very low nowadays, you should be aware that you can't rely on notifications for serious business logic. Background updates is a more a means of having your local state in sync and immediately available when the user opens the app, but it doesn't save you from having to manually trigger synchronization logic when your app is opened.
So about the specific bullets:
The thing is, iOS manages received notifications and optimizes the delivery to your app. Notifications can be received while your app is in background or stopped state. If you've sent a notification to the user and iOS kept it cached while your app was in background, and then the user forcibly killed your app, this notification will be lost. This should be probably be a very rare scenario, but could happen.
I personally don't have experience with this notification throughput stuff. I believe this is probably related to the fact that when a notification is sent and your app is in background, iOS will run it in background to deliver the notification and give you a chance to process it. Depending on the volume of notifications the operating system may impose restrictions on the background processing to preserve battery or other system resources.
So, I don't know your feature requirements, but I wouldn't consider the Remote Notification infrastructure much reliable for more than small updates to the local state.
I'm developing a great feature for my app which requires HTTP requests to be sent periodically in background.
I have read already many articles and discussions here, but haven't come up with a solution because all suggestions I met on stackoverflow.com solve the problem only partially.
Let me explain in details what do I want my application to do.
Consider there is a website with API and I want to send requests (when app is in background mode) periodically to check the state of data on the website. And if the state of data is acceptable I would send Push Notification to user to notify him that data is correct at the moment.
Could someone propose a solution how to implement this idea in iOS app?
On iOS you can't do this, as you've described it. You don't get to schedule tasks to happen at regular intervals when your app is in the background or not running. You also don't get to control whether iOS decides to terminate your app when it's running in the background, so "not running" is a case you'd need to handle (you can't just keep running in the background as for long as you want).
I'm not sure I understand the server side of things though. If your server is manipulating the data until it's acceptable, and it can send push notifications, why does it need to wait for an incoming request from the phone? Why not just send the push when the data is ready? If the app decides what's "acceptable", maybe have the app tell the server what it wants so that the server knows when to send a push.
There are a couple of options that would get close to what you describe. If you implement the "background fetch" feature in your app, iOS will launch the app when it's not running and let it make network calls in the background. There's no guarantee of how often this happens, though. This is described in Apple's background execution docs
The other option is the "silent" push notification. If your server sends one of these, iOS can launch the app in the background to handle the notification. The app could make a network call if necessary. You can send these at whatever time you like, but Apple warns to not overdo it:
Silent notifications are not meant as a way to keep your app awake in the background, nor are they meant for high priority updates. APNs treats silent notifications as low priority and may throttle their delivery altogether if the total number becomes excessive. The actual limits are dynamic and can change based on conditions, but try not to send more than a few notifications per hour.
Silent pushes are described in Apple's push notification docs.
iOS Background Execution Limits
Questions
How do I keep my app running continuously in the background?
If I schedule a timer, how do I get it to fire when the screen is locked?
How do I run code in the background every 15 minutes?
How do I set up a network server that runs in the background?
How can my app provide an IPC service to another one of my app while it’s in the background?
Answer from Apple:
The short answer to all of these is You can’t. iOS puts strict limits on background execution. Its default behavior is to suspend your app shortly after the user has moved it to the background; this suspension prevents the process from running any code.
Official: https://developer.apple.com/forums/thread/685525
I'm developing a great feature for my app which requires HTTP requests to be sent periodically in background.
I have read already many articles and discussions here, but haven't come up with a solution because all suggestions I met on stackoverflow.com solve the problem only partially.
Let me explain in details what do I want my application to do.
Consider there is a website with API and I want to send requests (when app is in background mode) periodically to check the state of data on the website. And if the state of data is acceptable I would send Push Notification to user to notify him that data is correct at the moment.
Could someone propose a solution how to implement this idea in iOS app?
On iOS you can't do this, as you've described it. You don't get to schedule tasks to happen at regular intervals when your app is in the background or not running. You also don't get to control whether iOS decides to terminate your app when it's running in the background, so "not running" is a case you'd need to handle (you can't just keep running in the background as for long as you want).
I'm not sure I understand the server side of things though. If your server is manipulating the data until it's acceptable, and it can send push notifications, why does it need to wait for an incoming request from the phone? Why not just send the push when the data is ready? If the app decides what's "acceptable", maybe have the app tell the server what it wants so that the server knows when to send a push.
There are a couple of options that would get close to what you describe. If you implement the "background fetch" feature in your app, iOS will launch the app when it's not running and let it make network calls in the background. There's no guarantee of how often this happens, though. This is described in Apple's background execution docs
The other option is the "silent" push notification. If your server sends one of these, iOS can launch the app in the background to handle the notification. The app could make a network call if necessary. You can send these at whatever time you like, but Apple warns to not overdo it:
Silent notifications are not meant as a way to keep your app awake in the background, nor are they meant for high priority updates. APNs treats silent notifications as low priority and may throttle their delivery altogether if the total number becomes excessive. The actual limits are dynamic and can change based on conditions, but try not to send more than a few notifications per hour.
Silent pushes are described in Apple's push notification docs.
iOS Background Execution Limits
Questions
How do I keep my app running continuously in the background?
If I schedule a timer, how do I get it to fire when the screen is locked?
How do I run code in the background every 15 minutes?
How do I set up a network server that runs in the background?
How can my app provide an IPC service to another one of my app while it’s in the background?
Answer from Apple:
The short answer to all of these is You can’t. iOS puts strict limits on background execution. Its default behavior is to suspend your app shortly after the user has moved it to the background; this suspension prevents the process from running any code.
Official: https://developer.apple.com/forums/thread/685525
I have implemented silent push notifications but I have noticed some strange behaviour. The silent push notifications are handled via:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
The silent push messages only seem to be received if the device is charging (ie cable connected) and/or if my app is foreground.
If I disconnect the device from the charger (or Mac) then the silent push notifications are no longer received unless the app is foreground.
I get non-silent push notifications normally in both cases.
If I plug in the USB cable again, then I get the expected behaviour and silent push notifications are received irrespective of whether the app is foreground or background.
I am using UILocalNotification so I know what is being received.
The fact that it all works fine with the device connected suggests that my silent pushes notifications are configured correctly and that the app has the correct background modes set in the plist etc.
This behaviour is repeatable on iPhone 5s, 6 and iPad 2 all running either IOS 8 or 8.1.
Has anyone else experienced this? It should be easy to reproduce. Why should the simple act of plugging a device into a charger change the ability to receive silent push notifications?
We have experienced the same behavior and have been trying to understand why iOS decides to deliver some notifications and not others.
What we have worked out so far is:
Messages will get received more reliably in background when on wifi than on cellular data. In fact, when on a cellular network (3g/4g), if your signal strength isn't strong enough, iOS receives the push message, but will not wake up your app. We posted in the apple forums about it here: https://devforums.apple.com/message/1069814#1069814. We also opened up a support ticket, and the support team told us to lodge it as a bug report, which we did a couple of weeks ago and are still waiting to hear back.
When you receive a push message, you need to call the fetchCompletionHandler as soon as possible. Technically you have 30 seconds to perform background processing, but iOS has in place a formula whereby the more frequently you send push messages and depending on the amount of time you spend processing those message before returning the app to suspended state, iOS can reduce the amount of times your app gets woken up in the future.
See here from Apple didReceiveRemoteNotification:fetchCompletionHandler: documentation:
As soon as you finish processing the notification, you must call the
block in the handler parameter or your app will be terminated. Your
app has up to 30 seconds of wall-clock time to process the
notification and call the specified completion handler block. In
practice, you should call the handler block as soon as you are done
processing the notification. The system tracks the elapsed time, power
usage, and data costs for your app’s background downloads. Apps that
use significant amounts of power when processing push notifications
may not always be woken up early to process future notifications.
In our testing, we have been sending frequent silent push notifications to our app (every 10 - 30 seconds). And the app is awake for about 3 seconds before we put it back to sleep. We have definitely noticed over time a degradation in the frequency in which our app gets woken up to the point where iOS will only wake up the app every 15 - 30 minutes. So there seems to be some sort of decay/throttling formula in place, but we cannot find any documentation on how it exactly works. We have requested this formula and the variables from apple as a support request, but they said "The information you are requesting is not publicly available" and again asked us to file a bug report.
So, hopefully this is helpful? We are still trying to learn more ourselves which is why I found this question :)
With iOS8 background push delivery to apps has changed. A background push will now only be delivered to the app under certain circumstances. Apple have not stated explicitly what these circumstances exactly are but from my extensive experimentation it basically comes down to if the phone is being charged or not. There are some other variables at play (such as network type, device type, wifi enabled) but the major major major factor is whether the device is being charged or not when the push arrives.
If the phone is being charged via a direct mains power supply or indirectly by being connected by USB to a computer then the background pushes will get delivered to the app the vast majority of the time. But disconnect the phone from the power supply or USB and the background push will almost never get delivered to the app, even if the phone's batter has a 100% charge.
You can very easily test this for yourself just by sending some pushes while the phone is being charged versus while its not. BUT you must take into account that background pushes with a development build and using the sandbox environment DO NOT behave the same as background pushes with a production build and a production environment, the background pushes are actually more likely to be delivered to the app in development then they are in production so it is vital you test using a production build and Apple's production environment to see the actual results.
Note there are two steps the push delivery, the first is it needs to get delivered to the phone itself, the second is once the phone has it, it then needs to get delivered by the OS to the app. In iOS7 things such as turing on Wifi made the chances of the push getting to the phone increase. With iOS8 however even though the push is successfully being delivered to the phone, the OS is not forwarding it on to a background app if the phone isn't being charged. This means the phone gets the notification and holds on to it, sometimes for several hours, before it might forward it to the app if the phone isn't being charged.
I had experienced the same problem and the reason behind not receiving push notification while the app is not charging is that when the Low Power Mode is enabled from Settings > Battery it disables background-fetch feature for all applications.
Which prevents device from receiving push notification.
This link might be useful.
Apple Documentation
I also noticed the same and wasted some time figuring out. See https://stackoverflow.com/a/31237889/1724763
If you turned off Bg App Refresh, silent remote push will be dropped silently (the irony).
However, my observation is that if you connect to Xcode via cable, somehow the Bg App Refresh setting is ignored and all silent push for your app works.
I highly suspect this is an undocumented feature: charging causes the Bg App Refresh setting to be ignored.
It's not working because you have enabled the wrong background mode in the plist. You need to enable the remote-notification tag (App downloads content in response to push notifications), not fetch. Fetch is used for something else. You may also need to use the content available key in your JSON payload, e.g.,
{
"aps": {
"content-available": 1
},
"yourdatakey":{data}
}
I hope you are using APNS delivering priority as "CONSERVE_POWER" (5), try to change it as "IMMEDIATE" (10)
I've been experiencing this problem for some time, and am very grateful for this question and #Kevin D. sharing their understanding. I'm beginning to think that https://stackoverflow.com/a/30834566/1449799 and https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW4 (see priority in one of the tables) are describing why my app is having trouble:
It is an error to use this priority for a push that contains only the content-available key.
To send the notifications, I'm using node-apn where the default (which i also need) is to set the priority to max (10 [beware, it looks like only 10 and 5 are correct values at this time]), but since i wanted a silent notification, i don't have alert, badge, or sound set.
IF YOUR APP IS NOT VoIP YOU CAN'T FOLLOW THIS ANSWER [your app will be rejected]
I found another solution that is worked for me using PushKit Framework
VoIP pushes provide additional functionality on top of the standard push that is needed to VoIP apps to perform on-demand processing of the push before displaying a notification to the user
When I send VOIP Push the App wakes up whatever the state of the Application and can perform any operations
Register for VOIP PushNotification in didFinishLaunchingWithOptions
PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{
if([credentials.token length] == 0) {
NSLog(#"voip token NULL");
return;
}
NSString *originalToken=[NSString stringWithFormat:#"%#",credentials.token];
NSString *token = [originalToken stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"PushCredentials: %#",token);}
then you can handle any background fetch in this function once you receive VOIP PushNotification
-(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type
NOTE: you must use certificate that enable VoIP Services Certificate
Is it possible to keep an iOS app in "Background" state by sending it a silent push notification every few seconds? I want to run background tasks on a regular interval and this seems like a viable solution. If so, is this acceptable under the App Store terms of use?
The app I am planning to build would rely on this functionality and I am concerned that Apple will reject it from the App Store.
Specifically, it’s this section in the guidelines that I am not sure about:
5.1 Apps that send Push Notifications without first obtaining user consent, as well as apps that require Push Notifications to function, will be rejected
Technically my app could be used without allowing push notifications but it wouldn’t serve its primary function of recording data in the background.
In iOS7 additional background modes were added, you can check out the available background modes here.
IMHO, if you misuse one of the background modes, the app will probably be rejected, saying that , i don't think silent push notifications were meant for: keep an iOS app in "Background" state by sending it a silent push notification every few seconds.
another thing is that silent push notifications are rate limited as described here, so i'm not sure if they will be sent every few seconds.
maybe you can use another background service
This is only possible via Cydia. Which means you will need to have a Repository, and jailbroken device for this to work.
The App Store will surely reject this, as it forces other apps to work in the background.