I am using
userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler
for getting the notification response in iOS 10, can anyone tell me how to get the Application states in it ?
Because in iOS 9 or before I used
application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
In this method, we can get the application state by
application.applicationState
thanks for the help.
You can get application's state from anywhere in your project something like,
UIApplication *applicaiton = [UIApplication sharedApplication];
if (applicaiton.applicationState == UIApplicationStateBackground) {
NSLog(#"background state");
}
same like you can use UIApplicationStateActive,UIApplicationStateInactive etc to get respective state
I did some search and I got these methods
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog( #"for handling push in foreground" );
// Your code
NSLog(#"%#", notification.request.content.userInfo); //for getting response payload data
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSLog( #"for handling push in background" );
// Your code
NSLog(#"%#", notification.request.content.userInfo); //for getting response payload data
}
Something like this:
NSString * state = #"Unknown";
UIApplication *application = [UIApplication sharedApplication];
if ( application.applicationState == UIApplicationStateInactive ) {
//The application received the notification from an inactive state, i.e. the user tapped the "View" button for the alert.
//If the visible view controller in your view controller stack isn't the one you need then show the right one.
state = #"UIApplicationStateInactive";
}
if(application.applicationState == UIApplicationStateActive ) {
//The application received a notification in the active state, so you can display an alert view or do something appropriate.
state = #"UIApplicationStateActive";
}
if(application.applicationState == UIApplicationStateBackground ) {
state = #"UIApplicationStateBackground";
}
Related
In my app I enabled remote notifications,
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"10.0")){
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
if( !error ){
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}];
}else{
UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
}
And I implemented the delegate methods as follows,
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(#"Failed!!");
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Print message.
if (userInfo) {
NSLog(#"Message ID: %#", userInfo);
}
completionHandler(UIBackgroundFetchResultNoData);
}
But when the app is in foreground and receiving a notification, I got a UIAlertView with the notification title and message. I want to
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(#"User Info : %#",notification.request.content.userInfo);
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionBadge);
}
//Called to let your app know which action was selected by the user for a given notification.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
NSLog(#"User Info : %#",response.notification.request.content.userInfo);
completionHandler();
}
I debugged on willPresentNotification: and after this triggers I got the alert. And I tested by removing this method as well. But still this alert is showing when receiving a notification.
How may I disable this alert view? I'm using 10.2 iOS in my iPhone
I don't think the UIAlertController comes from notifications. Are you sure you are not creating one elsewhere ?
Your notifications' implementation seems ok.
Can you search in your project and using breakpoints to see if any of your UIAlertControllers get hit?
Use UNNotificationPresentationOptionNone in the completionHandler
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(#"User Info : %#",notification.request.content.userInfo);
completionHandler(UNNotificationPresentationOptionNone);
}
For iOS 8 and 9, when the application is in the background, when a push notification is received, I am able to store the information it in the app. But for iOS 10, I cannot retrieve the information when the app is in the background. But only if I open/click on the notification, userNotification centerDidReceiveNotificationResponse is invoked.
For iOS 8 & 9, this works fine.
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
// iOS 10 will handle notifications through other methods
if( SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO( #"10.0" ) )
{
NSLog( #"iOS version >= 10. Let NotificationCenter handle this one." );
// set a member variable to tell the new delegate that this is background
return;
}
NSLog( #"HANDLE PUSH, didReceiveRemoteNotification: %#", userInfo );
// custom code to handle notification content
if( [UIApplication sharedApplication].applicationState == UIApplicationStateInactive )
{
NSLog( #"INACTIVE" );
completionHandler( UIBackgroundFetchResultNewData );
}
else if( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground )
{
NSLog( #"BACKGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
else
{
NSLog( #"FOREGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
}
For iOS 10 the method is not invoked,
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSLog( #"Handle push from foreground" );
// custom code to handle push while app is in the foreground
NSLog(#"%#", notification.request.content.userInfo);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler
{
NSLog( #"Handle push from background or closed" );
// if you set a member variable in didReceiveRemoteNotification, you will know if this is from closed or background
NSLog(#"%#", response.notification.request.content.userInfo);
}
I hope you have follow Below Steps.
Step 1 : Import "UserNotifications" framework.
#import <UserNotifications/UserNotifications.h>
Step 2 : And your AppDelegate confirming "UNUserNotificationCenterDelegate" delegate
#interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>
Step 3 : For iOS10, You can ask for the permission like this
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
if(!error){
// Permission for notifications is granted. Do the other code
}
}];
Now I think the problem you are having in your code in Handling
delegate methods for UserNotifications.
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(#"User Info : %#",notification.request.content.userInfo);
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
//Called to let your app know which action was selected by the user for a given notification.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
NSLog(#"User Info : %#",response.notification.request.content.userInfo);
completionHandler();
}
Your code is missing below line of codes
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
And
completionHandler();
In willPresentNotification and didReceiveNotificationResponse respectively.
My problem is, if app is in background and notification arrives and I opened the app from icon; app restores it states but I want to update the screen data in this case. Is there any way to update the data in background when notification arrives?
Here is the code which I'm using for tackling this case:
ViewController.m file code:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appIsComingFromBackground:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
// Do any additional setup after loading the view, typically from a nib.
}
- (void) appIsComingFromBackground:(NSNotification *) note {
// code
NSString *hasMessage = [[NSUserDefaults standardUserDefaults] objectForKey:#"alertmsg"];
if([hasMessage length]!=0)
{
_labelText.text = hasMessage;
[[NSUserDefaults standardUserDefaults] setObject:#"" forKey:#"alertmsg"];
}
else{
_labelText.text = #"";
}
}
AppDelegate.m file code:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if (application.applicationState == UIApplicationStateActive) {
}
else if(application.applicationState == UIApplicationStateBackground || application.applicationState == UIApplicationStateInactive)
{
[[NSUserDefaults standardUserDefaults] setObject:notification.alertTitle forKey:#"alertmsg"];
}
NSLog(#"Alert Message: %#", notification.alertTitle);
NSLog(#"Alert Body: %#", notification.alertBody);
}
Application is NOT Running
When the app is not running, users see notifications in the following ways, depending on the notification settings:
Displaying an alert or banner
Badging the app icon
Playing a sound
By tapping on action button of the notification, users will launch the app. In this case, the application:didFinishLaunchingWithOptions: method of the application delegate is called.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Handle launching from a notification
UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (locationNotification) {
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
}
return YES;
}
Applicaton is Running in Foreground
If the app is running while the notification is delivered, there is no alert displayed on screen. The application automatically calls its delegate’s application:didReceiveLocalNotification: method.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
}
// Request to reload table view data
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadData" object:self];
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
}
Application is Running in Background
The app has been launched before but users switch to another app. When the notification is fired, users normally see an alert banner at the top of the screen. When it’s tapped, the app will be brought to the foreground. Similar to the case that the app is running in foreground, the application automatically calls its delegate’s application:didReceiveLocalNotification: method.
In Appdelegate
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification
{
if (application.applicationState == UIApplicationStateActive) {
}
else if(application.applicationState == UIApplicationStateBackground || application.applicationState == UIApplicationStateInactive)
{
// [[NSUserDefaults standardUserDefaults] setObject:notification.alertTitle forKey:#"alertmsg"];
[[NSNotificationCenter defaultCenter]postNotificationName:#"PushNotificationReceived" object:nil userInfo:userInfo];
}
NSLog(#"Alert Message: %#", notification.alertTitle);
NSLog(#"Alert Body: %#", notification.alertBody);
}
In view controller:
-(void)viewDidLoad
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(doChangesWhatdidYouWant:) name:#"PushNotificationReceived" object:nil];
}
-(void)doChangesWhatdidYouWant:(NSNotification *)notification{
//Todo
}
I'm implementing push notifications in iOS 10. Everything working well.
But I need to hit API when APP received push notification (not only in Active state but also in background/terminated).
For this I'm using NSNotificationCenter for listening notification when App received push notification like this :
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSDictionary *userInfo = notification.request.content.userInfo;
NSLog(#"Message ID: %#", userInfo[#"gcm.message_id"]);
NSLog(#"%#", userInfo);
if( [UIApplication sharedApplication].applicationState == UIApplicationStateInactive )
{
NSLog( #"INACTIVE" );
completionHandler( UNNotificationPresentationOptionAlert );
}
else if( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground )
{
NSLog( #"BACKGROUND" );
completionHandler( UNNotificationPresentationOptionAlert );
}
else
{
NSLog( #"FOREGROUND" );
completionHandler( UNNotificationPresentationOptionAlert );
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTheTable" object:nil];
}
And I'm listening this notification in ViewController.m like this
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTable:) name:#"reloadTheTable" object:nil];
}
- (void)reloadTable:(NSNotification *)notification
{
// Calling API here
}
This is working fine when the app is running in the foreground.
But not in background and terminate states.
Is there any mistake by me or anything else I have to implement?
From iOS 10, we must add UserNotifications framework and delegate
So first we need to do below things in appDelegate.h
#import <UserNotifications/UserNotifications.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>
For FOREGROUND state
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSLog( #"Handle push from foreground" );
// custom code to handle push while app is in the foreground
NSLog(#"%#", notification.request.content.userInfo);
}
This is for BACKGROUND state.
So here you need to add the notification
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler
{
NSLog( #"Handle push from background or closed" );
// if you set a member variable in didReceiveRemoteNotification, you will know if this is from closed or background
NSLog(#"%#", response.notification.request.content.userInfo);
//Adding notification here
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTheTable" object:nil];
}
didReciveRemoteNotificationNotCalled in iOS 10
In my iOS Application, I want to hide UIAlertView when receiving push notification in didreceiveRemotenotification method.
Whole page of app delegate I am not writting code for show UIAlertView. Then why does it display automatically?
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[PFPush handlePush:userInfo];
if (application.applicationState == UIApplicationStateActive) { self.noti_json=[userInfo objectForKey:#"msg"];
[[NSNotificationCenter defaultCenter] postNotificationName:[userInfo objectForKey:#"title"] object:self];
} }
Thanks in Advance.
Edit (Adding code for my didReceiveRemoteNotification:):
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[PFPush handlePush:userInfo];
if (application.applicationState == UIApplicationStateActive)
{
self.noti_json=[userInfo objectForKey:#"msg"];
[[NSNotificationCenter defaultCenter] postNotificationName:[userInfo objectForKey:#"title"] object:self];
}
}
Remove the line [PFPush handlePush:userInfo];
and show your own alert only if the type is not the one you wanna avoid.
UserInfo must have some identifier or type of notification so that you can handle type specific notifications accordingly.
Handle Push
Edit
Or Simply use below line
if(![[userInfo objectForKey:#"type"] isEqualToString:#"typeName"]){
[PFPush handlePush:userInfo];
}
If you're receiving alerts for Push Notifications it can be due to having the Alerts enabled in settings for your app.