iOS Registering for Push Notifications within Application

21,089

Solution 1

A1: No, it doesn't have to be at the start of the app. You can invoke registerForRemoteNotificationTypes from anywhere in the code.

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

You will need to handle following delegates methods(in delegate) which gets called on successful/fail registering for push notification.

// Delegation methods
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
    const void *devTokenBytes = [devToken bytes];
    self.registered = YES;
    [self sendProviderDeviceToken:devTokenBytes]; // this will send token to your server's database
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
    NSLog(@"Error in registration. Error: %@", err);
}

A2: Yes you can. There are two possible scenarios. If your application is not running, you will handle push notification in didFinishLaunchingWithOptions. In this case if user has selected "open" in the message alert or clicked on Banners(depends on user's settings), your application will automatically start and you can handle user parameters passed in push notification.

 /* Push notification received when app is not running */
 NSDictionary *params = [[launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:@"appsInfo"];

    if (params) {
        // Use params and do your stuffs
    }

If your application is already running, push notification will be delivered to application:didReceiveRemoteNotification: delegate method where you can simply present UIAlertView with the message in push notification and handle alertView delegates OK/Cancel button click in standard way.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSDictionary *apsInfo = [userInfo objectForKey:@"apsinfo"]; // This appsInfo set by your server while sending push

    NSString *alert = [apsInfo objectForKey:@"alert"];

    UIApplicationState state = [application applicationState];

    if (state == UIApplicationStateActive) {
        application.applicationIconBadgeNumber = 0;

        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

        UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"Push Notification"
                                                            message:alert
                                                           delegate:self
                                                  cancelButtonTitle:@"NO"
                                                  otherButtonTitles:@"YES"];
        [alertview show];
        [alertview release];

    } else {
        [self setTabs:contentsInfo];
     }
}


- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
    if (buttonIndex != [alertView cancelButtonIndex]) {
     // User pressed YES, do your stuffs
     }
}

A3: If user has refused to accept push notification from your app then its didFailToRegisterForRemoteNotificationsWithError and you hence you will not get user's devToken which is required to be on your server to send push notification to that user. If user initially accept but later on if he changed settings to disable your push notification then Apple server will not send your push notification to that user. In this case that user's UDID will appear in Feedback service and ideally your server should remove that user's UDID from the database and stop sending push notification to that users going forward. If you keep sending invalid push notification, Apple server might drop your connection silently and you will not able to send any push notifications.

See Apple Push Notification docs for details on implementation.

Solution 2

You can use following tutorial for swift(Visit Link) and use following simple code for objective-c for Apple Push Notification.

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
        {
         // iOS 8 Notifications
            [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound |UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
            [application registerForRemoteNotifications];
        }
        return YES;
    }


    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        NSLog(@"Did Register for Remote Notifications with Device Token (%@)", deviceToken);
    }

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

        NSLog(@"Did Fail to Register for Remote Notifications");
        NSLog(@"%@, %@", error, error.localizedDescription);
    }

    -(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
        NSLog(@"%@",userInfo);
    }

Solution 3

  • Q1 It's not necessary to put push register at app launch, but some do put it in application: didFinishLaunchingWithOptions: to somehow ensure the device token is successfully stored on developer's server.
  • Q2 What the "yes/no" for here? If you mean the "yes/no" on "if receive push notification", then if the user clicked "yes", the delegate application: didRegisterForRemoteNotificationsWithDeviceToken will be triggered, otherwise not.
  • Q3 If the user click "no" to reject receiving push notification, then either you can later remind him to turn it on in settings, or have a function, like a UISwitch thing, to enable users to trigger [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound)]; again.
Share:
21,089
williamsandonz
Author by

williamsandonz

Updated on July 17, 2022

Comments

  • williamsandonz
    williamsandonz almost 2 years

    Q1. Do I have to do this at the start of my App? Or can I trigger the prompt to allow/not-allow at any point in my app?

    Q2. Is there a way to find out if the user clicked yes/no ? (callback?)

    Q3. If the user has already clicked no, (in a previous session), will my prompt actually fire? Or do I need to tell the user to go to their phone settings and enable it there?

    Reason being is I have an app which has a section inside it called "Notifications" whereby they can enable/disable to receive notifications on certain things, so I only want to prompt them to enable etc. when they are in this section not at the start of the App.

  • Rohan Sanap
    Rohan Sanap about 8 years
    If user rejects to receive push notification or switch off push notification from settings, how can we handle the case of re-prompting user? .i.e., How to know that user is not registered for push and give him re-prompt?
  • karan
    karan over 7 years
    we can also skip else part iOS < 8 Notifications.. as now a days we go ios 8 and above... Mohammad good obj c code.
  • mfaani
    mfaani over 7 years
    This answer (and likely other answers) is partially outdated. it only applies to iOS <7. in iOS789 you had to do a separate [application registerForRemoteNotifications] as that would get you the token (something you are able to do without the user permission ; permission is only required if you are to give alert/badge, sound to the user). in iOS 10 there is a new framework named UserNotifications which will allow you to find out if the user allowed access or not. See here for more on iOS 10 (1/2)
  • mfaani
    mfaani over 7 years
    In the previous versions you had to [application isRegisteredForRemoteNotifications] to see if you are registered or not (2/2)