0
votes

I'm trying to setup push notifications both for Android and iOS using Worklight.

Thus far I have managed to set up the Google GCM (subscribing to the push seems to succeed), and I used the example in the IBM Worklight Getting Started page as main reference.

In the adapter, the sendNotification method needs the userId, but I don't know how to retrieve that. In the example, it is passed as an argument to the jar, but to me this doesn't seem as a feasible solution, since I need a real app with multiple users.

I'm aware of the discussions on Stack Overflow:

But still they don't answer to my doubts... In one of many attempts I tried to call WL.Client.getUserName() on the client, but it returns null.

As far as I understood, this is related to the security (and realm) settings of Worklight, but I suspect I didn't really catch the concept of user id. Given that I'm really new to mobile development (therefore many concepts are new for me, and I may be saying something wrong), my doubts are:

  1. is Worklight storing an user id which is different from the android user id (as an abstraction)?
  2. if yes, is this the reason why the security/realm is sometimes mentioned? how to pair these two user id (android/worklight) or, at least, work with the worklight user?
  3. since this one seems like a usual problem (pushing notifications to different users), is it possible that there is no example code online?
  4. which one should be the flow / architecture to follow, according to the user id? EG: user id needs to be stored into a realm, this realm as information about x and should be of type y, it will be used to z, etc... (still I have to figure out how to deal with realms)

My authenticationConfig.xml looks like this:

 <staticResources>
    <resource id="subscribeServlet" securityTest="SubscribeServlet">
        <urlPatterns>/subscribeSMS*;/receiveSMS*;/ussd*</urlPatterns>
    </resource>

</staticResources> 

 <securityTests>

    <!-- Added for pushing -->   
    <mobileSecurityTest name="PushApplication-strong-mobile-securityTest">
        <testUser realm="PushAppRealm"/>
        <testDeviceId provisioningType="none"/>
    </mobileSecurityTest>

    <customSecurityTest name="SubscribeServlet">
        <test realm="SubscribeServlet" isInternalUserID="true"/>
    </customSecurityTest>           

</securityTests> 

<realms>
    <realm name="SampleAppRealm" loginModule="StrongDummy">
        <className>com.worklight.core.auth.ext.FormBasedAuthenticator</className>
    </realm>

    <realm name="SubscribeServlet" loginModule="rejectAll">
        <className>com.worklight.core.auth.ext.HeaderAuthenticator</className>          
    </realm>

    <!-- Added for pushing -->   
    <realm loginModule="PushAppLoginModule" name="PushAppRealm">
        <className>com.worklight.core.auth.ext.FormBasedAuthenticator</className>
    </realm>

</realms>

<loginModules>

    <!-- Added for pushing -->   
    <loginModule name="PushAppLoginModule">
        <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
    </loginModule>

    <loginModule name="StrongDummy">
        <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
    </loginModule>

    <loginModule name="requireLogin">
        <className>com.worklight.core.auth.ext.SingleIdentityLoginModule</className>
    </loginModule>

    <loginModule name="rejectAll">
        <className>com.worklight.core.auth.ext.RejectingLoginModule</className>
    </loginModule>

</loginModules>

And this one is the adapter (deviceSubscribeFunc is never called, I would expect the opposite):

WL.Server.createEventSource({
        name: 'PushEventSource',
        onDeviceSubscribe: 'deviceSubscribeFunc',
        onDeviceUnsubscribe: 'deviceUnsubscribeFunc',
        securityTest:'PushApplication-strong-mobile-securityTest'
});

// NEVER CALLED!
function deviceSubscribeFunc(userSubscription, deviceSubscription){
    WL.Logger.error(">> deviceSubscribeFunc"); // error is shown on the console, debug not
    WL.Logger.debug(userSubscription);
    WL.Logger.debug(deviceSubscription);
}

function deviceUnsubscribeFunc(userSubscription, deviceSubscription){
    WL.Logger.error(">> deviceUnsubscribeFunc"); // error is shown on the console
    WL.Logger.debug(userSubscription);
    WL.Logger.debug(deviceSubscription);
}

function testCall(message) {
    WL.Logger.error("Client says: " + message); // error is shown on the console, debug not
    return { response : "hello client!" };
}

function submitNotification(userId, notificationText){

    var userSubscription = WL.Server.getUserNotificationSubscription('NotificationManager.PushEventSource', userId);

    if (userSubscription==null)
        return { result: "No subscription found for user :: " + userId };

    var badgeDigit = 1;
    var notification = WL.Server.createDefaultNotification(notificationText, badgeDigit, {custom:"data"});

    WL.Logger.debug("submitNotification >> userId :: " + userId + ", text :: " + notificationText);

    WL.Server.notifyAllDevices(userSubscription, notification);

    return { 
        result: "Notification sent to user :: " + userId 
    };
}

Meanwhile the client subscribes to push in this way (toUI is a simple method which put a string into a new div in the UI):

        var pushNotificationReceived = function(props, payload) {
            toUI("pushNotificationReceived invoked");
            toUI("props :: " + JSON.stringify(props));
            toUI("payload :: " + JSON.stringify(payload));
        }

        if(WL.Client.Push) {
            var isSubscribed = WL.Client.Push.isSubscribed('myPush');
            toUI("User is " + (isSubscribed? "" : "<u>not</u>")+ " subscribed.", confStyle);
            WL.Client.Push.onReadyToSubscribe = function() {
                toUI("Ready to subscribe, subscribing...", confStyle);
                WL.Client.Push.registerEventSourceCallback("myPush", "NotificationManager", "PushEventSource", pushNotificationReceived);
            }
        } else
            toUI("Push not available.", errStyle);
1

1 Answers

0
votes

UserId should be supplied by the entity that triggers push notifications, e.g. your backend. How do you authenticate your users? Do you have some kind of user repository? This is where you keep your userIds. It is your backend that decides to send push notification once some event has occurred. Imagine a banking app. User123 has logged in. During the login WL server contacted the backend which validated that User123 exists in user repository and supplied password match. Once logged in User123 subscribes to push notifications. Later that week a real person who uses User123 goes to ATM and withdraws $10. This event is processed by a Banking backend. Banking backend sees that account that the withdrawal was made from is associated with mobile User123. Therefore it tells WL server to send push notification to User123.

Note that you don't have to base your push notifications on user identities. You can also use tag based notifications where users subscribe to specific tag and you can send notifications to all users subscribed to that tag (http://www-01.ibm.com/support/knowledgecenter/SSZH4A_6.2.0/com.ibm.worklight.dev.doc/devref/t_tag-based_notifications_setting_up.html)