Push notifications, device tokens, & base64 encoding
I am using my own server for push notifications, not urban airship. My server currently works with apps made in Objective-C without issue. The general workflow is like this:
Subscribe for notifications and get a device token, base64 encode the token, add the encoded token to a JSON dictionary, and then POST it to my server.
I'm having encoding issues in Appercelerator. Look at this:
//In my Obj-C app, my device token is an NSData object that looks like this:
<0cd9f571 b0e66e6d ca410d12 f67a404a 7e64b9b5 d2483fd9 63a9267b 1c7609e2>
//After it's base64 encoded, it looks like this:
DNn1cbDmbm3KQQ0S9npASn5kubXSSD/ZY6kmexx2CeI=
//In my Titanium app, my device token from looks like this:
0cd9f571b0e66e6dca410d12f67a404a7e64b9b5d2483fd963a9267b1c7609e2
//So far, so good. It matches the Obj-C app. When I base64
//encode my token with Titanium.Utils.base64encode(e.deviceToken),
//I get this:
MGNkOWY1NzFiMGU2NmU2ZGNhNDEwZDEyZjY3YTQwNGE3ZTY0YjliNWQyNDgzZmQ5NjNhOTI2N2IxYzc2MDllMg==
This is where the problem arises. The base64 encoding doesn't match! What is going on here? My suspicion is that base64 is encoding different object types. In the Obj-C app, the device token is an NSData object, not a string. In the Titanium app I think the deviceToken is a TiBlob (or string? I couldn't find the doc). Regardless, notifications aren't working my Titanium app but they are working in my Obj-C app.
As a test, I've plugged DNn1cbDmbm3KQQ0S9npASn5kubXSSD/ZY6kmexx2CeI= into my Titanium app as a string literal and then it worked! The question is, how do I properly encode the token in Titanium?
2 Answers
-
Hey Eduardo, I haven't used Titanium in a couple of years, so I'm not sure if there's a better solution now. At the time I just forked the Titanium project and modified the push notification code in the app delegate to use the NSData version of the device token instead of the string version. The method in question is here, starting on line 821: https://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/TiApp.m… notice on line 823 that the NSData object is converted to a string via
[deviceToken description]
. This is the cause of the problem. -
The value given to you "0cd9f571b0e66e6dca410d12f67a404a7e64b9b5d2483fd963a9267b1c7609e2" represents 32 bytes of data. i.e. 0c, d9, f5, etc are all bytes (in hex). you can convert these into bytes then put them into a blob OR even better send the string to an objective C module and convert it to the correct NSData object there with this code:
-(NSData) convertToData:(NSString )devToken {
const char * chars = [devToken UTF8String]; int i = 0; int len = (int)devToken.length; NSMutableData *data = [NSMutableData dataWithCapacity:len / 2]; char byteChars[3] = {'\0','\0','\0'}; unsigned long wholeByte; while (i < len) { byteChars[0] = chars[i++]; byteChars[1] = chars[i++]; wholeByte = strtoul(byteChars, NULL, 16); [data appendBytes:&wholeByte length:1]; } return data;
}