0

Here is how I've been registering for push notifications:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions

{

//-- Set Notification
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])

{

    // iOS 8 Notifications: Registering for notifications and types
    [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];

    [application registerForRemoteNotifications];

}

else

{

    // iOS < 8 Notifications
    _storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:

     (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

}

_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

[[UIApplication sharedApplication] registerForRemoteNotificationTypes:

 (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];

if (launchOptions != nil)

{

    NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

    if (dictionary != nil)

    {

        NSLog(@"Launched from push notification: %@", dictionary);

        /*[self addMessageFromRemoteNotification:dictionary updateUI:NO];*/

    }

} 

return YES;

}

Within the last week, I have been using the following terminal command from Sending Push Notifications Using Command-Line Tools to successfully send a test push notification to a testing device.

curl -v --header 'apns-topic: com.domain.appname' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Hello From Faunna"}}' --http2  https://api.sandbox.push.apple.com/3/device/258ecf658e25256c8f06ddb1138d5d536ba0e760a96ebd12d3b1dbe112857c58

Recently after creating provisioning profile and adding it to Xcode, the app no longer prints the device token in the debug window. After removing the provisioning profile from my Apple Developer account under profiles, I tried using a backed up version of the app which still prints a device token to the debugger window. When I copy the device token and enter it into the terminal command to send another test push notification, the terminal output is a 400 status code:

{"reason":"BadDeviceToken"}* Closing connection 1

curl -v --header 'apns-topic: com.domain.appname' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Test"}}' --http2  https://api.sandbox.push.apple.com/3/device/a146d82d4acea02c9ef6de5838174292d0e2cd18a40be17fb79334c5003a0058



* Could not resolve host: alert



* Closing connection 0



curl: (6) Could not resolve host: alert



*   Trying 17.188.138.73...



* TCP_NODELAY set



* Connected to api.sandbox.push.apple.com (17.188.138.73) port 443 (#1)



* ALPN, offering h2



* ALPN, offering http/1.1



Enter PEM pass phrase:



* successfully set certificate verify locations:



*   CAfile: /etc/ssl/cert.pem



CApath: none



* TLSv1.2 (OUT), TLS handshake, Client hello (1):



* TLSv1.2 (IN), TLS handshake, Server hello (2):



* TLSv1.2 (IN), TLS handshake, Certificate (11):



* TLSv1.2 (IN), TLS handshake, Server key exchange (12):



* TLSv1.2 (IN), TLS handshake, Request CERT (13):



* TLSv1.2 (IN), TLS handshake, Server finished (14):



* TLSv1.2 (OUT), TLS handshake, Certificate (11):



* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):



* TLSv1.2 (OUT), TLS handshake, CERT verify (15):



* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):



* TLSv1.2 (OUT), TLS handshake, Finished (20):



* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):



* TLSv1.2 (IN), TLS handshake, Finished (20):



* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384



* ALPN, server accepted to use h2



* Server certificate:



*  subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US



*  start date: Feb  8 21:41:22 2021 GMT



*  expire date: Mar 10 21:41:22 2022 GMT



*  subjectAltName: host "api.sandbox.push.apple.com" matched cert's "api.sandbox.push.apple.com"



*  issuer: CN=Apple Public Server RSA CA 12 - G1; O=Apple Inc.; ST=California; C=US



*  SSL certificate verify ok.



* Using HTTP2, server supports multi-use



* Connection state changed (HTTP/2 confirmed)



* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0



* Using Stream ID: 1 (easy handle 0x7fbd4700aa00)



> POST /3/device/a146d82d4acea02c9ef6de5838174292d0e2cd18a40be17fb79334c5003a0058 HTTP/2



> Host: api.sandbox.push.apple.com



> User-Agent: curl/7.64.1



> Accept: */*



> apns-topic: com.faunna.PushChat



> Content-Length: 37



> Content-Type: application/x-www-form-urlencoded



> 



* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!



* We are completely uploaded and fine



< HTTP/2 400 



< apns-id: 8DE6AA75-8E41-E95E-1FAF-51D93A8B3200



< 



* Connection #1 to host api.sandbox.push.apple.com left intact



{"reason":"BadDeviceToken"}* Closing connection 1

What is causing the BadDeviceToken output in this set up? And how should I be registering for remote notifications from this point forward?

Update:

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{

UINavigationController *navigationController = (UINavigationController*)_window.rootViewController;
ChatViewController *chatViewController = (ChatViewController*)[navigationController.viewControllers objectAtIndex:0];

DataModel *dataModel = chatViewController.dataModel;
NSString* oldToken = [dataModel deviceToken];

NSString* newToken = [deviceToken description];
newToken = [newToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
newToken = [newToken stringByReplacingOccurrencesOfString:@" " withString:@""];

NSLog(@"My token is: %@", newToken);

[dataModel setDeviceToken:newToken];

if ([dataModel joinedChat] && ![newToken isEqualToString:oldToken])
{
    [self postUpdateRequest];
}

}
programcode
  • 104
  • 1
  • 14
  • 1
    Can you show your `didRegisterForRemoteNotifications` code. Is that method being called? Is `didFailToRegisterForRemoteNotifications` being called? – Paulw11 Sep 13 '21 at 20:40
  • I updated the question. After restarting my MacBook and running the app again, the Debugger Window no longer prints a device token at all. It just says `registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later. ` – programcode Sep 13 '21 at 22:02

2 Answers2

1

In the comments you mention that you are getting

registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later

in the console when you run your app.

It seems that your code is following the < iOS 8 path rather than the iOS8+ path, resulting it not calling registerForRemoteNotifications and you don't have the latest token.

Checking for a particular selector is not the right way checking the iOS version.

You should check the iOS version using if (@available(iOS 8, *)) { and put your iOS 8+ code in that block. (Although you can probably drop support for iOS 7 at this point).

if (@available(iOS 8, *)) {
  // iOS 8 Notifications: Registering for notifications and types
    [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];

    [application registerForRemoteNotifications];
} else {
// iOS < 8 Notifications
    _storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:

     (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}

You really should not use description in production code either; It is really just for debugging and its output can change without notice.

You should convert the token to a string of hex characters using dedicated code

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • In the parameters in the if statement, Xcode is giving a parse issue: `Expected a version of the form 'major[.minor[.subminor]]'`. Do you know how to fix this? – programcode Sep 14 '21 at 01:05
  • 1
    Sorry, I had a typo - the 8 was missing – Paulw11 Sep 14 '21 at 03:20
  • I tried with the updated code but the debugger is still not printing the device token? – programcode Sep 14 '21 at 03:58
  • The app is receiving a `... Would Like to Send You Notifications` alert with the updated code, but is not printing the device token to the Debugger Window yet. – programcode Sep 14 '21 at 04:22
  • Did you set a breakpoint in the `didRegisterForRemoteNotifications` and `didFailToRegisterForRemoteNotifications` methods? Are either of those methods called? – Paulw11 Sep 14 '21 at 05:11
0

It turns out I was trying to use a production token with an APS entitlement set to development.

programcode
  • 104
  • 1
  • 14