46

I am checking my app compatibility with iOS 8, I am getting following Log in console "Attempting to badge the application icon but haven't received permission from the user to badge the application" . Can anyone please help me to get rid of this warning. And Yes, my app shows Badges on App Icon and TabBar Icon.

Hemant Chittora
  • 3,152
  • 3
  • 19
  • 25

11 Answers11

43

Here is What I did in my AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // registering for remote notifications
    [self registerForRemoteNotification];
    return YES;
}


- (void)registerForRemoteNotification {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
        UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
        UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    } else {
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    }
}

#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [application registerForRemoteNotifications];
}
#endif
Hemant Chittora
  • 3,152
  • 3
  • 19
  • 25
  • 3
    the `SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(...)` macros isn't declared by default. i'm getting a warning. are you using this [gist](https://gist.github.com/alex-cellcity/998472)? – Julian B. Dec 03 '14 at 15:09
  • Yes I am using the same gist. – Hemant Chittora Dec 03 '14 at 16:25
  • 3
    the #ifdef __IPHONE_8_0 is not needed since that delegate method wont be called unless you are actually using ios 8 or higher. – Pochi Dec 08 '14 at 05:32
  • 2
    you can also use `if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])` to detect whether you can call iOS 8.0 method – milkplus May 27 '15 at 23:11
  • `NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0` is preferred. – DawnSong Jan 04 '16 at 02:46
16

Apple makes new API for registering notifications and working with badges.

See WWDC 2014 session video: https://developer.apple.com/videos/wwdc/2014/?id=713 , http://asciiwwdc.com/2014/sessions/713 (text version) and https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/index.html#//apple_ref/occ/instm/UIApplication/registerUserNotificationSettings:

User can change permissions for every UIUserNotificationType (UIUserNotificationTypeBadge, UIUserNotificationTypeSound, UIUserNotificationTypeAlert) in Settings.

Before changing badge you must check permissions.

Code sample from my AppDelegate:

- (BOOL)checkNotificationType:(UIUserNotificationType)type
{
  UIUserNotificationSettings *currentSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
  return (currentSettings.types & type);
}

- (void)setApplicationBadgeNumber:(NSInteger)badgeNumber
{
  UIApplication *application = [UIApplication sharedApplication];

  if(SYSTEM_VERSION_LESS_THAN(@"8.0")) {
    application.applicationIconBadgeNumber = badgeNumber;
  }
  else {
    if ([self checkNotificationType:UIUserNotificationTypeBadge]) {
      NSLog(@"badge number changed to %d", badgeNumber);
      application.applicationIconBadgeNumber = badgeNumber;
    }
    else {
      NSLog(@"access denied for UIUserNotificationTypeBadge");
    }
  }
}

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

The currentUserNotificationSettings method is available in the UI application instance and will give you the most up-to-date user notification preferences.

Working with badge number:

[self setApplicationBadgeNumber:0];

instead of

application.applicationIconBadgeNumber = 0;
KepPM
  • 1,129
  • 7
  • 17
9

You can use

    #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
        if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])
        {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
            [[UIApplication sharedApplication] registerForRemoteNotifications];
        } else
        {
            [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
             (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
        }
    #else
       [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    #endif
KlimczakM
  • 12,576
  • 11
  • 64
  • 83
user2885077
  • 702
  • 6
  • 14
7

I came across this answer whilst looking for a solution in Swift. I have done the following (assuming iOS 8):

UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, categories: nil))
UIApplication.sharedApplication().registerForRemoteNotifications()
djbp
  • 714
  • 8
  • 24
  • For newbs like me, this goes in the `AppDelegate.swift` file in the `didFinishLaunchingWithOptions` function and the alert message that comes up when the app is launched asks about all the notification types even if you remove some from that list. – Jed Grant Jun 03 '15 at 18:33
5

Rather than checking the IOS Version i would check if the UIUserNotificationSettings exists and register for BadgeType like we used to do with remote notifications.

Class userNotification = NSClassFromString(@"UIUserNotificationSettings");

if (userNotification)
{
    UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
}
Ilker Baltaci
  • 11,644
  • 6
  • 63
  • 79
5

If you want use Local Notification use Below Code:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 


    [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
    [[UIApplication sharedApplication] registerForRemoteNotifications];

#else

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
 (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

#endif
narner
  • 2,908
  • 3
  • 26
  • 63
Subathra D
  • 389
  • 3
  • 7
3

iOS 8 has an application method called registerUserNotificationSettings:. Part of the docs say, "If your app displays alerts, play sounds, or badges its icon while in the background, you must call this method during your launch cycle to request permission to alert the user in those ways."

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • Thanks @Phillip for your quick reply. Will it work in iOS 6 and 7 also ? Or do we need to put any check for that? – Hemant Chittora Sep 22 '14 at 12:48
  • Check for the OS version that you're running. If you look at the method in its header, it says "NS_AVAILABLE_IOS(8_0)", so you can't call it on an earlier version. – Phillip Mills Sep 22 '14 at 12:56
1

You can use

if(SYSTEM_VERSION_LESS_THAN(@"8.0"))
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
else
{
    [[UIApplication sharedApplication] registerForRemoteNotifications];
}

....

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

For push notification, I think it will solve it, in my case on simulator I get this warning as it doesn't support push and i the user reject the permission than again you will have that warning. Thank You.

souvickcse
  • 7,742
  • 5
  • 37
  • 64
0
+ (BOOL)canBadgeTheApp {
    BOOL canBadgeTheApp;
    if ([UIDevice currentDevice].systemVersion.doubleValue >= 8) {
        UIUserNotificationType types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
        canBadgeTheApp = ((types & UIRemoteNotificationTypeBadge) != 0);
    } else {
        canBadgeTheApp = YES;
    }
    return canBadgeTheApp;
}
Lucien
  • 8,263
  • 4
  • 30
  • 30
  • 1
    as Apple Always says, DO NOT use #define or version to test for a feature, use selector: respondsToSelector.. as mikplus noted. – ingconti Jun 04 '15 at 13:53
0

for "swifters" the above code:

final func checkNotificationType(type : UIUserNotificationType) -> Bool {

    let application = UIApplication.sharedApplication()
    if application.respondsToSelector(Selector("registerUserNotificationSettings:")) {
        // iOS8 and above
        let currentSettings : UIUserNotificationSettings = application.currentUserNotificationSettings()
        let types = currentSettings.types
        return types.rawValue & type.rawValue > 0
    }else{
        return true
    }
}
ingconti
  • 10,876
  • 3
  • 61
  • 48
0

the only thing you need is

if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0)       {
// here you go with iOS 8
} else {

}