ask user for permission to show alert when firing local notification - ios

I want to show an alert when the local notification is fired, but for that I have to ask for permission, as it says to me when I run the app on my iPhone:
Attempting to schedule a local notification {fire date = Friday 13 June 2014 12 h 10 min 27 s Central European Summer Time, time zone = (null), repeat interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Friday 13 June 2014 12 h 10 min 27 s Central European Summer Time, user info = (null)} with an alert but haven't received permission from the user to display alerts
How can I do that?
Here´s the code as it is now:
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
localNotif.fireDate = [[NSDate date] dateByAddingTimeInterval:timeUntilNotification];
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.alertBody = #"ZEIT!";
localNotif.alertAction = #"Show me the Timer!";
localNotif.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] +1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];

add this code, it will show a alert view to ask user for permission.
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound|UIUserNotificationTypeBadge
categories:nil]];
}
you can add this code in application:didFinishLaunchingWithOptions; method, so that the app will ask your user when they launch the app, or you can add this code when you set Local Notification, it's up to you.

蘇健豪's answer is good.
In Swift it looks like this:
let registerUserNotificationSettings = UIApplication.instancesRespondToSelector("registerUserNotificationSettings:")
if registerUserNotificationSettings {
var types: UIUserNotificationType = UIUserNotificationType.Alert | UIUserNotificationType.Sound
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotific‌​ationSettings(forTypes: types, categories: nil))
}
Also see here: Ask for User Permission to Receive UILocalNotifications in iOS 8

//register notifications
if([application respondsToSelector:#selector(registerUserNotificationSettings:)]) //ios 8+
{
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
[application registerForRemoteNotifications];
}
else // ios 7 or less
{
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge];
}

In the swift language....
var type = UIUserNotificationType.Badge | UIUserNotificationType.Alert | UIUserNotificationType.Sound;
var setting = UIUserNotificationSettings(forTypes: type, categories: nil);
UIApplication.sharedApplication().registerUserNotificationSettings(setting);
UIApplication.sharedApplication().registerForRemoteNotifications();

Try this for Objective-C
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSLog(#"didFinishLaunchingWithOptions");
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound categories:nil]];
}
return YES;
}

Related

Custom UIButton with local notification

I'm trying to create a custom button that then schedules a local notification. The code I've found on here seems to be outdated. I've looked at the outlines from Apple https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html
But I'm still pretty confused. Can anyone post a clean and concise example including which files I put which code? (Including registering) Even just an example of creating any local notification would be helpful, thanks!
In AppDelegate.m, register the types of user interactions the app supports (from iOS 8.0 and later)
UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert);
UIUserNotificationSettings *mySettings =
[UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
Inside the button tapped method you do this:
NSDate * fireDate; // The schedule date time.
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = fireDate;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = #"alertText";
localNotification.alertAction = #"buttonTitle";
localNotification.soundName = UILocalNotificationDefaultSoundName;
// Schedule it with the app
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
In AppDelegate.m add this method to handle when a local notification arrives (if necessary):
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)localNotification{
// This method gets called when a local notification arrives
}

Silent push notification doesn't work on iOS7 in background mode

