Is it possible to in iOS to get a push from the server and then to run a method without displaying a notification at all? For example, to check if now is the configured time and if it is to dispaly a notification and if not to send the server a non availble message.
Yes, what you are looking for are silent push notifications which got introduced in iOS 7. Take a look at the docs regarding push notifications which state:
The aps dictionary can also contain the content-available property. The content-available property with a value of 1 lets the remote notification act as a “silent” notification. When a silent notification arrives, iOS wakes up your app in the background so that you can get new data from your server or do background information processing. Users aren’t told about the new or changed information that results from a silent notification, but they can find out about it the next time they open your app.
and
content-available -
number -
Provide this key with a value of 1 to indicate that new content is available. Including this key and value means that when your app is launched in the background or resumed, application:didReceiveRemoteNotification:fetchCompletionHandler: is called.
(Newsstand apps are guaranteed to be able to receive at least one push with this key per 24-hour window.)
You can then react accordingly and eventually actually trigger another notification if you feel like the user needs to be informed about something (not 100% sure about that one though).
A little more in-depth information and code can be found in this objc.io post.
Yes, it is possible:
Implement didReceiveRemoteNotification:fetchCompletionHandler:
Make sure to register for remote notifications, see documentation here:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
return YES;
}
Also make sure to edit Info.plist and check the "Enable Background Modes" and "Remote notifications" check boxes:
Additionally, you need to add "content-available":1 to your push notification payload, otherwise the app won't be woken if it's in the background (see documentation here):
For a push notification to trigger a download operation, the
notification’s payload must include the content-available key with its
value set to 1. When that key is present, the system wakes the app in
the background (or launches it into the background) and calls the app
delegate’s
application:didReceiveRemoteNotification:fetchCompletionHandler:
method. Your implementation of that method should download the
relevant content and integrate it into your app
So payload should at least look like this:
{
"aps" = {
"content-available" : 1,
"sound" : ""
}
}
Just leave the sound property empty and omit the alert/text property and your notification will be silent.
Unfortunately, the app won't be woken up, if it's not running at all (force-quit), see this answer.
Related
I was going to Content-available flag in push notification payload and get doubt over statment which says that if set to "1" iOS will launch the application in background.
Lets assume app is never tapped and opened. So does this mean if recevied this flag app will be actually launched in background.
See here.
But no it won't work. Why? Because you need to launch the app at least once so you get a token. Without a token the server can't differentiate between your device and thousands of other users.
For a push notification to trigger a download operation, the notification’s payload must include the content-available key with its value set to 1. When that key is present, the system wakes the app in the background (or launches it into the background) and calls the app delegate’s application:didReceiveRemoteNotification:fetchCompletionHandler: method. Your implementation of that method should download the relevant content and integrate it into your app.
Apple documentation : Source
In android we can make alert message of push notification dynamically on conditions(data) which comes in push notification payload. i.e piece of code gets executed when push comes and then alert is shown.
Cant we do this in ios? Do we need to send alert message from API all the time? cant we change it on client side(ios)?
In fact, you can. You just need to send a "silent" remote notification, handle the notification in your app and display local notifications depending on the payload. The steps are:
Implement didReceiveRemoteNotification:fetchCompletionHandler:
Make sure to register for remote notifications, see documentation here:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
return YES;
}
Also make sure to edit Info.plist and check the "Enable Background Modes" and "Remote notifications" check boxes:
Additionally, you need to add "content-available":"1" to your push notification payload, otherwise the app won't be woken if it's in the background (see documentation here):
For a push notification to trigger a download operation, the
notification’s payload must include the content-available key with its
value set to 1. When that key is present, the system wakes the app in
the background (or launches it into the background) and calls the app
delegate’s
application:didReceiveRemoteNotification:fetchCompletionHandler:
method. Your implementation of that method should download the
relevant content and integrate it into your app
So payload should at least look like this:
{
aps = {
"content-available" : 1,
sound : ""
};
}
Just leave the sound property empty and omit the alert/text property and your notification will be silent.
Unfortunately, the app won't be woken up, if it's not running at all (force-quit), see this answer.
It's my understanding that the system will either wake you from being closed or running in the background, and allow you to fetch BEFORE it displays the system alert to the user.
I have to download some data to show the user when they tap a push notification.
I am seeing my fetch activities being performed WHILE the push is shown to the user. It is allowing user to tap the notification and launch the app before we've completed the data fetch.
Is this correct?
I didn't have the chance to use push notifications and background fetch mode myself,
but according to the docs:
the system sends the notification to your app (launching it if needed)
and gives it a few moments to process the notification before displaying
anything to the user. You can use those few moments
to download content related to the push notification and
be ready to display it to the user.
so as i understand you are suppose to have some time to react (download data) to a notification before presenting something to the user and not while the notification is shown
the docs don't mention what is considered "few moments" (not that i have seen).
so maybe the download operation is taking more than those "few moments"
hope this helps
Using so-called "silent" push notification in iOS7 you can send specific silent push from your server. You need to add additional key content-available in your aps dictionary
"aps" : {
"alert" : "alert",
"sound" : "sound",
"badge" : badge,
"content-available" : 1
}
Then you need to set two background modes in your project: Remote notifications and Background fetch.
Now every remote push will call for
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
and you can implement any background logic here. For example you can start some fetch process (no longer then 30 seconds!), show custom local notification (which substitutes for standard remote on-screen push) at the moment or on fetch completion.
Be sure that push notifications are allowed for your app in Notification center and that you allow Background App Refresh for your app in Settings/General.
Another important thing is that silent pushes work until you unload you app from background manually (double tap on home button).
Note that this silent mechanism worked incorrectly until iOS7.1
You are in control to choose if to show the AlertView even if using third party like UrbanAirShip.
Any how, you can decide not to show it, initiate background fetch with completion block.
After that you can use local notification to show what ever data you need to show.
Behaviour is little different in iOS 7 and below it.
If you can provide some more code/implementation I might be able to help a bit more.
I wrote a simple messaging system, which allows sending brief messages from web interface to devices, in form of push notification.
On android, everything went well, once device receives notification is sends delivery confirmation receipt back to server, then read acknowledgement. Obviously, delivery confirmation often happens while app is running in background or phone is asleep.
I wrote similar app for iOS. How surprised I was that application: didReceiveRemoteNotification is not called when app is not active!
Is it really impossible to track message delivery without user interaction when app is not active? Others have suggested keeping log of messages on server and sending them when app opens, but this still requires user interaction.
Is there a way around apple restriction on background services? Can I somehow make my app use sound or location service, to allow simple POST request while in background?
In iOS7 you can use push notifications with background fetch, which is a remote notification with the content-available flag set. Example payload: {aps: {content-available: 1}}.
In this case iOS will wake up your app (there are some limitations see: Will iOS launch my app into the background if it was force-quit by the user?).
After your app is woken up you have 30 seconds to send to your server the push notification receipt confirmation.
You'll also have to enable the "Background fetch" capability in the Target background modes and update the AppDelegate to include this method:
- (void)application: (UIApplication *)application didReceiveRemoteNotification:
(NSDictionary *)userInfo fetchCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler
So this requires a bit of work from your side.
I hope this helps.
For iOS there isn't any direct way that provides any info regarding the actual delivery, but I found one workaround which I tried and it is working fine.
Use "Notification service extension", the main use of this is to provide rich notification, so it basically wakes our app whenever new push comes and gives around 30 seconds of time perform our task like download an image to show in the notification. We can use this app wake up feature to call our backend.
So send some unique id with payload and from this method call your backend server with the push id, by this way you can be sure that push notification is delivered into the device.
This will work all state of the application, even in the killed state, so this is full proof and we can rely on this workaround for delivery info.
Reference link: https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension
Mis-using background services is a good way to get your app rejected. Apple are pretty strict on what an app can do in the background.
As a user, if I found out that an app I'd installed was making web requests in the background with no good reason, it would be swiftly deleted!
Push notifications are a one-way message - there is no guarantee that a notification has even been delivered, never mind read. I suggest you read up on the APNS here.
When application is not in Active state application: didReceiveRemoteNotification method won't be called .
If you want track the notification information when application is not in active state follow the below procedure.
application didFinishLaunchingWithOptions: method will be called every time when we open the application
from this method we are getting NSDictionary object called launchOptions. From this launchOptions dictionary we will get the notification data in the form of dictionary for the key UIApplicationLaunchOptionsRemoteNotificationKey
find the code from below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *remoteNotify = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
//Accept push notification when app is not open
if (remoteNotify) // it is only true when you get the notification{
// use the remoteNotify dictionary for notification data}}
http://cydia.saurik.com/package/backgrounder
Check that out, for th source, click on Developers Page.
If its not apples way, there is no way.
That's where jailbreaking comes in. You might have to make your app jailbreak compatible and take advantage of a lot more power.
I'd say for what your looking for, make a new version of Backgrounder that works they way you need it.
I know this is covered in a lot of places, but I cannot figure this out. I use Urban Airship for push notifications. Everything seems to be fine except that when my app is in the background - didReceiveRemoteNotification is not getting called. It works when in the foreground - I am able to properly process messages. And I am able to get to messages from launch options if message is tapped from notifications center. But when in the background, a message it send - iOS displays the alert - didReceiveRemoteNotification is not called. When I tap on my Application icon (not from within notification center) the app comes to the foreground and I have no idea the notification is present. Any ideas?
application:didReceiveRemoteNotification: will call in the background only when you have added content-available key with value 1 into the notification payload.
In case of the Urban Airship, you can send Test Push under the Setting tab.
Sample Payload for Push Notifications:
{
"aps": {
"alert": "aaaa",
"badge": "+1",
"content-available": "1"
},
"device_tokens": [
"86BA71E361B849E8312A7B943BA6B26A74AB436381CF3FEE3CD9EB436A12A292"
]
}
Apple has clearly mentioned in his documentation....
For a push notification to trigger a download operation, the
notification’s payload must include the content-available key with its
value set to 1. When that key is present, the system wakes the app in
the background (or launches it into the background) and calls the app
delegate’s
application:didReceiveRemoteNotification:fetchCompletionHandler:
method. Your implementation of that method should download the
relevant content and integrate it into your app.
https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
From the APNS programming guide :
Let’s review the possible scenarios when the operating delivers a
local notification or a remote notification for an application.
The notification is delivered when the application isn’t running in the
foreground. In this case, the system presents the notification,
displaying an alert, badging an icon, perhaps playing a sound.
As a result of the presented notification, the user taps the action button
of the alert or taps (or clicks) the application icon. If the action
button is tapped (on a device running iOS), the system launches the
application and the application calls its delegate’s
application:didFinishLaunchingWithOptions: method (if implemented); it
passes in the notification payload (for remote notifications) or the
local-notification object (for local notifications).
If the application icon is tapped on a device running iOS, the application
calls the same method, but furnishes no information about the
notification.
I believe the last sentence describes your case, and explains why your application gets no information about the notification.
didReceiveRemoteNotification is calling ONLY if app in foreground or if app is just launched or is bought from background to foreground
link in Apple and some question
Method didFinishLaunchingWithOptions:(NSDictionary *)launchOptions parameter launchOptions one of the dictionary keys are UIApplicationLaunchOptionsRemoteNotificationKey which holds the pressed push notification info.
You can push received info after tour main root controller is initialised. I save it to some property and then push it after view is initialised.
if (launchOptions) {
if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) {
self.notificationToMakeAction = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}
}