When iPhone app is closed totally i.e. not even in background, then how APNS handling can be done.
e.g. Store APNS Data in sqlite when app is completely closed.
in AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (launchOptions)
{ //launchOptions is not nil
NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
userInfoDic = userInfo;
if (apsInfo)
{ //apsInfo is not nil
[self performSelector:#selector(postNotificationToPresentPushMessagesVC)
withObject:nil
afterDelay:1];
}
}
return YES;
}
-(void)postNotificationToPresentPushMessagesVC
{
[[NSNotificationCenter defaultCenter]postNotificationName:#"recievePush" object:userInfoDic];
}
in all VC:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(recievePush:) name:#"recievePush" object:nil];
}
- (void) recievePush : (NSNotification *) notif
{
NSDictionary *dict = notif.object;
// do something with message data
}
Related
My problem is, if app is in background and notification arrives and I opened the app from icon; app restores it states but I want to update the screen data in this case. Is there any way to update the data in background when notification arrives?
Here is the code which I'm using for tackling this case:
ViewController.m file code:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appIsComingFromBackground:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
// Do any additional setup after loading the view, typically from a nib.
}
- (void) appIsComingFromBackground:(NSNotification *) note {
// code
NSString *hasMessage = [[NSUserDefaults standardUserDefaults] objectForKey:#"alertmsg"];
if([hasMessage length]!=0)
{
_labelText.text = hasMessage;
[[NSUserDefaults standardUserDefaults] setObject:#"" forKey:#"alertmsg"];
}
else{
_labelText.text = #"";
}
}
AppDelegate.m file code:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if (application.applicationState == UIApplicationStateActive) {
}
else if(application.applicationState == UIApplicationStateBackground || application.applicationState == UIApplicationStateInactive)
{
[[NSUserDefaults standardUserDefaults] setObject:notification.alertTitle forKey:#"alertmsg"];
}
NSLog(#"Alert Message: %#", notification.alertTitle);
NSLog(#"Alert Body: %#", notification.alertBody);
}
Application is NOT Running
When the app is not running, users see notifications in the following ways, depending on the notification settings:
Displaying an alert or banner
Badging the app icon
Playing a sound
By tapping on action button of the notification, users will launch the app. In this case, the application:didFinishLaunchingWithOptions: method of the application delegate is called.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Handle launching from a notification
UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (locationNotification) {
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
}
return YES;
}
Applicaton is Running in Foreground
If the app is running while the notification is delivered, there is no alert displayed on screen. The application automatically calls its delegate’s application:didReceiveLocalNotification: method.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
}
// Request to reload table view data
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadData" object:self];
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
}
Application is Running in Background
The app has been launched before but users switch to another app. When the notification is fired, users normally see an alert banner at the top of the screen. When it’s tapped, the app will be brought to the foreground. Similar to the case that the app is running in foreground, the application automatically calls its delegate’s application:didReceiveLocalNotification: method.
In Appdelegate
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification
{
if (application.applicationState == UIApplicationStateActive) {
}
else if(application.applicationState == UIApplicationStateBackground || application.applicationState == UIApplicationStateInactive)
{
// [[NSUserDefaults standardUserDefaults] setObject:notification.alertTitle forKey:#"alertmsg"];
[[NSNotificationCenter defaultCenter]postNotificationName:#"PushNotificationReceived" object:nil userInfo:userInfo];
}
NSLog(#"Alert Message: %#", notification.alertTitle);
NSLog(#"Alert Body: %#", notification.alertBody);
}
In view controller:
-(void)viewDidLoad
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(doChangesWhatdidYouWant:) name:#"PushNotificationReceived" object:nil];
}
-(void)doChangesWhatdidYouWant:(NSNotification *)notification{
//Todo
}
Launch options is always nil.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Launch options is always coming nil
//even when I launch from 3D touch shortcut icon
shortcutItemkey = [launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey];
return N0;
}
performActionForShortcutItem delegate method is getting called as usual.
-(void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler {
completionHandler([self handleShortcut:shortcutItem]);
}
- (void)shortcutsWithIcon
{
#try
{
UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithTemplateImageName:#"img_editProduct"];
UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:#"img_Classifieds"];
UIMutableApplicationShortcutItem *item1 = [[UIMutableApplicationShortcutItem alloc]initWithType:#"com.3dtouchApp.postAnItem" localizedTitle:#"Post an Item" localizedSubtitle:#"Add new product for sale" icon:icon1 userInfo:nil];
UIMutableApplicationShortcutItem *item2 = [[UIMutableApplicationShortcutItem alloc]initWithType:#"com.3dtouchApp.LatestAds" localizedTitle:#"Latest Ads" localizedSubtitle:#"View top recent Ads" icon:icon2 userInfo:nil];
NSArray *items = #[item2, item1];
[UIApplication sharedApplication].shortcutItems = items;
}
#catch (NSException *exception) {
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (self.window.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
{
[self shortcutsWithIcon];
UIApplicationShortcutItem *item = [launchOptions valueForKey:UIApplicationLaunchOptionsShortcutItemKey];
if (item) {
NSLog(#"We've launched from shortcut item: %#", item.localizedTitle);
} else {
NSLog(#"We've launched properly.");
}
if ([item.type isEqualToString:#"com.3dtouchApp.postAnItem"])
{
***//Code for launch your screen***
}
if ([item.type isEqualToString:#"com.3dtouchApp.LatestAds"])
{
***//code for launch your screen***
}
}
return YES;
}
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
{
if ([shortcutItem.type isEqualToString:#"com.3dtouchApp.LatestAds"])
{
***//Code for launch your screen***
}
if ([shortcutItem.type isEqualToString:#"com.3dtouchApp.postAnItem"])
{
***//Code for launch your screen***
}
}
I used Pushbots to configure push notifications for my app. After I get the notification, I am able to put it into a UITableview. However the notification only appears after the user restarts the app. Is there a way to immediately add the notification text after the user gets it, or when the user clicks the notification?
In my AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[Pushbots sharedInstanceWithAppId:#"--myAppid--"];
[[Pushbots sharedInstance] receivedPush:launchOptions];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// This method will be called everytime you open the app
// Register the deviceToken on Pushbots
[[Pushbots sharedInstance] registerOnPushbots:deviceToken];
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(#"Notification Registration Error %#", [error userInfo]);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//Handle notification when the user click it while app is running in background or foreground.
[[Pushbots sharedInstance] receivedPush:userInfo];
//NSLog(#"UserInfo: %#", userInfo);
NSString *msg = [userInfo valueForKey:#"aps"];
NSString *alertMsg = [msg valueForKey:#"alert"];
//NSLog(#"Push Notification:%#",alertMsg);
[[NSUserDefaults standardUserDefaults]setObject:alertMsg forKey:#"ReceivedNotifications"];
NSLog(#"Alert: %#", alertMsg);
}
In my ViewController.m:
#import "ViewController.h"
#interface ViewController () <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *notifTableView;
#end
#implementation ViewController
{
NSMutableArray *notif;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.notifTableView.dataSource = self;
self.notifTableView.delegate = self;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *checkAlert = [[NSString alloc] init];
checkAlert = [defaults stringForKey:#"ReceivedNotifications"];
NSLog(#"Alert Message: %#", checkAlert);
notif = [NSMutableArray arrayWithObjects:checkAlert, nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [notif count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.textLabel.text = [notif objectAtIndex:indexPath.row];
return cell;
}
In your ViewController viewDidLoad method start listen to a NSNotification as below,
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:)
name:#"TestNotification"
object:nil];
Add this receiveNotification to your ViewController as well. Inside this if condition you can reload the TableView.
- (void) receiveNotification:(NSNotification *) notification
{
// [notification name] should always be #"TestNotification"
// unless you use this method for observation of other notifications
// as well.
if ([[notification name] isEqualToString:#"TestNotification"])
NSLog (#"Successfully received the test notification!");
}
Don't forget to remove the notification when you dealloc the ViewController,
[[NSNotificationCenter defaultCenter] removeObserver:self];
Then from your AppDelegate once you receive a notification, post a Notification to TestNotification name
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:nil]; //You can set object as nil or send the object you want to get from the ViewController
try to use NSNoticationCenter same as DilumN said in his answer , when you receive the notification then reload the tableview in that method.
How to set badge for UIBarButtonItem from Appdelegate (whenever push notification comes) if UITabbarcontroller is not the rootviewcontroller ?
I have a LoginViewController and a PinViewController before UITabbarcontroller. I'm setting LoginViewController as rootviewcontroller if user has not logged in and PinViewController as rootviewcontroller if user has already logged in. But I found that we could set badge for UIBarButtonItem from Appdelegate only if the rootviewcontroller is UITabbarcontroller.
Can anyone help me with this?
You can manage it by Posting Notifications
// In App Delegate Class
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSNumber *count = [NSNumber numberWithInt:5]; // This is static...
NSDictionary *dataDict = [NSDictionary dictionaryWithObject:count
forKey:#"count"];
application.applicationIconBadgeNumber = 0;
if (application.applicationState == UIApplicationStateActive)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"getPushNotification" object:dataDict];
}
}
In Controller where you want to update badge count on bar.
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateBadgeCount:)
name:#"getPushNotification"
object:nil];
}
- (void)updateBadgeCount:(NSNotification *)note {
NSDictionary *theData = [note userInfo];
if (theData != nil) {
NSNumber *n = [theData objectForKey:#"count"];
// Do your stuff here...
}
}
Thanks.
If i force close my app from background. then local notification come .And if tapped on local notification my method not called when app is running in foreground.I am newer in iOS. Please Help.
-(void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"Reh" object:nil];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Reminder"
message:notification.alertBody
delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil,nil];
[alert show];
NSLog(#"%#",notification.soundName);
// AudioServicesPlaySystemSound (1010);
MyNotificationViewController *profile=[[MyNotificationViewController alloc]initWithNibName:#"MyNotificationViewController" bundle:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"RefreshFoeByPush" object:nil];
self.viewController = [[SWRevealViewController alloc] initWithRearViewController:self.leftMenuController frontViewController:profile]; self.viewController.rightViewController=nil;
[UIView transitionWithView:self.window duration:0.5 options:UIViewAnimationOptionCurveEaseInOut
animations:^{self.window.rootViewController = self.viewController;} completion:nil];
application.applicationIconBadgeNumber = 0;
}
else
{
NSString *tokend= [[NSUserDefaults standardUserDefaults] stringForKey:#"token"];
if (tokend == (id)[NSNull null] || tokend.length == 0 )
{
}
else
{
MyNotificationViewController *profile=[[MyNotificationViewController alloc]initWithNibName:#"MyNotificationViewController" bundle:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"RefreshFoeByPush" object:nil];
self.viewController = [[SWRevealViewController alloc] initWithRearViewController:self.leftMenuController frontViewController:profile]; self.viewController.rightViewController=nil;
[UIView transitionWithView:self.window duration:0.5 options:UIViewAnimationOptionCurveEaseInOut
animations:^{self.window.rootViewController = self.viewController;} completion:nil];
}
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotification != nil) {
[self showLocalNotificationAlert:localNotification];
}
return YES;
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[self showLocalNotificationAlert:notification];
}
-(void)showLocalNotificationAlert:(UILocalNotification *)notification {
// handle here what you want
}
ALSO
When local notification fire didReceiveLocalNotification method is called not handleActionWithIdentifier
And yes put your stuff in common method -(void)showLocalNotificationAlert:(UILocalNotification *)notification so you just needs to call
When app is in forground then didReceiveLocalNotification this will called.
When app is not in forground and you tapped on notification then this notification object can be get from didFinishLaunchingWithOptions
For Remote Notification
In didFinishLaunchingWithOptions
NSDictionary *remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotification) {
[self showRemoteNotificationAlert:remoteNotification];
}
Dictionary contains payload for remotenotification
And also made common method for remote notification fire and remote notification tapped.
lol
When your app is killed and you tap on push notification this function will trigger;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
you should handle it like this,
UILocalNotification *localNotif = [launchOptionsobjectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
Parse or Do something
}