- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
This code is for registering for UILocalNotification and this will also popup this:
Question 1: At this state when user has not chosen any option, How do I get notified when user choose one of the option which is Don't Allow or Ok? So I can execute app accordingly.
--
UIUserNotificationSettings *current = [[UIApplication sharedApplication] currentUserNotificationSettings];
UIUserNotificationType required = UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
if(current.types & required) {
NSLog(#"Permission present: %lu", (unsigned long)current.types);
} else {
NSLog(#"Permission not present: %lu", (unsigned long)current.types);
}
When app will launch after first time, with this code I am trying to fetch which permission user has allowed (maybe he goto settings and disabled all types of notification alerts).
Question 2: I am simply getting numbers in log like 7 for the types of permission I am checking and 0 if user has not allowed the UILocalNotification. How to check for permissions correctly?
I used the below method in one of my project to determine whether the user has given permission or not, or whether he/she actually turned off the notifications in settings. Put this method in Appdelegate and check
-(BOOL)notificationServicesEnabled {
BOOL isEnabled = NO;
if ([[UIApplication sharedApplication] respondsToSelector:#selector(currentUserNotificationSettings)]){
UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
isEnabled = NO;
} else {
isEnabled = YES;
}
} else {
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert) {
isEnabled = YES;
} else{
isEnabled = NO;
}
}
return isEnabled;
}
Then you can simple check with condition
if([self notificationServicesEnabled])
Related
I need to check if user have enabled push notifications in Settings. For this I use this code:
if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications] == NO) {
NSLog(#"NO");
// NO
}
if ([[UIApplication sharedApplication]respondsToSelector:#selector(currentUserNotificationSettings)]){
UIUserNotificationSettings *noticationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (!noticationSettings || (noticationSettings.types == UIUserNotificationTypeNone)) {
NSLog(#"NO");
// here it does not work, I enabled push notifications
// in settings and noticationSettings.types returns UIUserNotificationTypeNone
// NO
} else {
NSLog(#"YES");
// YES
}
}
but problem is that noticationSettings.types returns alwyas UIUserNotificationTypeNone, regardless whether are push notifications enabled in Settings or not.
As you can see on the picture, I have enabled push notifications, but noticationSettings.types returns me UIUserNotificationTypeNone, can anybody tell me where could be the problem? Thanks
Your screenshot indicates that you did not call registerUserNotificationSettings with UIUserNotificationTypeBadge or UIUserNotificationTypeSound or UIUserNotificationTypeAlert.
Try the following:
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
|UIUserNotificationTypeSound
|UIUserNotificationTypeAlert) categories:nil];
UIApplication *application = [UIApplication sharedApplication];
[application registerUserNotificationSettings:settings];
Hi in my app i have notification section and user can enable notifications using switch.After first launch when ever user on the switch i am getting don't allow or ok alertview from ios.If user select don't allow and switch will be off and user will not get notifications. Now if user try to on the switch i want to show an alert to user with text "Please enable notifications from settings".Can any one please suggest the way to do this.
For UILocalNotification permission check the following, types parameter value will be none incase user has not allowed it.
[[UIApplication sharedApplication] currentUserNotificationSettings]
You can check the the permission using isRegisteredForRemoteNotifications method.
- (void)checkForNotificationPermission
{
if (!([[UIApplication sharedApplication] isRegisteredForRemoteNotifications] && [self pushNotificationsEnabled]))
{
// Show alert here
}
}
// For fixing iOS 8 issue mentioned here http://stackoverflow.com/a/28441181/1104384
- (BOOL)pushNotificationsEnabled
{
if ([[UIApplication sharedApplication] respondsToSelector:#selector(currentUserNotificationSettings)])
{
UIUserNotificationType types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
return (types & UIUserNotificationTypeAlert);
}
else
{
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
return (types & UIRemoteNotificationTypeAlert);
}
}
NSString *iOSversion = [[UIDevice currentDevice] systemVersion];
NSString *prefix = [[iOSversion componentsSeparatedByString:#"."] firstObject];
float versionVal = [prefix floatValue];
if (versionVal >= 8)
{
if ([[UIApplication sharedApplication] currentUserNotificationSettings].types != UIUserNotificationTypeNone)
{
NSLog(#" Push Notification ON");
}
else
{
NSString *msg = #"Please press ON to enable Push Notification";
UIAlertView *alert_push = [[UIAlertView alloc] initWithTitle:#"Push Notification Service Disable" message:msg delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Setting", nil];
alert_push.tag = 2;
[alert_push show];
NSLog(#" Push Notification OFF");
}
}
else
{
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types != UIRemoteNotificationTypeNone)
{
NSLog(#" Push Notification ON");
}
else
{
NSString *msg = #"Please press ON to enable Push Notification";
UIAlertView *alert_push = [[UIAlertView alloc] initWithTitle:#"Push Notification Service Disable" message:msg delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Setting", nil];
alert_push.tag = 2;
[alert_push show];
NSLog(#" Push Notification OFF");
}
}
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIAp
plication sharedApplication] registerUserNotificationSettings:settings];
// [[UIApplicationsharedApplication]registerForRemoteNotifications];
if ([[UIApplication sharedApplication] respondsToSelector:#selector(currentUserNotificationSettings)]) {
UIUserNotificationType types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
if (types == UIUserNotificationTypeNone) {
[_TransparentView setBackgroundColor:[[UIColor clearColor] colorWithAlphaComponent:0.8]];
lblDescription.text=#"Please enable notifications from settings.";
}
}
}
Try this code. It will work for iOS 8.0 later and before versions.
if (([[[UIDevice currentDevice] systemVersion] compare:8.0 options:NSNumericSearch] != NSOrderedAscending)) {
if (![[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
{
DisplayAlert(#"Please enable Permission from Settings->App Name->Notifications->Allow Notifications");
return;
}
}
else{
UIRemoteNotificationType status = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (status == UIRemoteNotificationTypeNone)
{
DisplayAlert(#"Please enable Permission from Settings->App Name->Notifications->Allow Notifications");
return;
}
}
I'm trying to check if PushNotifications for my app are enabled.
In AppDelegate.m I do register app for remote notifications, and in Settings on iPhone (iOS 8) Push Notifications for this app are enabled.
I've googled to methods:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
BOOL check = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
As the result, types = UIRemoteNotificationTypeNone and check = NO.
I'm using this code sample to register application for Push Notifications:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
//-- Set Notification
if ([application respondsToSelector:#selector(isRegisteredForRemoteNotifications)])
{
// iOS 8 Notifications
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
}
else
{
// iOS < 8 Notifications
[application registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}
//--- your custom code
return YES;
}
What is the problem here?
I think you've already found a solution but just in case: in iOS 8, enabledRemoteNoficationTypes is deprecated you should use:
if ([[UIApplication sharedApplication] respondsToSelector:#selector(currentUserNotificationSettings)]) {
UIUserNotificationSettings *currentSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (currentSettings.types == UIUserNotificationTypeNone) {}
Best
Try checking your state with this code:
UIRemoteNotificationType allOnType = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge ;
UIRemoteNotificationType offType = UIRemoteNotificationTypeNone ;
UIRemoteNotificationType currentTypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (currentTypes == allOnType) {
// all are on
} else if (currentTypes == offType) {
// all are off
} else {
// some are on, some are off
}
Edit
Also, try implementing the Push Notification Callbacks:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSLog(#"Token%#",deviceToken);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
{
NSLog(#"err:%#",err);
}
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//for iOS8
}
I can check if user granted notification (alert) permission or not before iOS8 like that:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
{
//user granted
}
it is not working on iOS8, it says:
iOS (3.0 and later) Deprecated:Register for user notification settings using the registerUserNotificationSettings: method instead.
console says:
enabledRemoteNotificationTypes is not supported in iOS 8.0 and later.
so how can I check it on iOS 8?
Ok I solved my problem like this:
BOOL isgranted = false;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([[UIApplication sharedApplication] respondsToSelector:#selector(isRegisteredForRemoteNotifications)])
{
isgranted = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
}
#else
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
{
isgranted = true;
}
#endif
I expanded on woheras answer a bit to be more dynamic
- (BOOL)pushNotificationsEnabled
{
BOOL isgranted = false;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){
if ([[UIApplication sharedApplication] respondsToSelector:#selector(isRegisteredForRemoteNotifications)])
{
isgranted = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
}else{
}
}else{
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
{
isgranted = true;
}else{
}
}
return isgranted;
}
I didn't have much luck using isRegisteredForNotifications. I ended up using currentUserNotificationSettings instead.
+ (BOOL)notificationServicesEnabled {
BOOL isEnabled = NO;
if ([[UIApplication sharedApplication] respondsToSelector:#selector(currentUserNotificationSettings)]){
UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
isEnabled = NO;
} else {
isEnabled = YES;
}
} else {
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert) {
isEnabled = YES;
} else{
isEnabled = NO;
}
}
return isEnabled;
}
Trying to shoot two birds with one stone here. First, instead of checking for isRegisteredForRemoteNotifications(), you should probably check for currentUserNotificationSettings(). With that, you can see if Alerts, Sound, etc are allowed. Secondly, it seems like the iOS version check is redundant here. Simply checking if object responds to selector is good enough. Lastly, the code example is in Swift, for that one user who asked for it :P
func hasPushNotificationsEnabled() -> Bool {
if UIApplication.sharedApplication().respondsToSelector("currentUserNotificationSettings") {
let settings = UIApplication.sharedApplication().currentUserNotificationSettings()
return (settings.types & UIUserNotificationType.Alert) != UIUserNotificationType.None
}
let types = UIApplication.sharedApplication().enabledRemoteNotificationTypes()
return (types & UIRemoteNotificationType.Alert) != UIRemoteNotificationType.None
}
Here is how to do Daniels answer in Swift 2.0
func hasPushEnabled() -> Bool {
//ios 8+
if UIApplication.sharedApplication().respondsToSelector("currentUserNotificationSettings") == true {
let settings = UIApplication.sharedApplication().currentUserNotificationSettings()
if (settings?.types.contains(.Alert) == true){
return true
} else {
return false
}
}
else {
let types = UIApplication.sharedApplication().enabledRemoteNotificationTypes()
if types.contains(.Alert) == true {
return true
} else {
return false
}
}
}
I made a very simple app that can run in the background while a timer runs. If the app is still in the background and the timer ends it will send a local notification and set the application badge to 1. When I start the app I always clear it. I noticed that after installing Xcode 6 I was getting this message every time I started the app:
"Attempting to badge the application icon but haven't received permission from the user to badge the application"
Clearly that text is generated by my app setting the badge to 0 to clear it. Where do I set these permissions or request them? Is it now regarded as a push notification?
The problem has been fixed and the answer is posted below. The bottom line is that you need to get confirmation from the user for any kind of notification, while that used to be true only for push notifications.
I ended up not using the Application Badge at all and I abandoned the initial code snippet that I have posted here in the mean while. Since there are still people reading and commenting on this question I will add my working current solution here as well. It does contains checks for iOS7 but I do not use the callback method. Also this version doesn't just ask for Application Badge permission anymore.
Solution
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
This is what I use now
.h file
#import <Foundation/Foundation.h>
#interface NotificationPermissionHandler : NSObject
+ (void)checkPermissions;
+ (bool)canSendNotifications;
#end
.m file:
#import "NotificationPermissionHandler.h"
#implementation NotificationPermissionHandler
static const UIUserNotificationType USER_NOTIFICATION_TYPES_REQUIRED = UIUserNotificationTypeAlert | UIUserNotificationTypeSound;
static const UIRemoteNotificationType REMOTE_NOTIFICATION_TYPES_REQUIRED = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
+ (void)checkPermissions;
{
bool isIOS8OrGreater = [[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)];
if (!isIOS8OrGreater)
{
[NotificationPermissionHandler iOS7AndBelowPermissions];
return;
}
[NotificationPermissionHandler iOS8AndAbovePermissions];
}
+ (void)iOS7AndBelowPermissions
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:REMOTE_NOTIFICATION_TYPES_REQUIRED];
}
+ (void)iOS8AndAbovePermissions;
{
if ([NotificationPermissionHandler canSendNotifications])
{
return;
}
UIUserNotificationSettings* requestedSettings = [UIUserNotificationSettings settingsForTypes:USER_NOTIFICATION_TYPES_REQUIRED categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:requestedSettings];
}
+ (bool)canSendNotifications;
{
UIApplication *application = [UIApplication sharedApplication];
bool isIOS8OrGreater = [application respondsToSelector:#selector(currentUserNotificationSettings)];
if (!isIOS8OrGreater)
{
// We actually just don't know if we can, no way to tell programmatically before iOS8
return true;
}
UIUserNotificationSettings* notificationSettings = [application currentUserNotificationSettings];
bool canSendNotifications = notificationSettings.types == USER_NOTIFICATION_TYPES_REQUIRED;
return canSendNotifications;
}
#end
This was my first solution
I kept it just as a reference for to the initial discussion. This code is not maintained.
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
You can also stack permissions into one request by doing this:
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
Also since iOS 8 it's possible to figure out what kind of alerts are allowed by the user:
UIUserNotificationSettings* notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (notificationSettings.types == UIUserNotificationTypeBadge)
{
// change the badge
}
I ended up using this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"first_run"])
{
[self setDefaults];
}
[self askAlertPermissions];
if ([self canChangeBadge])
{
[self setBadge:0];
}
return YES;
}
- (void)setDefaults;
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSNumber numberWithBool:NO] forKey:#"alerts_allowed"];
[defaults setObject:[NSDate date] forKey:#"first_run"];
// More defaults if needed
[defaults synchronize];
}
- (void)askAlertPermissions;
{
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
}
// This will be called only after confirming your settings
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings;
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// There is also a built in method to find out if the user has appropriate settings, you might want to use that instead if you just want to know what the setting is
[defaults setObject:[NSNumber numberWithBool:YES] forKey:#"alerts_allowed"];
}
- (bool)canChangeBadge;
{
UIUserNotificationSettings* notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
return notificationSettings.types == UIUserNotificationTypeBadge;
}
More to read:
https://developer.apple.com/library/content/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html
https://developer.apple.com/documentation/uikit/uiapplication