0
votes

I'm trying to integrate my Android and iOS native apps with Notification Hub. For example, on iOS, as soon as I receive the deviceToken and if my user is already authenticated, I register directly with NotificationHub:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    log.debug("Received device token \(deviceToken.hexEncodedString()). Saving device token to user defaults.", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken")
    let defaults = UserDefaults.standard
    defaults.set(deviceToken, forKey: UserNotificationDeviceTokenKey)
    defaults.synchronize()

    if let authenticatedUser = Session.shared.authenticatedUser {
        log.debug("Trying to register device token \(deviceToken.hexEncodedString()) to user \(authenticatedUser.id) on notification hub with hub name \(String(describing: hubName)) and connection string \(String(describing: connectionString)). Notification hub null? \(notificationHub == nil)")
        self.notificationHub?.registerNative(withDeviceToken: deviceToken, tags: Set<String>([authenticatedUser.id]), completion: { error in
            if (error != nil) {
                log.error("Error registering for notifications: \(error.debugDescription)", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken");
            } else {
                log.debug("Successfully registered device token \(deviceToken.hexEncodedString()) for user with ID \(authenticatedUser.id) and email \(authenticatedUser.emailAddress)", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken")
            }
        })
    }
}

And whatever happens, I start by saving the device token to the user defaults so that when a user does log in, he can retrieve the deviceToken from user defaults and call the same registerNative method to create a registration associating this deviceToken with a tag that is the user's identifier:

func userDidSignIn(user: User) {
    if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
        let deviceToken = UserDefaults.standard.data(forKey: UserNotificationDeviceTokenKey){

        log.debug("Trying to register device token \(deviceToken.hexEncodedString()) to user \(user.id) on notification hub with hub name \(String(describing: appDelegate.hubName)) and connection string \(String(describing: appDelegate.connectionString)). Notification hub null? \(appDelegate.notificationHub == nil)")

        appDelegate.notificationHub?.registerNative(withDeviceToken: deviceToken, tags: Set<String>([user.id]), completion: { error in
            if (error != nil) {
                log.error("Error registering for notifications: \(error.debugDescription)");
            } else {
                log.debug("Successfully registered device token \(deviceToken.hexEncodedString()) for user with ID \(user.id) (\(user.emailAddress)) who just logged in", context: "HTRootViewController.userDidSignIn")
            }
        })
    } else {
        log.warning("No device token found in settings.", "HTRootViewController.userDidSignIn")
    }
}

I have all my logs remotely sent to Bugfender, which lets me check the logs for all the devices using this app installed in TestFlight, so I can see that all the registerNative's are successful:

Trying to register device token 0fea9a4d99ec37dc4f3ac252c35fa4e1617004fd14740973d80a7dfdaeacc857 to user 77bfb1c6-b05a-440b-a7a0-71ae5a91bbb2 on notification hub with hub name Optional("[my notification hub name]") and connection string Optional("[my notification hub connection string]"). Notification hub null? false

Successfully registered device token 0fea9a4d99ec37dc4f3ac252c35fa4e1617004fd14740973d80a7dfdaeacc857 for user with ID 77bfb1c6-b05a-440b-a7a0-71ae5a91bbb2 ([my user's email]) who just logged in

But then, when I load the list of all the registrations using this .NET C# code:

public async Task<List<RegistrationDescription>> GetRegistrations()
{
    var hub = NotificationHubClient.CreateClientFromConnectionString([my notification hub connection string], [my notification hub name]);
    var result = await hub.GetAllRegistrationsAsync(1000);
    return result.ToList();
}

I can see that some registrations are there, but others are nowhere to be found, even though they succeeded according to my mobile logs.

Does anyone know what else could be going on? What else can I check? Why else would registrations not be saved even though the call to registerNative seems to succeed?

EDIT: As a matter of fact, and after checking more precisely what is happening, the registration first appears in the list of registrations returned by Notification Hub, but as soon as we try to send a notification, it's as if Notification Hub could not reach the corresponding device token and deleted the registration altogether. Is there a way to see the logs of Notification Hub to see what is going on and why it decides to delete this registration?

1

1 Answers

0
votes

I figured it out. It turns out it was working on my device because I ran the beta in debug mode, so it was getting its device token from the Sandbox APS environment, which matched the Sandbox endpoint configured in Notification Hub, but other users were using the Production APS environment configured in the archive build, so they got device tokens for a different environment and notification hub correctly identified as incorrect device tokens. Once we switched the Notification Hub to the production APNS endpoint, all the TestFlight users were able to receive notifications because their registrations stayed in Notification Hub. Now that does mean that my debug builds trying to use that environments won't receive notifications, but that's OK, that's why we have a different environment and Notification Hub for development purposes. So if anyone sees something similar, don't forget to double check your Notification Hub configuration matches the type of build your users are using, and don't forget that TestFlight builds are now production-type builds, same as App Store builds.