Tuesday, 25 April 2017

Azure Mobile App: Targeted PUSH with iOS/Node.js

I am really struggling with a lack of documentation by Microsoft.

Here's what I have:

  • Working Node.js Azure Mobile app.
  • Working SQL Server database, successfully connected to Mobile App. (I'm not sure if this matters, but some of my reading has indicated that I need to keep my own list of user/device registrations for PUSH notifications.)
  • Working iOS app tied into the Mobile App.
  • Working Notification Hub tied into the Mobile App.

So, I am able to use the "Test Send" function in my Notification Hub, and all devices will receive the test message. Great.

Now, I'm trying to extend this functionality to target specific users with PUSH notifications. I am not primarily a Node.js developer, so digging through that source code to figure stuff out is hard for me, and the documentation (and examples) provided by Microsoft in this area is really, really thin. I found this Microsoft documentation for targeted PUSH notifications, but it's for a .NET backend. If you toggle to the Node.js version of that page/article, there's some information about PUSH notifications, and specifically targeting specific users. Under the section titled "How to: Send push notifications to an authenticated user using tags" is the following information:

When an authenticated user registers for push notifications, a user ID tag is automatically added to the registration. By using this tag, you can send push notifications to all devices registered by a specific user. The following code gets the SID of user making the request and sends a template push notification to every device registration for that user:

Great. So, I'm assuming that means registration like this (since there's no example code):

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    AppSingleton *app = [AppSingleton singleton];
    MSClient *client = app.client;        
    [client.push registerDeviceToken:deviceToken completion:^(NSError *error) {
        if (error == nil) {
            NSLog(@"Registered device!");
        } else {
            NSLog(@"Error registering for notifications: %@", error);
        }
    }];
}

Well, when I run that code (with a logged-in/authenticated user), I get the "Registered device!" message, but I'm not really sure where to go from there. I went to the "Test Send" blade of the Notification Hub associated with this app, but attempting to send a targeted message to the associated user associated failed. I tried sending with a tag of "_UserId:{userId}" where {userId} is the actual ID for the logged-in user. No dice. Is there any way in the Azure Portal to follow up on this and see a list of registered devices?

Anyway, I put the following code (copied almost directly from the aforementioned Microsoft documentation) in a particular call in my API:

// Just testing
var payloadString = '{"messageParam": "This is a template payload."}';
// Send a notification to the current user.
context.push.send(context.user.id, payloadString, function (error) {
    if (error) {
        console.error('Error while sending push notification: ', error);
    } else {
        console.log('PUSH notification sent successfully!');
    }
});

While I get the "PUSH notification sent successfully" message in my Node console, I get nothing on my devices.


Research background:

I'm basically trying to do the same thing as asked in this question. The problem is that when I follow the advice and link provided in the answer (here), the latest commit says, "Removed push registration / deletion functionality," but there's no information about where those methods went. Great. Ugh.

I read this answer (by Adrian Hall, so it should be valid), and it seems to align with this answer, which seems to lay out a pretty logical workflow. I have written an API method with Adrian's code as a template. I am stuck, however, trying to call this code from my iOS app. Here's the API code (I made the platform a supplied variable so that this wouldn't be purely iOS-specific, since I'll need to support Android eventually):

var promises = require('azure-mobile-apps/src/utilities/promises');

function createInstallation(context, installationId, platform, pushChannel) {
    var installation = {
        installationId  : installationId,
        pushChannel     : pushChannel,
        platform        : platform,
        tags            : [ pushChannel ]
    };
    return promises.wrap(context.push.createOrUpdateInstallation, context.push)(installation);
}

module.exports = {
    post: function (req, res, next) {
        console.log(req.body);
        var context         = req.azureMobile;
        var installationId  = req.get('X-ZUMO-INSTALLATION-ID');
        var platform        = req.body.Platform;
        var pushChannel     = req.body.PushChannel;

        createInstallation(context, installationId, platform, pushChannel).then((result) => {
            res.status(204).end();
        }).catch(next);
    }
};

To be honest, I'm not really sure what the code above is doing. Based on the quote above from Microsoft, I would assume that the registerDeviceToken:completion: takes care of this. If so, why the need for the additional API method? Or, if the API method is necessary, then what does the call to registerDeviceToken:completion: actually do? All I want is to be able to send a PUSH notification to a specific user (on all registered devices). I don't care about categories or groups. What's the shortest path to that goal?


I'm not really sure where to go from here. Microsoft's documentation in this area is really thin and the update schedule seems to be very uneven. I even read a document last week on this topic that was last updated in 2015! I can't figure out whether I need to register users/devices from the client app (iOS/Android) or from the Node.js API (or maybe both)? And the documentation is also very unclear about how to actually structure a tag using the Node.js server SDK so as to send a PUSH notification to a specific user. I've seen examples that say it's just context.user.id or maybe it's _UserId:{userId} (which would really be '_UserId:' + context.user.id, right?) or even username:{userId}. So which is the right way?



via mbm29414

No comments:

Post a Comment