I am trying lot but not succeed yet to get silent notification when app is killed state
Here code I am trying ..
APS data:
{
"aps": {
"content-available": 1,
"sound": ""
}
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSDictionary *userInfo1 = userInfo;
NSLog(#"userInfo: %#", userInfo1);
//self.textView.text = [userInfo description];
// We can determine whether an application is launched as a result of the user tapping the action
// button or whether the notification was delivered to the already-running application by examining
// the application state.
if (application.applicationState == UIApplicationStateActive)
{
//opened from a push notification when the app was on background
NSLog(#"userInfoUIApplicationStateactive->%#",[userInfo objectForKey:#"aps"]);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Did receive a Remote Notification" message:[NSString stringWithFormat:#"Your App name received this notification while it was Running:\n%#",[[userInfo objectForKey:#"aps"] objectForKey:#"alert"]]delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else
{
// a push notification when the app is running. So that you can display an alert and push in any view
NSLog(#"userInfoUIApplicationStateBackground->%#",[userInfo objectForKey:#"aps"]);
[self scheduleAlarmForDate1:[NSDate date]alarmDict:userInfo];
}
}
In the payload’s aps dictionary must not contains the alert, sound, or badge keys.
{
"aps":{
"content-available" : 1
}
}
Please try this.
You should implement as in AppDelegate.m
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
NSDictionary *aps = [userInfo objectForKey:#"aps"];
NSLog(#"hello");
NSLog(#"userinfo---->>>>%#",userInfo);
[UIApplication sharedApplication].applicationIconBadgeNumber=[[aps objectForKey:#"badge"] integerValue];
[self application:application didReceiveRemoteNotification:userInfo];
}
Related
I use APNs to send the notifications to my app. But my app does not work well when I did the following steps:
steps
swipe the app to force quit (app is not running, not in background mode ..)
send the notification from APNs
got the notification on my iPhone and I tapped the notification banner
app seemed to try to launch(showed the launch image), but launched fail (crash?)
my app can receive notification foreground and background.
Tap the notification banner in background then it can bring app to foreground then go to the view I wrote, everything works fine.
Except force quit the APP
here is my code in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController:[self navigationController]
leftMenuViewController:leftMenuViewController
rightMenuViewController:rightMenuViewController];
self.window.rootViewController = container;
[self.window makeKeyAndVisible];
UIMutableUserNotificationAction *acceptAction =
[[UIMutableUserNotificationAction alloc] init];
// Define an ID string to be passed back to your app when you handle the action
acceptAction.identifier = #"MARK_AS_READ_IDENTIFIER";
// Localized string displayed in the action button
acceptAction.title = NSLocalizedString(#"Mark as Read", nil);
// If you need to show UI, choose foreground
acceptAction.activationMode = UIUserNotificationActivationModeBackground;
// Destructive actions display in red
acceptAction.destructive = NO;
// Set whether the action requires the user to authenticate
acceptAction.authenticationRequired = NO;
// First create the category
UIMutableUserNotificationCategory *inviteCategory =
[[UIMutableUserNotificationCategory alloc] init];
// Identifier to include in your push payload and local notification
inviteCategory.identifier = #"actionCategory";
// Add the actions to the category and set the action context
[inviteCategory setActions:#[acceptAction]
forContext:UIUserNotificationActionContextDefault];
// Set the actions to present in a minimal context
[inviteCategory setActions:#[acceptAction]
forContext:UIUserNotificationActionContextMinimal];
NSSet *categories = [NSSet setWithObject:inviteCategory];
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert) categories:categories]];
// for calling didReceiveRemoteNotification when app first launch
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
[self application:application didReceiveRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]];
}
return YES;
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
//register to receive notifications
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"Device token: %#",deviceToken);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Fail to get device token: %#", error);
}
// tap the backgraund banner button
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)newUserInfo completionHandler:(void (^)())completionHandler {
if ([identifier isEqualToString:#"MARK_AS_READ_IDENTIFIER"]) {
// when tapping the background banner's button will mark the notification status to read
[Functions updateComingNotificationToRead];
}
if (completionHandler) {
completionHandler();
}
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)newUserInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
//NSLog(#"Notification received: %# %#", newUserInfo,[newUserInfo objectForKey:#"aps"] );
userInfo = newUserInfo;
NSString *alertMessage = [[newUserInfo objectForKey:#"aps"] objectForKey:#"alert"];
UIApplicationState state = [application applicationState];
UIAlertView *alertView = nil;
// for background banner use
switch (state) {
case UIApplicationStateActive: // when app is alive, show alert to notify user
alertView = [[UIAlertView alloc]initWithTitle:NSLocalizedString(#"SmartHome",nil) message:NSLocalizedString(alertMessage,nil) delegate:self cancelButtonTitle:NSLocalizedString(#"Close",nil) otherButtonTitles:NSLocalizedString(#"Open",nil),NSLocalizedString(#"Mark as Read",nil), nil];
[alertView show];
break;
case UIApplicationStateBackground: // app is in background mode
// user tap the banner or tap the mark as read button, code will go here
[Functions addNotificationDataInDatabase:[newUserInfo objectForKey:#"uniqueID"] type:[newUserInfo objectForKey:#"deviceType"] event:[newUserInfo objectForKey:#"event"] time:[newUserInfo objectForKey:#"time"] read:#"0" description:alertMessage];
break;
case UIApplicationStateInactive: // tapping the banner
//NSLog(#"UIApplicationStateInactive");
// go to notification view
// because will go to the notification view detail, set status to read
[self gotoNotificationView:userInfo]; //uniqueID
break;
default:
break;
}
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
handler(UIBackgroundFetchResultNoData);
// send post notification for updating the badge, will get the notification in foreground
[[NSNotificationCenter defaultCenter] postNotificationName:#"APNsNotification" object:self userInfo:nil];
}
Does anyone have this problem before? Did I miss something?
Please help me!!
u can put alert and check launchOptions
if (launchOptions) {
if ([launchOptions objectForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"]) {
[self application:self didReceiveRemoteNotification:[launchOptions objectForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"] fetchCompletionHandler:^(UIBackgroundFetchResult result) {
}];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)newUserInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) {
NSString *str = [[userInfo objectForKey:#"aps"] objectForKey:#"alert"];
}
}
I know how to show a push notifications UIAlertView if the app is in the background or foreground using the following code:
(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSString *message = [ [userInfo objectForKey:#"aps"]
objectForKey:#"alert"];
UIAlertView *alert = [ [UIAlertView alloc]
initWithTitle:#""
message:message
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
However, I also want to show an alert view if the app was completely closed and the user wants to open the app via the push notifications.
How can I achieve this?
Thanks
When application launches as a result of a push notification, in other words, when the app was not running, you need to handle that case in [AppDelegate application:didFinishLaunchingWithOptions:] method.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Push Notification" message:notification[#"aps"][#"alert"] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
}
If the app is in background or foreground (active) state, you need to handle that case in [AppDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] method.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
if (application.applicationState == UIApplicationStateActive) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Push Notification" message:userInfo[#"aps"][#"alert"] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else if (application.applicationState == UIApplicationStateBackground || application.applicationState == UIApplicationStateInactive) {
// Do something else rather than showing an alert view, because it won't be displayed.
}
}
For more information, you can take a look at Local and Remote Notification Programming Guide from Apple.
(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo ;
and
- (void)application:(UIApplication *)application didReceiveRemoteNotification:
(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult
result))completionHandler{};
never get called ,although i receive the notification on the iphone, Is there any other function that needs to be added for this to work?.Thank you.
Update
I tried this when the app is not in background nor active but i didnt receive the message.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set app's client ID for |GPPSignIn| and |GPPShare|.
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
// Clear application badge when app launches
application.applicationIconBadgeNumber = 0;
if ([[launchOptions allKeys] containsObject:UIApplicationLaunchOptionsRemoteNotificationKey]) {
id userInfo=[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:#"MESSAGE" message:userInfo delegate:self cancelButtonTitle:#"ok" otherButtonTitles: nil];
[alert show];
}
if your application close and get notification .....
add below code in didFinishLaunchingWithOptions
if ([[launchOptions allKeys] containsObject:UIApplicationLaunchOptionsRemoteNotificationKey])
{
id userInfo=[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSLog(#"%#",[[userInfo objectForKey:#"aps"] objectForKey:#"alert"]);
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:#"MESSAGE" message:[[userInfo objectForKey:#"aps"] objectForKey:#"alert"] delegate:self cancelButtonTitle:#"ok" otherButtonTitles: nil];
[alert show];
}
but this call when you click on notification
I'm using apple push notification service in my project.
Please follow the 2 ways of opening the app and handling this push notifications. In the second scenario I do not know how to handle it. Do you know how?
The push notification arrived to my device,
Scenario 1:
I clicked on the push notification.
The - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo function AppDelegate.m file catches this function.
Scenario 2:
I normally opened the device (by clicking on the app)
How can I handle the push notification?
The other answers show how to get the notification data when the user taps the notification.
The difference between the two nethods shown is that one is called when app is already running, either in foreground or background, while the other is called when app is not running at all.
On your second case, when the user doesn't tap the notification, the notification data isn't passed to the app when you open it with the launch Icon.
First scenario:
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
{
NSLog (#"APNS: notification received: %#", userInfo);
NSString *message = nil;
id alert = [userInfo objectForKey:#"aps"];
if ([alert isKindOfClass:[NSString class]])
{
message = alert;
}
else if ([alert isKindOfClass:[NSDictionary class]])
{
message = [alert objectForKey:#"alert"];
}
if (message)
{
if (![message isEqualToString:#""])
{
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: #"notification"
message: message
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
}
Second scenario:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog (#"LAUNCH OPTIONS: %#",launchOptions);
id remoteNotificationValue = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotificationValue)
{
NSString *message = nil;
id alert = [remoteNotificationValue objectForKey:#"aps"];
if ([alert isKindOfClass:[NSString class]])
{
message = alert;
}
else if ([alert isKindOfClass:[NSDictionary class]])
{
message = [alert objectForKey:#"alert"];
}
if (message)
{
if (![message isEqualToString:#""])
{
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: #"notification"
message: message
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
}
....
Of course you might want to make a special method that handles notifications and is called from both scenarios (with NSDictionary * parameter) so your code would be more readable. Sometimes APNS notifications are useful also when app is running - empty notification (with no payload) might be used to trigger the data synchronization with server to avoid polling for example.
You can get the arrived notifications when the app starts with the following code (e.g: in application:didFinishLaunchingWithOptions):
NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
Here is a more thorough explanation: How to manage notification when users click on badge
You can handle that like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Checking if app was launched from the notification
if (launchOptions != nil) {
NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil){
// Read dictionary and do something since the app
// was launched from the notification.
}
}
Here is an example of what the dictionary object contains
NSString *message = #"";
NSString *badge = #"";
NSString *sound = #"";
if([dictionary objectForKey:#"alert"]) {
message = [dictionary objectForKey:#"alert"];
}
if([dictionary objectForKey:#"badge"]) {
badge = [dictionary objectForKey:#"badge"];
}
if([dictionary objectForKey:#"sound"]) {
sound = [dictionary objectForKey:#"sound"];
}
Hope it helps!
I am using following code,
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//code here to handle call
//[[UIApplication sharedApplication] openURL:
// [NSURL URLWithString:#"tel:1-408-555-5555"]];
UIAlertView *alert1=[[UIAlertView alloc]initWithTitle:#"Teshjhjkhhjkhjkhjkhkjhkhkhkjhjkhjkkkjhjhhjhjkjt" message:#"Test" delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil];
[alert1 show];
[alert1 release];
}
but when application is open I can see the alert, but I want this alert when I press the view button in push message.
Try to implement in this format:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
application.applicationIconBadgeNumber = 0;
self.textView.text = [userInfo description];
// We can determine whether an application is launched as a result of the user tapping the action
// button or whether the notification was delivered to the already-running application by examining
// the application state.
if (application.applicationState == UIApplicationStateActive)
{
// Nothing to do if applicationState is Inactive, the iOS already displayed an alert view.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Did receive a Remote Notification"
message:[NSString stringWithFormat:#"The application received this remote notification while it was running:\n%#",
[[userInfo objectForKey:#"aps"] objectForKey:#"alert"]]
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
}