I have this weird situation, my app support iOS7 and above. what it does, it's enabled Remote notifications by using silent notifications.
I know that iOS7 and iOS8 above has different logic to handle notification. I did this :
if ([[UIApplication sharedApplication] respondsToSelector:#selector(isRegisteredForRemoteNotifications)])
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else {
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
here's notification receives
{
aps = {
"content-available" = 1;
};
}
So what it does is, app receive silent notification, and then set localNotification, see below :
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];
notification.soundName = UILocalNotificationDefaultSoundName;
notification.alertBody = #"testing";
notification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
All it works in iOS8 and iOS9 in background mode and foreground mode. When app is in foreground, it will trigger didReceiveLocalNotification.
But when I was testing in iOS7, it doesn't work if the app is in background mode. I'm trying to figure out how this happen, while other OS working fine. I did test while app is open, it did receive push notification, and didReceiveLocalNotification get triggered. but when goes to background, nothing happen (no local push notification).
You didn't mention about enabling Background Fetch. Have you enabled it in your App Capabilities?
and set this in your AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
and this as your delegate method
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
// do your thing here. maybe calling a view controller class or stuff
}
But if you're not into background fetch, try this instead:
{
aps = {
"content-available" : 1,
"sound" : ""
};
}
Good luck!
Im not exactly sure about the issue, but maybe you can try to change respondsToSelector. Refer to the following:
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)])
As pointed in this tread, aps need to include priority in order to work in iOS7.
aps = {
badge = 7;
"content-available" = 1;
priority = 5;
};
check this : https://stackoverflow.com/a/23917593/554740

How to send a push notification for a fixed hour?

I'm new IOS developer, and i never worked before with push notification or local.
The user need to set a hour, for taken the push notification.
What need to do my application?
My application, sent everyday for every user who set before the hour a push notification. The push notification is always same.
Can anyone help me? How can i do that?
Link for refrence to set local notification :
http://www.appcoda.com/ios-programming-local-notification-tutorial/
http://www.icodeblog.com/2010/07/29/iphone-programming-tutorial-local-notifications/
//Replace following method in Appdelegate.m in First link's code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
//-- Set Notification
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}
// Handle launching from a notification
UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (locationNotification) {
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
}
return YES;
}
You can do this for local notification
NSDate *date = self.datePicker.date;
UILocalNotification *note = [[UILocalNotification alloc] init];
note.alertBody = #"Say Hello!";
note.fireDate = date;
[[UIApplication sharedApplication] scheduleLocalNotification:note];
Also you can use framework from parse.com for remote notifications

Ask for User Permission to Receive UILocalNotifications in iOS 8

