I am encountering a weird behavior of the PFInstallation of my iOS App. On every app launch I am registering the device to receive push notifications and calling the below code on the method didRegisterForRemoteNotificationsWithDeviceToken:
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
NSLog(#"%#", currentInstallation );
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"currentInstallation saved" );
}
if (error) {
NSLog(#"currentInstallation NOT saved" );
}
}];
When I install the app on my iphone the installation is saved correctly with its deviceToken. I am absolutely sure that some days ago i was manually deleting the deviceToken through the Parse Dashboard (to try out things) then on app re-launch the device token was saved correctly again. Same thing for some channels I was using. Today the deviceToken is not being saved, nor the channels. The saveInBackgroundWithBlock succeeds but the deviceToken field is empty. The NSLog of the currentInstallation contains the deviceToken, but it's not saved. While trying to understand the reason for this behavior i found out that if I add the line currentInstallation.deviceToken = #""; just after PFInstallation *currentInstallation = [PFInstallation currentInstallation]; then the deviceToken gets saved correctly. Consume Parse guru explain to me why this is happening and why some days ago it wasn't? I recently upgraded the Parse Framework on this app, can that be the reason?
Related
I'm currently working on project that allows user to receive push notifications whenever there is something new on the user account. I'm using Parse as my push notifications service. I'm having no problem until recently our server starting to receive empty token device on every push notification registration, this problem is not always happening. So when I tried the app on my device it just run as it should but when my app tested on our client device , our server receive an empty token device for that client user. How can this happen? How can I fix this? And how is the best practice to get and set the device token?
Here is my code in appdelegate:
- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
const unsigned *tokenBytes = [deviceToken bytes];
NSString *token = [NSString stringWithFormat:#"%08x%08x%08x%08x%08x%08x%08x%08x",
ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
//function for saving device token to server
[[ASEngine defaultEngine] setCurrentDeviceToken:token];
if([[ASEngine defaultEngine] currentCredential] != nil) {
[[ASEngine defaultEngine] webStoreDeviceToken:token];
}
//save current instalation to parse
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
NSLog(#"Error e current installation: %#", error);
}];
//save device token locally
[[NSUserDefaults standardUserDefaults] setObject:deviceToken forKey:#"deviceToken"];
}
An empty token wont ever be generated,
iOS provides didFailToRegisterForRemoteNotificationsWithError method which is being probably called in your case, please make sure to check that for any errors in token creation.
Sometimes it happens when your device is not connected to internet.
Make sure your device is connected to internet.
I want to update device token in installation table on parse using iOS.
To save a device token I did:
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:(NSData*)[AppHelper userDefaultsForKey:#"token"]];
[currentInstallation setObject:[PFUser currentUser].objectId forKey:#"user"];
NSArray *channels = [NSArray arrayWithObjects:#"AnyString",nil];
currentInstallation.channels=channels;
[currentInstallation saveInBackground];
I want to update this device token. I know to update token I have to use rest API i.e. https://api.parse.com/1/installations. How to update the row as I also don't have installation id.
Please provide proper syntax.
Write below code in didRegisterForRemoteNotificationsWithDeviceToken method in AppDelegate .
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
PFInstallation *currnentInstallation = [PFInstallation currentInstallation];
[currnentInstallation setDeviceTokenFromData:deviceToken];
[currnentInstallation saveInBackground];
}
For Register user in channels use below code in Login Screen
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
if ([PFUser currentUser].objectId)
{
currentInstallation[#"user"] = [PFUser currentUser];
currentInstallation.channels = #[[NSString stringWithFormat:#"user_%#",[PFUser currentUser].objectId]];
NSLog(#"Saving Installation channel = %#",currentInstallation.channels);
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
NSLog(#"Current installation updated: Error: %#",error);
}];
}
For more details , refer this link https://www.parse.com/docs/ios/guide#push-notifications-installations
In AppDelegate's didRegisterForRemoteNotificationsWithDeviceToken method, set deviceToken to installation table and save device token to NSUserDefaults ,like this:
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
currentInstallation.channels = #[#"global"];
[currentInstallation saveInBackground];
[[NSUserDefaults standardUserDefaults]setObject:deviceToken forKey:#"deviceToken"];
And on login or signup ,set user like this :
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setObject:[PFUser currentUser] forKey:#"User"];
[currentInstallation setDeviceTokenFromData:[[NSUserDefaults standardUserDefaults] valueForKey:#"deviceToken"]];
currentInstallation.channels = #[#"global"];
[currentInstallation saveInBackground];
UPDATE:
you need to make additions to installation table. Add column userID to installation and then get query installation table with current user's userID.
You can refer this https://www.parse.com/questions/retrieve-objectid-from-installation-table link for better understanding
Hope it helps :)
I am using Parse iOS SDK. I have problem in resetting the badge count. I am using the tutorial(parse) code to send push notifications. I am using increment for badge, but the badge count keeps on incrementing. I am resetting the badge count in applicationDidBecomeActive: method like this,
- (void)applicationDidBecomeActive:(UIApplication *)application {
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
if (currentInstallation.badge != 0) {
currentInstallation.badge = 0;
[currentInstallation saveEventually];
}
// ...
}
It just resets the badge number locally. But when I send the push notification next time, it just increments the previous count value and displays it. I guess the badge number in Parse server is not getting reset. Also, I tried to use [currentInstallation saveInBackground]; , but it not working too. Help
Try leaving away the if-statement (if you don't mind unnecessary api requests):
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
currentInstallation.badge = 0;
[currentInstallation saveEventually];
It seems that sometimes the installation.badge != 0 check fails.
This is how I solved my desynced badges.
I am using parse rest api from my php app to push to ios app. I can see in parse it has been pused to parse successfully
But how come parse not pushing these notificatioin to ios app?
You can do this by following the below steps:-
1) Register for remote notification from iOS app AppDelegate.m
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
[currentInstallation saveInBackground];
}
2) Subscribe the UDID to channels - Group channels as per your requirement
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation addUniqueObject:#"ChannelName" forKey:#"channels"];
[currentInstallation saveInBackground];
3) Send Notification to the particular channel from your php app.
From the push notification guide, Im noticing that parse recommends setting the device token from within the AppDelegate. Im interested in sending push notifications to certain users, and Im wondering if its possible to move the code for registering a device and their deviceToken within the login code which is found outside of the AppDelegate.
I think you should keep the deviceToken association in the delegate, but after the user logs in, grab the current installation and associate it with the user:
PFInstallation *current = [PFInstallation currentInstallation];
[current setObject:[PFUser currentUser] forKey:#"owner"];
[current saveInBackground];
You can run this code after login/ signup in application
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:sharedInstance.DeviceToken];
[currentInstallation setObject:[PFUser currentUser] forKey:#"user"];
currentInstallation.channels = #[ #"channel" ];
[currentInstallation saveInBackground];