I'm using UNUserNotificationCenter for sending push notifications in iOS.
I'm able to receive the notification when App is in foreground state. But when the App is in the background state, the notification is not received. Whenever the application will come to foreground state, only then will the notification be received.
For register Remote Notification:
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"10.0")) {
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
if( !error ){
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
}
else{
NSLog( #"Push registration FAILED" );
NSLog( #"ERROR: %# - %#", error.localizedFailureReason, error.localizedDescription );
NSLog( #"SUGGESTIONS: %# - %#", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );
}
}];
}
else {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
when the app is in the foreground mode, this method is called:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
But this method is not working in background mode.
I referred to some StackOverflow questions but wasn't able to solve the issue.
Is there anything to add in iOS version 11?
If its a remote notification, this method is called in the app delegate:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
//Handle notification here!
}
Related
my code can get remote notification and remote message, the last problem is can not getting remote message when app in background ( just open app then got it)
When i push remote notification and app in background, it's seem notification message show like expect, click to this notification then it bring me to my app. I dont know why remote message does not have some behavior like that( I using postman and "https://fcm.googleapis.com/fcm/send" to send remote message)
. Plz someone help me
Here is my code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for remote notifications
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
// iOS 7.1 or earlier. Disable the deprecation warnings.
UIRemoteNotificationType allNotificationTypes =
(UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeBadge);
[application registerForRemoteNotificationTypes:allNotificationTypes];
} else {
// iOS 8 or later
// [START register_for_notifications]
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
// iOS 10 or later
UNAuthorizationOptions authOptions =
UNAuthorizationOptionAlert
| UNAuthorizationOptionSound
| UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:authOptions
completionHandler:^(BOOL granted, NSError * _Nullable error) {
}
];
// For iOS 10 display notification (sent via APNS)
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
// For iOS 10 data message (sent via FCM)
[[FIRMessaging messaging] setRemoteMessageDelegate:self];
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
// [END register_for_notifications]
}
// [START configure_firebase]
[FIRApp configure];
// [END configure_firebase]
// Add observer for InstanceID token refresh callback.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tokenRefreshNotification:)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
return YES;
}
// [START receive_message]
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID.
NSLog(#"didReceiveRemoteNotification1 ID: %#", userInfo[#"gcm.message_id"]);
// Print full message.
NSLog(#"didReceiveRemoteNotification1 %#", userInfo);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID.
NSLog(#"didReceiveRemoteNotification2 ID: %#", userInfo[#"gcm.message_id"]);
// Print full message.
NSLog(#"didReceiveRemoteNotification2 %#", userInfo);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
// Print message ID.
NSDictionary *userInfo = notification.request.content.userInfo;
NSLog(#"willPresentNotification: %#", userInfo[#"gcm.message_id"]);
// Print full message.
NSLog(#"willPresentNotification %#", userInfo);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;
NSLog(#"didReceiveNotificationResponse: %#", userInfo);
}
- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {
NSLog(#"%#", [remoteMessage appData]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert" message:[NSString stringWithFormat:#"%#", [remoteMessage appData]] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[alert show];
}
- (void)tokenRefreshNotification:(NSNotification *)notification {
NSString *refreshedToken = [[FIRInstanceID instanceID] token];
NSLog(#"InstanceID token: %#", refreshedToken);
[self connectToFcm];
}
- (void)connectToFcm {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Unable to connect to FCM. %#", error);
} else {
NSLog(#"Connected to FCM.");
}
}];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Unable to register for remote notifications: %#", error);
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"APNs token retrieved: %#", deviceToken);
[[FIRMessaging messaging] setAPNSToken:deviceToken];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self connectToFcm];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[FIRMessaging messaging] disconnect];
NSLog(#"Disconnected from FCM");
}
For other people who face same problem.
Finally after a lot of searching, i found the solution, very simple, u need to follow the content of firebase app message to make it readable by push notification service. U can see here
and here
this is sample to make it show to device when in background mode :)
{
"condition": "'condition1' in topics && 'condition2' in topics",
"notification": {
"category": "notification_category",
"title_loc_key": "notification_title",
"body_loc_key": "notification_body",
"badge": 1
},
"data": {
"data_type": "notification_data_type",
"data_id": "111111",
"data_detail": "FOO",
"data_detail_body": "BAR"
}
}
Now everything work like expect, then the second job is just modify message content like whatever u want :)
here my code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes: (UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}
[application registerForRemoteNotifications];
return YES;
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
NSLog(#"device registered...");
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
// [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
NSString *deviceID = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
deviceID = [deviceID stringByReplacingOccurrencesOfString:#" " withString:#""];
str_DeviceToken = deviceID;
NSLog(#"device token is %#",str_DeviceToken);
}
I neither get any device token error nor get device token when i run this code into device.
I spent a day behind find the issue please help to get device token.
Thanks in advance
I am not getting push in production Mode . while it work fine in developer mode.Here is my code I am newer in iOS and i am first time implementation APN. Please help. I am stuck in lot of time.
if (iOSversion >=8) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication]registerForRemoteNotifications];
}
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)tokenss
{
NSUInteger rntypes;
NSString *device=[[UIDevice currentDevice]systemVersion];
int ar=[device intValue];
if (ar>=8) {
rntypes = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
}
NSString *deviceToken =[self stringWithDeviceToken:tokenss];
NSLog(#"Device token: %#", deviceToken);
callBackToken =deviceToken;
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
{
NSString *errorString = [NSString stringWithFormat: #"Error: %#", err];
NSLog(#"%#",errorString);
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
//handle the actions
if ([identifier isEqualToString:#"declineAction"]){
}
else if ([identifier isEqualToString:#"answerAction"]){
}
}
Such problems are due to current Provisioning Profile does not contain APNS information, as the Provisioning Profile is created BEFORE creating the APNS certificate.
Therefore, to solve the problem, create a new Provisioning Profile & select the Provisioning Profile in Xcode will clear the error.
Also, when you add push, I believe you have updated the certificates in keychain too.
I upgarded my Xcode to Xcode 6.0.1, now remote notification registration is not happening for iOS 8 device. It is working fine for iOS 7 device.
I have added the code in app delegate as mentioned below:
//-- Set Notification
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
NSLog(#"current notifications : %#", [[UIApplication sharedApplication] currentUserNotificationSettings]);
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}
Even the current notification is present, and it is not nil.
And yet the below method is not called :
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
Screenshot below explains that I have enabled certain options in background mode:
And the notification is set in the device settings for my app.
You need to call
[[UIApplication sharedApplication] registerForRemoteNotifications];
in your iOS8 code path, after registering the user notification settings.
Below code will work in iOS 8.0 Xcode 6.0 or later and also for below versions.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//This code will work in iOS 8.0 xcode 6.0 or later
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeNewsstandContentAvailability| UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
return YES;
}
Check following steps hope it will help you
Steps 1 In didFinishLaunchingWithOptions
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
//ios8 ++
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)])
{
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
}
}
else
{
// ios7
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerForRemoteNotificationTypes:)])
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
}
}
Step 2
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings // available in iOS8
{
[application registerForRemoteNotifications];
}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString * token = [NSString stringWithFormat:#"%#", deviceToken];
//Format token as you need:
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
token = [token stringByReplacingOccurrencesOfString:#">" withString:#""];
token = [token stringByReplacingOccurrencesOfString:#"<" withString:#""];
NSLog(#"%#",token);
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
// Handle your remote RemoteNotification
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(#"Error:%#",error);
}
I am new to Objective C. In my app i need to implement push notification, i have created new app ID and i have created new provisioning profile also. i have finished all the steps mentioned in this link
i have declared this delegate function in my appDelegate .m file.
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *deviceTokens = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
deviceTokens = [deviceTokens stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"registered device token %#", deviceTokens);
self.deviceToken = deviceTokens;
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSString *str = [NSString stringWithFormat: #"Error: %#", err];
NSLog(#"String %#",str);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
for (id key in userInfo) {
NSLog(#"key: %#, value: %#", key, [userInfo objectForKey:key]);
}
}
But this delegate functions are not called. please help me to fix this issue.
In your AppDelegated didfinishLaunching with options write the following line
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
Add this code to your application didFinishLaunchingWithOptions method, inside your app delegate
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
//We check because ios7 cannot respond to this method and there will be a crash..
UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
[application registerForRemoteNotifications];
}
else {
//This will work on ios7 devices and below
UIRemoteNotificationType types = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:types];
[application registerForRemoteNotifications];
}
return YES;
Use new delegate method
Swift:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)