Read push notification message without picking from the notification center - iphone

I'm trying to read push message when app is in background or killed and user tap on application icon(which has badge) instead from notification center.I have seen few questions in stackoverflow regarding this, but non of them solve this problem,
Here is the scenario,
I receive a push message.
And then i ignore the message.
Next i launch the application by tapping icon which has badge(not from the notification center)
It won't call didReceiveRemoteNotification: method.
As per iOS application life cycle, it'll run didFinishLaunchingWithOptions: when app launches, and next time it'll call applicationWillEnterForeground: and applicationDidBecomeActive: methods. my question is how can i read all the push messages from above life cycle methods which i received previously and ignored?
I have already tried below snippet in didFinishLaunchingWithOptions: (From this answer) but i always get null as payload.
NSDictionary *pushNotificationPayload = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(pushNotificationPayload) {
NSLog(#"Payload is not null");
[self application:application didReceiveRemoteNotification:pushNotificationPayload];
}else{
NSLog(#"Payload is null");
}
Any valuable answer appreciated, Thanks.
BTW, i use iOS 6

Related

iOS Push notification issue

I am doing a project in which push notification feature is one of the key feature.
It is working fine when I am in the app, I receive notification and handle that notification.
But the issue is when I am in background and notification receives I see badge on my app icon
and when I click on the icon my app is launching but the didReceiveRemoteNotification method is not called so I am unable to handle that notification.
And another issue is some times it shows the notification message in device notification list and some times it didn't .
When I am entering in my app through clicking on notification list item the didReceiveRemoteNotification calls and I am successfully able to handle notification.
I write following code in didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method
NSDictionary* remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotif != nil)
{
NSLog(#"didFinishLaunchingWithOptions\nNotification recieved:\n%#",remoteNotif);
notificationData=[[NSDictionary alloc]initWithDictionary:remoteNotif];
[notif saveNotification:remoteNotif];
}
Help me to resolve this .
Thanks in advance.
Things which you are doing in didfinishlaunch method do in didReceiveRemoteNotification as well.
When you will come from background, didfinishlaunch won't be called.
- (void)application:(UIApplication*)application didReceiveRemoteNotification:
(NSDictionary*)userInfo
{
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive)
{
//What you want to do when your app was active and it got push notification
}
else if (state == UIApplicationStateInactive)
{
//What you want to do when your app was in background and it got push notification
}
}
From Apple's Local And Push Notification programming guide
Handling Local and Remote Notifications
Let’s review the possible scenarios when the system 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 . If the application icon is clicked on a
computer running OS X, the application calls the delegate’s
applicationDidFinishLaunching: method in which the delegate can
obtain the remote-notification payload.
The notification is delivered when the application is running in the foreground.
The application calls its delegate’s
application:didReceiveRemoteNotification: method (for remote
notifications) or application:didReceiveLocalNotification: method
(for local notifications) and passes in the notification payload or
the local-notification object.
So in your case, when application is running in background, and when you click the notification/alert, operating system brings your app into foreground. So it falls under second point.
You can implement application:didReceiveRemoteNotification: method to get the notification payload, if action button is tapped. But when the application icon is pressed instead of action message, the notification payload is not forwarded with the method. Your only option is to contact your server and sync the data. After all as per Apple's policy, push notification only tells that there is data on server, and either way you need to connect to server and get the data.
I did the same thing in one of my application. There is no way to handle notification when clicked on app icon. So, what you can do is to make a server call to get latestPushNotificationIdSync.
You must be storing your data somewhere on server so, you need to check on your server what is the latest latestPushNotificationId.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
notificationContentDict = launchOptions;
if([[launchOptions valueForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"]count]>0){
application.applicationIconBadgeNumber = 0;
NSString *key = [[launchOptions valueForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"] valueForKey:#"id"];
contentId = key;
////// you can use this content id ///// write your code here as per the requirement ..////
//// display your content on UI /// either get from server or local ...///
[self displayContent:[launchOptions valueForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"] application:application];
}
else
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(#"badge count ..%d", application.applicationIconBadgeNumber);
if( application.applicationIconBadgeNumber >0){
if(!notificationContentDict){
make a server call to get "latestPushNotificationIdSync"
application.applicationIconBadgeNumber = 0;
NSLog(#"badge count applicationDidBecomeActive.%d", application.applicationIconBadgeNumber);
}
}
}

get push notification while the app is not running iPhone

I am working on one iPhone app which involves a push notification. As I have seen in many documents and tutorials it suggests to register for push notification with in
application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
like the following:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert| UIRemoteNotificationTypeBadge| UIRemoteNotificationTypeSound];
...
}
now the question is, if the app was not running (even in background), when the push come, it cant process the push message, but if I use the push message again from the notification area and lunch the app again, I can get my message.
what I need to do to make my app get the push message even when it lunch for the first time?
You might be conflating the notion of registering for and receiving notifications. It is impossible for an app to receive a push notification before the registerForRemoteNotificationTypes: method is called the first time, since this method provides the push token that is used to send push notifications in the first place.
So, you must be talking about receiving notifications under the two separate situations in which they can be delivered: upon initial app launch, and during the execution of the program.
In order to handle notifications of the first type, you must inspect the options dictionary sent to application:didFinishLaunchingWithOptions:. The following code shows how to route a notification received at launch to the delegate method that is called when a push notification arrives while the app is already running.
Place this in your application:didFinishLaunchingWithOptions: override:
NSDictionary *pushNotificationPayload = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(pushNotificationPayload) {
[self application:application didReceiveRemoteNotification:pushNotificationPayload];
}

iOS 5 banner push notification disappear, user tap on app icon to start the app

With iOS 5, push notifications can appear as banner and disappear after a few seconds.
I understand that didReceiveRemoteNotification will be called when user taps on the banner.
My question is, if the banner has disappeared and my user sees that there is a badge number on the app, they will tap on the app icon to start the app. Now if the app is running in the background, how do I check that the app is brought to foreground and there has been a notification, and do the necessary?
The purpose of my notification is basically to inform user there has been an update to the app content and encourage them to run the app to get the latest contents. My app only checks for latest contents at launch time and doesn't check for updates periodically.
This question is a bit old, but I'll pop what I've found in here anyway.
There are two methods you need to implement in your app delegate to check if your app was either launched from the remote notification (From when the app is not running on your device), or received the remote notification while running (in the background or foreground).
First is a method that is already in your App Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
To check if this was launched from a remote notification, have some code similar to this:
// Check to see if launched from notification
if (launchOptions != nil)
{
NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
NSLog(#"Launched from push notification: %#", dictionary);
// DO SOMETHING HERE
}
}
The other method you will need to implement is specifically for the case that your application for when your application is running:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"Received notification: %#", userInfo);
}
How you handle the notification from there is up to you, but that's how your app knows about it!
In this second method, you can check the UIApplicationState of the passed application to find out if you were in the foreground or background.

applicationWillTerminate when is it called and when not

Hi I have read several questions on SO about applicationWillTerminate getting called and not getting called.
I wanted to summarize what I understood as there are several posts that speak differently.
For IOS (without multitasking) it is called always when home button is pressed.
For IOS 4 and above
a. it is not called when pressing home button (as the app moves to background)
b. it is called when closing the app from the multi tasking dock and if the app has a sudden terminate flag in info.plist disabled else it is not called. ( I set the "Application should get App Died events" and even then on closing the app from the multitasking dock the terminate function did not get called)
Based on that I had a couple of questions
Is it a good practise to set the Application should get App Died events flag? ( I set the "Application should get App Died events" and even then on closing the app from the multitasking dock the terminate function did not get called)
or
Is registering for "UIApplicationWillTerminateNotification" a better thing to do than the info.plist setting?
Basically I need to do some work only when the app terminates and NOT when it moves to background.
or
EDIT (1):
When the app is terminated the following is sent to the APP. How do I catch it?
Program received signal: “SIGKILL”.
EDIT (2):
Please note : It is not getting called in IOS 4 and above when removing from the multitasking dock. You might think it is. But in my case it is not.
I am asking if anyone knows why? Is there something else I am missing.
Also Note I set the "Application should get App Died events" and even then it is not getting called.
EDIT (3):
The answer for the following question also did not work.
applicationWillTerminate does not get invoked
Anybody facing the similar issue as me?
In short, unless you have UIApplicationExitsOnSuspend in your Info.plist set to YES, in iOS4 and above there is no guarantee that applicationWillTerminate: will ever get called.
As the documentation says:
For applications that support background execution, this method is
generally not called when the user quits the application because the
application simply moves to the background in that case. However, this
method may be called in situations where the application is running in
the background (not suspended) and the system needs to terminate it
for some reason
(Emphasis mine.)
If you need to do something before the app exits you need to do it in applicationDidEnterBackground:. There is no way to catch SIGKILL.
I see -applicationWillTerminate: getting called with the following test. In a new project (I used the 'Single View Application' template), add the following to the AppDelegate:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"%s", __PRETTY_FUNCTION__);
__block UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if (identifier != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:identifier];
identifier = UIBackgroundTaskInvalid;
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
for (int i=0; i < 20; i++) {
NSLog(#"%d", i);
sleep(1);
}
if (identifier != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:identifier];
identifier = UIBackgroundTaskInvalid;
}
});
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
This example will start a background task when the app enters the background. The task is just a 20s delay (with logging once a second) that keeps the app running in the background (note the difference between running in the background and suspended) long enough to allow it to be killed from the app switcher.
So, to test it, run the app, hit the home button to send the app to the background, then before the 20s delay is up, remove the app from the app switcher. After the end of the 20s, -applicationWillTerminate: is called. You can watch the console in Xcode to verify that this is the case.
I tried this in the iOS Simulator for iOS 5.1 and 6.1 (both iPhone) and saw it happen in both cases. I also tested on iPhone 4S running iOS 6.1.2 and saw the same behavior.
As I know, there are 3 situations that your application will die.
Terminated by the end user, you can do something in -[UIApplication applicationWillEnterBackground:], in which case, -[UIApplication applicationWillTerminate:] will NOT be called.
Dropped by the system, such as memory not enough, you can do something in -[UIApplication applicationWillTerminate:], in which case, we do NOT know whether applicationWillEnterBackground: has been called;
Crashed, nothing can be done except using some kind of Crash Reporting Tool. (Edited: catching SIGKILL is impossible)
Source: http://www.cocos2d-iphone.org/forum/topic/7386
I copied my state saving code from applicationWillTerminate to applicationDidEnterBackground and also added a multitaskingEnabled boolean so that I only call state saving in applicationDidEnterBackground. BECAUSE, there is one instance on a multitasking device where applicationWillTerminate is called: If the app is in the foreground and you power off the device. In that case, both applicationDidEnterBackground and applicationWillTerminate get called.
As we know that the App has only 5 sec when -applicationWillTerminate being called. So If someone want to update the server at that point. Than use
Synchronous call.
[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
Note:- -applicationWillTerminate will not call if app is being killed from suspended state. Suspended state means app is not working anything in backgroupd. One of the solution for this is to use background task.
Based on Andrew's test, I understand the docs for applicationWillTerminate(_:) to be meant as having the following clarifications:
For apps that do not support background execution or are linked against iOS 3.x or earlier, this method is always called when the user quits the app. For apps that support background execution, this method is generally not called [right away] when the user quits the app because the app simply moves to the background in that case. However, this method may be called [instead of beginBackgroundTask(expirationHandler:)] in situations where the app is running in the background (not suspended) and the system needs to terminate it for some reason.
// absolute answer applicationWillTerminate
func applicationWillTerminate(application: UIApplication) {
print("applicatoinWillTerminate")
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
step 1: command + shift + h (double click(tab))
step 2: move app top side (kill)
step 3: applicationWillTerminate Work

Push Notifications without alert

Can I get push notifications without alert view?
The idea in what service for game will send notifications as response for change game state (may be game state will store in database), if this is impossible, what you can suggest about how me send new game state to each connected game client as response of changing game state.
Game will be developing for iPad.
Thanks,
Roman
For me #Ajay answer is not correct (sorry).
With push notification you can choose between three user options: text message (alerts), sounds and badges. Every push notification can contain one or more of these options, so you can send for example a notification with sound and badge, but without message and in this case any alert is shown.
Note that you can even pass hidden options in a private dictionary to your application.
Use content-available property:
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.
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html
Why not!
You can send a hidden push notification without any alert, banner or sound.
PHP CODE
without a text:
$payload['aps'] = array('badge'=> 0, 'sound' => 'default');
Without text and sound
$payload['aps'] = array('badge'=> 0);
and on your ios end you can make a condition for this:
//Receiving a Push Notification
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSMutableDictionary *pushNotiFicationDict = [userInfo objectForKey:#"aps"];
NSLog(#":%#", pushNotiFicationDict);
if([pushNotiFicationDict objectForKey:#"alert"])
{
// when push notification has text
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:#"MESSAGE" message:[pushNotiFicationDict objectForKey:#"alert"]
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles:nil];
[alert show];
}
else
{
// when push notification does not have text
}
}
But i think you can not perform any action if application is not running or running in background.
No, a push notification will always display a notification as it requires user consent to wake up or launch your application. However if your Application is in the foreground and running, the push notification will not appear and your app can handle the message that the push notification has. All of the preceding applies to local notifications aswhile.
I don't know what you mean by game state. But just have your app listen in on a script on your server which will pass information to your app. Edit: Or like I said above if your app is open in the foreground, push notifications won't appear on screen and you can send information that way. However if you want to do it in the background its not possible no matter what unless you are truly multitasking (GPS, VOIP, Music) or you have user consent through push notification.
You can handle notifications in app and store data in DB, or instead show a message but when app is not running NO.
I agree with #MacTeo. You can delivery a push notification with a payload that contains only one attribute (Sound, Alert (or message) and badge.
With your requirement, keep track of the users device on the server when they open and close the app (foreground and background). If something happens then you can check to see the device's state on the server. You could then decide on how to construct a notification (if any is necessary) base on the last reported state of the device.
Just spitballing:
You could, if you wanted to (however, it isn't what the APNs is designed to do), deliver a push notification with only a badge count = 0 and pass some extra dictionary data with it. That would not alert the user and could be handled in the app if it was in the foreground.