I have set up local notifications in the App Delegate Using this:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UILocalNotification *notification = [[UILocalNotification alloc]init];
[notification setAlertBody:#"Watch the Latest Episode of CCA-TV"];
[notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:5]];
[notification setTimeZone:[NSTimeZone defaultTimeZone]];
[application setScheduledLocalNotifications:[NSArray arrayWithObject:notification]];
}
When I run the app and then quit it I receive an error saying:
2014-06-07 11:14:16.663 CCA-TV[735:149070] Attempting to schedule a local notification {fire
date = Saturday, June 7, 2014 at 11:14:21 Pacific Daylight Time, time
zone = America/Los_Angeles (PDT) offset -25200 (Daylight), repeat
interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount,
next fire date = Saturday, June 7, 2014 at 11:14:21 Pacific Daylight
Time, user info = (null)} with an alert but haven't received
permission from the user to display alerts
How can I get the necessary permission to display the alerts?
Since iOS 8 you need to ask user's permission to show notifications from your app, this applies for both remote/push and local notifications. In Swift you can do it like this,
Update for Swift 2.0
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
// Override point for customization after application launch.
if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:")))
{
let notificationCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
notificationCategory.identifier = "INVITE_CATEGORY"
notificationCategory.setActions([replyAction], forContext: UIUserNotificationActionContext.Default)
//registerting for the notification.
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes:[.Sound, .Alert, .Badge], categories: nil))
}
else
{
//do iOS 7 stuff, which is pretty much nothing for local notifications.
}
return true
}
Swift 3.2
if(UIApplication.instancesRespond(to: #selector(UIApplication.registerUserNotificationSettings(_:)))){
let notificationCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
notificationCategory.identifier = "INVITE_CATEGORY"
notificationCategory.setActions([replyAction], forContext: UIUserNotificationActionContext.Default)
//registerting for the notification.
application.registerUserNotificationSettings(UIUserNotificationSettings(types:[.sound, .alert, .badge], categories: nil))
}
else{
//do iOS 7 stuff, which is pretty much nothing for local notifications.
}
Objective C syntax is also very similar.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
// Override point for customization after application launch.
return YES;
}
To check for currently registered notification types you can use UIApplication class's method,
- (UIUserNotificationSettings *)currentUserNotificationSettings
So if the user has said no to your app then this function should return a setting without any types in it.
I have written a tutorial about this, you could see it here.
Put this code in the view controller where you will first program the notifications (if you program them at launch, then it will be application:didFinishLaunchingWithOptions:):
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound categories:nil]];
}
In Swift:
if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:"))) {
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Alert | .Sound, categories: nil))
}
The solutions that test against system version number are sub-optimal and error-prone.
Try this for Objective-C:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
// are you running on iOS8?
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)])
{
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound) categories:nil];
[application registerUserNotificationSettings:settings];
}
else // iOS 7 or earlier
{
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
}
For Swift:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
// Override point for customization after application launch.
if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:")))
{
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, categories: nil))
}
else
{
//
}
return true
}
I just faced the same problem. Seems like in iOS 8 we need to do an additional step, usually done inside:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /*...*/ }
You can use this code if you want to keep it backward compatible:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)])
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]];
}
#endif
The system will remember the decision, and will only ask once.
**Local Notification with three button action for iOS8+
//Button : I TOOK IT , REMIND LATER , SKIP IT**
let completeAction = UIMutableUserNotificationAction()
completeAction.identifier = "COMPLETE_TODO"
completeAction.title = "I TOOK IT"
completeAction.activationMode = .Background
completeAction.destructive = true
completeAction.authenticationRequired = false
let remindAction = UIMutableUserNotificationAction()
remindAction.identifier = "REMIND_TODO"
remindAction.title = "REMIND LATER"
remindAction.activationMode = .Background
remindAction.destructive = false
// remindAction.authenticationRequired = false
let skipAction = UIMutableUserNotificationAction()
skipAction.identifier = "SKIP_TODO"
skipAction.title = "SKIP IT"
skipAction.activationMode = .Background
skipAction.destructive = false
skipAction.authenticationRequired = false
let todoCategory = UIMutableUserNotificationCategory()
todoCategory.identifier = "TODO_CATEGORY"
todoCategory.setActions([completeAction, remindAction, skipAction], forContext: .Default)
todoCategory.setActions([completeAction,remindAction,skipAction], forContext: .Minimal)
if application.respondsToSelector("isRegisteredForRemoteNotifications")
{
let categories = NSSet(array: [todoCategory,todoVideoCategory])
let types:UIUserNotificationType = ([.Alert, .Sound, .Badge])
let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: categories as? Set<UIUserNotificationCategory>)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}
}

How to check if Local Notification is enabled/disabled?

I understand we can check if a user has enabled/disabled Remote Notification with this code:
[[UIApplication sharedApplication] enabledRemoteNotificationTypes]
But what about checking for Local Notification?
I don't find a corresponding property for local notification types, and I have verified that enabledRemoteNotificationTypes is only for remote notifications.
And we all know, users can edit their Notification settings, which will affect both remote and local.
I'm not sure, but I don't think you can access this information.
One way you can check if the user has notifications enabled for your app is to send yourself a local notification with a 1 second delay :
UILocalNotification *testNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
localNotification.alertBody = #"Test notification";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
And check if you catch it in :
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification) {
// If you get here, notifications are enabled
}
All there is left is add info (e.g in localNotification.userInfo) so you can know in didReceiveLocalNotification: if you are handling your test notification, or if it's a "real" notification.
- (BOOL) isLocalNotificationsEnable {
if ([[UIApplication sharedApplication] respondsToSelector:#selector(currentUserNotificationSettings)]) {
UIUserNotificationSettings *grantedSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
return (grantedSettings.types == UIUserNotificationTypeNone) ? NO : YES;
}
return NO;
}
Note: the if block is only require if you're targeting < iOS 8.0.

Resources