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:
- userID in getUserNotificationSubscription WORKLIGHT Pushnotification
- Worklight: Push notification without User ID
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:
- is Worklight storing an user id which is different from the android user id (as an abstraction)?
- 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?
- since this one seems like a usual problem (pushing notifications to different users), is it possible that there is no example code online?
- 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);