iOS) Push Notification using parse when app is background - ios

I looked a lot questions and answers for the same issue.
And What I know now is that
'didReceiveRemoteNotification' is not called when the app is background.
didReceiveRemoteNotification is just called when app is foreground or when user comes to app by tapping notification if its in background.
application:didFinishLaunchingWithOptions: is called when user taps on notification to open the app if its killed.
My situation is below:
I'm using parse to push and get notification.
I'm successful getting notification when app is foreground and I'm handling data and show alert and list notification at notification list.
But I can not get notification when app is background or killed.
But I check my app can get notification when my app is background or killed when using 'custom audience' of Parse as I want. (Like other famous applications)
What I want to is I want to get notification when app is background or killed like when I use 'custom audience' of Parse.
But when I use just API of Parse , it doesn't work as i want.
Is there anything I'm missing now?
My registering code is below:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
NSLog(#"didReceiveRemoteNotification executed : %#",userInfo);
NSInteger bettingIDX = [[userInfo objectForKey:#"betting_idx"] integerValue];
NSString *message = [userInfo objectForKey:#"message"];
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = [NSString stringWithFormat:#"%#",message];
NSUUID *uuid = [NSUUID UUID];
NSString *notificationKey = [uuid UUIDString];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSLog(#"DeviceToken : %#", deviceToken );
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
[currentInstallation saveInBackground];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
[Parse setApplicationId:#"applicationID"
clientKey:#"clientID"];
[PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}

Use method didFinishLaunchingWithOptions:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if let launchOptions = launchOptions as? [String: AnyObject],
let userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] as? [String: String] {
}
return true
}
The official documentation says the following:
The user taps the default button in the alert or taps (or clicks) the
app icon. If the default action button is tapped (on a device running
iOS), the system launches the app and the app calls its delegate’s
application:didFinishLaunchingWithOptions: method, passing in the
notification payload (for remote notifications) or the
local-notification object (for local notifications). Although
application:didFinishLaunchingWithOptions: isn’t the best place to
handle the notification, getting the payload at this point gives you
the opportunity to start the update process before your handler method
is called.

Related

How to register for push notifications AFTER login/register?

I need to register the user into the installation class in Parse after they login/register, but it does not register. There is no error printed, and when I breakpoint in the appdeleagate nothing happens.
viewDidLoad of viewcontroller after login/register
override func viewDidLoad() {
super.viewDidLoad()
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Sound, .Badge], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()
}
AppDelegate
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let installation = PFInstallation.currentInstallation()
installation["user"] = PFUser.currentUser()
installation.setDeviceTokenFromData(deviceToken)
installation.saveInBackgroundWithBlock({ (success: Bool, error: NSError?) -> Void in
if (error == nil){
print("saved installation")
}else{
print("error \(error)")
}
})
}
To register to receive push notifications via Apple Push Service you have to call a registerForRemoteNotifications() method of UIApplication.
If registration succeeds, the app calls your app delegate object’s application:didRegisterForRemoteNotificationsWithDeviceToken: method and passes it a device token.
You should pass this token along to the server you use to generate push notifications for the device. If registration fails, the app calls its app delegate’s application:didFailToRegisterForRemoteNotificationsWithError: method instead.
you can refer this Appcoda's beginner guide for push notifiction
Update :
#pragma mark - push notificaiton
-(void)registerToReceivePushNotification {
// Register for push notifications
UIApplication* application =[UIApplication sharedApplication];
[application registerForRemoteNotificationTypes:
UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound];
}
nd the two application delegate callbacks are in app delegate
// handle user accepted push notification, update parse
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken {
// Store the deviceToken in the current installation and save it to Parse.
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:newDeviceToken];
// enable future push to deviceId
NSUUID *identifierForVendor = [[UIDevice currentDevice] identifierForVendor];
NSString* deviceId = [identifierForVendor UUIDString];
[currentInstallation setObject:deviceId forKey:#"deviceId"];
[currentInstallation saveInBackground];
}
// handle push notification arrives when app is open
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
[PFPush handlePush:userInfo];
}
You can do the registration call at any time - and it is a good idea to only do so when you know in the app you would like the user to receive push notifications.
The two application delegate callbacks have to be in your app delegate though, as you register for notification types on the application delegate and you only have one. I would suggest making an application delegate method to call that then does the registration, you could call it from your view controller through [[UIApplication sharedApplication] delegate] (cast the result of that call to your application delegate class).
code is in objective-c convert it in swift.
hope this will help :)

ios push messsage can not receive in background

I am beginner write about IOS push with swift. It works when app is running in foreground but not work while app in background or close.
By the way, I can receive alert message by APNS.newPayload().alertBody when app is in background or close.
Thank u much for help.
Below is my server and ios code.
iOScode
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("Recived: \(userInfo)")
var receiveMsg = userInfo["key1"] as! String
print("receiveMsg = \(receiveMsg)")
}
Server Code
ApnsService service =
APNS.newService()
.withCert("ooxx.p12","")
.withSandboxDestination()
.build();
String payload = APNS.newPayload().customField("key1", "M;senderGCMID5;senderUserID5;userName5;userMessage5").build();
String token = "token";
service.push(token, payload);
I have read some question about this topic, but I can not solve this problem.
I have tried the other function in iOS code like below, and it doesn't work.
APNS push working in foreground but not background
I don't know how to implement. Can u teach me ? thanks much
func application
(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
var receiveMsg = userInfo["key1"] as! String
print("receiveMsg = \(receiveMsg)")
}
thank pralthom for helping, I sovle the problem by setting content value = 1.
reference APN background refresh, setting up AppDelegate.m
I implemented the push notifications in Objective-C. I don't have the code in swift, but I guess it's very similar...
You have to register for push notification in the AppDelegate.
Add the following code in the didFinishLaunchingWithOptions delegate:
// Register for Push Notitications, if running iOS 8
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
UIUserNotificationTypeBadge |
UIUserNotificationTypeSound);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes
categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
} else {
// Register for Push Notifications before iOS 8
[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound)];
}
Then you have to add the following delegates also in the AppDelegate
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"DEBUG" message:[NSString stringWithFormat:#"Are you sure to use the right provisionning ? %#", error.localizedDescription] delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//Do whatever you want with the push received
It works in background and also when the app is killed. The app status is different for the OS if the app is killed.
There is one more delegate to add: didRegisterForRemoteNotificationsWithDevicetoken.
After you call the registerForRemoteNotifications method of the UIApplication object, the app calls this method when device registration completes successfully. In your implementation of this method, connect with your push notification server and give the token to it. APNs pushes notifications only to the device represented by the token.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *formattedToken = [[[deviceToken description]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]]
stringByReplacingOccurrencesOfString:#" "
withString:#""];
[[NSUserDefaults standardUserDefaults] setObject:formattedToken forKey:#"DEVICE_IDENTIFIER"];
[[NSUserDefaults standardUserDefaults] synchronize];
// Send the device identifier to your server
I think you didn't register the device and that's the reason the push comes only when the app is in foreground.
When you test your push notification, you should reset the push notification settings of your iPhone. You can find how to do this in the following post: Reset push notification settings for app

Push notification alert not displaying when coming out of background

Ive got the following code in my app delegate to display the text contained in a Push notification within a UIAlertView.
The code works fine while the app is still loaded in the background, however, once the app goes out of the background, the notification doesn't appear.
Can somebody much cleverer than me show me where I am going wrong, and what I need to do to fix it?
app Delegate.m:
#synthesize pushText;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[Parse setApplicationId:#"hGG5RdgNVdI7eCeZynV32lWYXywQRHkpp5zLdY7Q"
clientKey:#"TwmNbpBYEt4u3euE3lzNIgwyroSl8RPGF2dJFsPv"];
// Register for Push Notitications, if running iOS 8
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
UIUserNotificationTypeBadge |
UIUserNotificationTypeSound);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes
categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
} else {
// Register for Push Notifications before iOS 8
[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound)];
}
return YES;
NSMutableArray *alertTextArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"alertTextArray"];
NSDictionary *notifKey = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
if (notifKey)
{
[alertTextArray addObject:[notifKey objectForKey:#"alert"]];
}
[[NSUserDefaults standardUserDefaults] setObject:alertTextArray forKey:#"alertTextArray"];
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
if (currentInstallation.badge != 0) {
currentInstallation.badge = 0;
[currentInstallation saveEventually];
}
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// Store the deviceToken in the current installation and save it to Parse.
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
[currentInstallation saveInBackground];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[PFPush handlePush:userInfo];
pushText = [[userInfo objectForKey:#"aps"] objectForKey:#"alert"];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"News", "")
message:pushText
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
#end
Do you mean that when the app is in Foreground (= Running), notifications alert does not show ?
This is actually by design and how iOS notifications work.
If the app is running, notifications alert are not shown and it is up to your app to display them in a way that is meaningful for your application.
You get dictionary with push info when app restarts, it's in launch options, check docs.
ps: Copying my comment as answer

didReceiveRemoteNotification is not being called in background mode until I do not tap on notification in ios

I have searched for hours but somewhere is saying that,
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandlerNotification
is called, regardless of application is in active state or inactive state. Somewhere it says when application is not active it push notification calls your didFinishLaunchingWithOptions and there you can detect notification like this :
NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]`
In my case, both are working if user tap on notification and everything is fine, but the problem occurs when user does not tap on notification and direct open app from its icon, then neither didFinishLaunchingWithOptions detect it has notification nor didReceiveRemoteNotification get called. I need to save messages in database, received from push notification, but without tapping on notification how to call method?
to get notification data in didFinishLaunchingWithOptions do this code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if(launchOptions != nil)
{
NSDictionary *remoteNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
if(remoteNotif != nil){
[UIApplication sharedApplication].applicationIconBadgeNumber = [[[remoteNotif objectForKey:#"aps"] objectForKey: #"badge"] integerValue];
//do something here to process notification
}
}
}

Add alertview in application when you recive push notification

Hi Im currently developing an app where i have push notifications activated. I use parse.com. I have got it working so far that i can send a notification and the device receives it and i also get a badge on the app. But when i open the nothing happens and the badge does not disappear. I've set it in my appdelegate.m so parse is handling the push notifications. Heres some code that im using:
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken {
// Store the deviceToken in the current installation and save it to Parse.
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:newDeviceToken];
[currentInstallation saveInBackground];
}
and also:
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
[PFPush handlePush:userInfo];
}
Thanks
Ok thaks but how to i show the content of the push notification in the alert view? Or is that not a problem do i just have to configure a alertview with no text?
There are two scenarios:
App closed
When the app is closed and the user taps on a notification it's like when taps on the app icon. The app starts from application:didFinishLaunchingWithOptions:. To know if the app is opened normal (tap icon) or with a notification, just check the dictionary launchOptions for the key UIApplicationLaunchOptionsRemoteNotificationKey.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary * pushDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (pushDictionary)
{
//AlertView
}
}
App opened
When the app is opened there are two possible case
App in background UIApplicationStateInactive
App in foreground UIApplicationStateActive
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if (application.applicationState == UIApplicationStateInactive)
{
//AlertView
}
else if (application.applicationState == UIApplicationStateActive)
{
// AlertView
}
}
pushDictionary and userInfo are exactly the same dictionary that represents the notification.
Edit 1
A push notification is a JSON file that iOS automatically convert into a NSDictionary. The standard configuration is:
{"aps":
{
"alert":"Text message",
"sound":"default",
"badge":"1" //the number shown on the app's icon
}
}
From this base you can extend the JSON and put inside your own content. For example
{"aps":
{
"alert":"Text message",
"sound":"default",
"badge":"1" //the number shown on the app's icon
},
"Name":"Fry"
}
Now you can retrive the name in this very simple way:
NSString * name = userInfo[#"Name"];
and show it in the alert.
Edit 2
To show the content of push in UIAlertView just do this:
UIAlertView *av = [[UIAlertView alloc] initWithTitle:name
message:name
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Ok", nil];
[av show];
If you receive push notification while your app isn't active (killed)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
will not be triggered. Instead of that you will have to use object with key UIApplicationLaunchOptionsRemoteNotificationKey from launchOptions dictionary inside
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

Resources