Action buttons on Remote Notification iOS 10 (objective C) is not coming IIViewDeckController - objective-c

After lot of googling and following apple's doc , still I am not able to get action button in remote(push) notification but I am getting it in local notification by following the same code for local notification.
- (void)triggerAndRegisterNotification {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"10.0")) {
// create actions
#if XCODE_VERSION_GREATER_THAN_OR_EQUAL_TO_8
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// create actions
UNNotificationAction *acceptAction = [UNNotificationAction actionWithIdentifier:#"com.AG.yes"
title:#"Save"
options:UNNotificationActionOptionForeground];
UNNotificationAction *declineAction = [UNNotificationAction actionWithIdentifier:#"com.AG.no"
title:#"Decline"
options:UNNotificationActionOptionDestructive];
UNNotificationAction *snoozeAction = [UNNotificationAction actionWithIdentifier:#"com.AG.snooze"
title:#"Snooze"
options:UNNotificationActionOptionDestructive];
NSArray *notificationActions = #[ acceptAction, declineAction, snoozeAction ];
// create a category
UNNotificationCategory *inviteCategory = [UNNotificationCategory categoryWithIdentifier:CYLInviteCategoryIdentifier actions:notificationActions intentIdentifiers:#[] options:UNNotificationCategoryOptionNone];
NSSet *categories = [NSSet setWithObject:inviteCategory];
// registration
[center setNotificationCategories:categories];
#endif
} else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
// create actions
UIMutableUserNotificationAction *acceptAction =
[[UIMutableUserNotificationAction alloc] init];
acceptAction.identifier = #"com.AG.yes";
acceptAction.title = #"Accept";
acceptAction.activationMode =
UIUserNotificationActivationModeBackground;
acceptAction.destructive = NO;
acceptAction.authenticationRequired = NO; //If YES requies
passcode, but does not unlock the device
UIMutableUserNotificationAction *declineAction =
[[UIMutableUserNotificationAction alloc] init];
declineAction.identifier = #"com.AG.no";
acceptAction.title = #"Decline";
acceptAction.activationMode =
UIUserNotificationActivationModeBackground;
declineAction.destructive = YES;
acceptAction.authenticationRequired = NO;
UIMutableUserNotificationAction *snoozeAction =
[[UIMutableUserNotificationAction alloc] init];
snoozeAction.identifier = #"com.AG.snooze";
acceptAction.title = #"Snooze";
snoozeAction.activationMode =
UIUserNotificationActivationModeBackground;
snoozeAction.destructive = YES;
snoozeAction.authenticationRequired = NO;
// create a category
UIMutableUserNotificationCategory *inviteCategory =
[[UIMutableUserNotificationCategory alloc] init];
inviteCategory.identifier = CYLInviteCategoryIdentifier;
NSArray *notificationActions = #[ acceptAction, declineAction,
snoozeAction ];
[inviteCategory setActions:notificationActions
forContext:UIUserNotificationActionContextDefault];
[inviteCategory setActions:notificationActions
forContext:UIUserNotificationActionContextMinimal];
// registration
NSSet *categories = [NSSet setWithObject:inviteCategory];
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:types
categories:categories];
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
}
/// 2. request authorization for localNotification
[self registerNotificationSettingsCompletionHandler:^(BOOL
granted,
NSError * _Nullable error) {
if (granted) {
NSLog(#"request authorization succeeded!");
[[UIApplication sharedApplication]
registerForRemoteNotifications];
}
}];
**COMMENTED CODE FOR LOCAL NOTIFICATION**
// if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"10.0")) {
// #if XCODE_VERSION_GREATER_THAN_OR_EQUAL_TO_8
// Deliver the notification at 08:30 everyday
// NSDateComponents *dateComponents = [[NSDateComponents
alloc] init];
// dateComponents.hour = 8;
// dateComponents.minute = 30;
// UNCalendarNotificationTrigger *trigger =
// [UNCalendarNotificationTrigger
triggerWithDateMatchingComponents:dateComponents
repeats:YES];
// UNMutableNotificationContent *content =
[[UNMutableNotificationContent alloc] init];
// content.title = [NSString
localizedUserNotificationStringForKey:#"AG said:"
arguments:nil];
// content.body = [NSString
localizedUserNotificationStringForKey:#"Hello Tom!Get up,
let's play with Jerry!" arguments:nil];
// content.sound = [UNNotificationSound
defaultSound];
// content.categoryIdentifier =
CYLInviteCategoryIdentifier;
/// 4. update application icon badge number
// content.badge = #([[UIApplication sharedApplication]
applicationIconBadgeNumber] + 1);
// content.launchImageName = #"any string is ok,such as
微博#iOS程序犭袁";
// Deliver the notification in five seconds.
//*** Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'time interval
must be at least 60 if repeating'
// UNTimeIntervalNotificationTrigger *trigger =
[UNTimeIntervalNotificationTrigger
// triggerWithTimeInterval:60.0f repeats:YES];
// UNNotificationRequest *request = [
UNNotificationRequest
requestWithIdentifier:#"FiveSecond"
// content:content trigger:trigger];
// UNUserNotificationCenter *center =
[UNUserNotificationCenter currentNotificationCenter];
/// 3. schedule localNotification,The delegate must be set before
the application returns from
applicationDidFinishLaunching:.
// center.delegate = self;
// [center addNotificationRequest:request
withCompletionHandler:^(NSError * _Nullable error) {
// if (!error) {
// NSLog(#"add NotificationRequest succeeded!");
// }
// }];
//#endif
// } else {
/// 3. schedule localNotification
// UILocalNotification *localNotification =
[[UILocalNotification alloc] init];
// localNotification.fireDate = [NSDate
dateWithTimeIntervalSinceNow:5.f];
// localNotification.alertTitle = #"AG said:";
// localNotification.alertBody = #"Hello Tom!Get up,
let's play with Jerry!";
// localNotification.alertAction = #"play with Jerry";
//Identifies the image used as the launch image when the user
taps (or slides) the action button (or slider).
// localNotification.alertLaunchImage =
#"LaunchImage.png";
// localNotification.userInfo = #{ #"CategoryIdentifier"
: CYLInviteCategoryIdentifier };
//
// localNotification.timeZone = [NSTimeZone
defaultTimeZone];
//repeat evey minute, 0 means don't repeat
// localNotification.repeatInterval = NSCalendarUnitMinute;
/// 4. update application icon badge number
// localNotification.applicationIconBadgeNumber =
[[UIApplication sharedApplication]
applicationIconBadgeNumber] + 1;
// [[UIApplication sharedApplication]
scheduleLocalNotification:localNotification];
//
// }
}
/// 3. THIS IS THE METHOD TO AUTHORIZE THE NOTIFICATION
- (void)registerNotificationSettingsCompletionHandler:(void (^)(BOOL
granted, NSError *__nullable error))completionHandler; {
/// 2. request authorization for localNotification
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"10.0")) {
#if XCODE_VERSION_GREATER_THAN_OR_EQUAL_TO_8
UNUserNotificationCenter *center = [UNUserNotificationCenter
currentNotificationCenter];
[center requestAuthorizationWithOptions:
(UNAuthorizationOptionBadge | UNAuthorizationOptionSound
| UNAuthorizationOptionAlert)
completionHandler:completionHandler];
#endif
} else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0"))
{
// UIUserNotificationSettings
*userNotificationSettings = [UIUserNotificationSettings
settingsForTypes:(UIUserNotificationTypeAlert |
UIUserNotificationTypeSound |
UIUserNotificationTypeBadge)
//
categories:nil];
// UIApplication *application = [UIApplication
sharedApplication];
// [application
registerUserNotificationSettings:userNotificationSettings];
//FIXME:
// !completionHandler ?: completionHandler(granted, error);
}
}
**AND IN** APPDELEGATE.m
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"10.0")) {
#if XCODE_VERSION_GREATER_THAN_OR_EQUAL_TO_8
/// schedule localNotification, the delegate must be set before
// the application returns fromapplicationDidFinishLaunching:.
UNUserNotificationCenter *center = [UNUserNotificationCenter
currentNotificationCenter];
center.delegate = self;
#endif
}
[self triggerAndRegisterNotification];
}
I am using iphone 7 for testing purpose.
Please help me solve this. Thanks in Advance
Payload JSon
aps = {
alert = {
"artist_id" = 16912;
body = "Kurt Rosenwinkel is playing at Joe Henderson Lab at
SFJAZZ Center";
eventid = 149687805;
sound = default;
timestamp = "810b6035-e4d7-4722-81db-7455e81a48fe";
title = "Kurt Rosenwinkel";
tracks = "itunes,spotify";
type = 2;
};
category = "com.wcities.notification";
};
I checked the category identifier which I set in my app is also same as in payload json.
UPDATE
As I debugged and come to the point that from above code I am getting push notification with action buttons but in some where after did finish launching I am changing my windows root view controller to view controller which is a child of IIViewDeckController.
After commenting this line push notification is coming with action buttons. I am totally confused why it is happening because as per my knowledge there should not be any impact on push notifications if I set or present or push any viewcontroller.
please let me know If I am doing any mistakes here. I have shared all code and scenario above.
Thanks

As I am using dockview library so the viewcontrollers which are added in dock view controller had some code related to setting categories as nil.That is the reason due to which I couldn't able to get the action button in remote notification so I remove this extra code and everything is working fine. I am still finding that stupid person who wrote this code. Appretiate the help

in ios 10 notification work with -(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
//code
completionHandler(UNNotificationPresentationOptionAlert);
}
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
}

Related

GCM Push Notifications are not coming on iPhone when app is not active for one day

On iPhone/iPad after installing the app, app is able to receive notification first time. Once app is inactive, then it stops getting notification in both foreground and background.
Can someone point, what I am I missing . Looks like no issue with message format since I get first time.
Server Code:
message.put("priority", "high");
message.put("content_available",true);
if (to != null)
{
message.put("to", to.replace("\\", ""));
}
if (messageId != null)
{
message.put("message_id", messageId);
}
JSONObject subobj = new JSONObject();
subobj.put("sound", "default");
message.put("notification", subobj);
message.put("data", payload);
if (timeToLive != null)
{
message.put("time_to_live", timeToLive);
}
if (delayWhileIdle != null && delayWhileIdle)
{
message.put("delay_while_idle", true);
}
if (collapseKey != null)
{
message.put("collapse_key", collapseKey);
}
message.put("delivery_receipt_requested", true);
Client Code:
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
// First run Delete keychain
if (![[NSUserDefaults standardUserDefaults] objectForKey:#"FirstRun"]) {
// Delete values from keychain here
application.applicationIconBadgeNumber = 0;
[self resetKeychain];
[[NSUserDefaults standardUserDefaults] setValue:#"1strun" forKey:#"FirstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
self.viewController = [[MainViewController alloc] init];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
#if __has_feature(objc_arc)
self.window = [[UIWindow alloc] initWithFrame:screenBounds];
#else
self.window = [[[UIWindow alloc] initWithFrame:screenBounds]
autorelease];
#endif
self.window.autoresizesSubviews = YES;
//notification
[self updateDurationLabel];
UIFont *font = [UIFont boldSystemFontOfSize:10.0f];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
[self.segFromStyle setTitleTextAttributes:attributes forState:UIControlStateNormal];
[self.segToStyle setTitleTextAttributes:attributes forState:UIControlStateNormal];
[self flowManager];
UILocalNotification *remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotification) {
application.applicationIconBadgeNumber = 0;
self.launchNotification = remoteNotification.userInfo;
NSLog(#"NotificationCheck: remoteNotification");
}
UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotification) {
application.applicationIconBadgeNumber = 0;
NSLog(#"NotificationCheck: localNotification");
self.launchNotification = localNotification.userInfo;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:localNotification.userInfo options:0 error:nil];
NSString* jsonString = [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
NSLog(#"Dict:%#", jsonString);
}
[self.window makeKeyAndVisible];
return YES;
}
You may refer with this thread wherein it suggested to add the "priority": "high" to the JSON toget the notifications in the background.
{
"to" : "token...",
"priority": "high",
"notification" : {
"title": "GCM TITLE",
"body" : "FROM GCM",
"badge": "1",
"sound": "default"
}
}
Additional references:
GCM push notification to iOS with content_available (not working to invoke from inactive state)
GCM support for ios application when application in background or killed
Making GCM work for iOS device in the background

watch os 2 not waking parent app and changing UITableView of parent

I have a watch app that is being updated for watch os 2. The sendmessage does not wake the parent app. According to the transition documentation is this how you would wake a parent in the background.
"The iOS app is always considered reachable, and calling this method from your Watch app wakes up the iOS app in the background as needed."
Has anyone had this problem? The only way to get data is to have the parent app already open.
Another weird thing is the watch app changes the uitableview for the parent app. When the -(IBAction)yesterdaySales:(id)sender is called on the watch, it changes the parent app UITableView instead of the watch tableview.
InterfaceController.m
#import "InterfaceController.h"
#import "MyRowController.h"
#import "ftDateParser.h"
#import WatchKit;
#import <WatchConnectivity/WatchConnectivity.h>
#interface InterfaceController() <WCSessionDelegate>
{
IBOutlet WKInterfaceDevice *it;
BOOL tday;
IBOutlet WKInterfaceLabel *lblCompany;
}
#end
#implementation InterfaceController
#synthesize myTable = _myTable;
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
if([WCSession isSupported]){
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
//[self requestInfoPhone];
[self getToday];
}
- (void)willActivate {
// This method is called when watch view controller is about to be visible to user
[super willActivate];
}
- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
[super didDeactivate];
}
-(void)requestInfoPhone{
NSDictionary *dic = #{#"request":#"ySales"};
[[WCSession defaultSession] sendMessage:dic
replyHandler:^(NSDictionary *replyInfo){
NSLog(#"The Reply: %#", replyInfo);
NSDictionary *location = replyInfo;
NSString *name = location[#"label"];
NSString *totalSales = location[#"totalSales"];
// NSString *test2 = location[#"rowText"];
NSMutableArray *sales = [[NSMutableArray alloc]init];
NSMutableArray *storeNames = [[NSMutableArray alloc]init];
sales = location[#"rowText"];
storeNames = location[#"storeNames"];
[self loadTable:sales names:storeNames company:name];
[_labelName setText:name];
[_labelTotalSales setText:totalSales];
tday = YES;
}
errorHandler:^(NSError *error){
NSLog(#"%#", error);
}
];
}
-(void)loadTable:(NSMutableArray*)tester names:(NSMutableArray*)names company:(NSString *)company{
[_myTable setNumberOfRows:[tester count] withRowType:#"row"];
[_labelName setText:company];
for (int i = 0; i < [tester count]; i++) {
MyRowController *vc = [_myTable rowControllerAtIndex:i];
[vc.testLabel setText:[ftDateParser currencyFormat: tester[i]]];
[vc.nameLabel setText:[ftDateParser parseName:names[i]]];
}
[_myTable scrollToRowAtIndex:(0)];
}
-(IBAction)yesterdaySales:(id)sender{
if (tday) {
[_ydaySales setTitle:#"Today Sales"];
[self requestInfoPhone];
}
else{
[_ydaySales setTitle:#"Yesterday Sales"];
[self getToday];
}
}
-(void)getToday{
NSDictionary *dic = #{#"request":#"todaySales"};
[[WCSession defaultSession] sendMessage:dic
replyHandler:^(NSDictionary *replyInfo){
NSDictionary *location = replyInfo;
NSString *name = location[#"label"];
NSString *totalSales = location[#"totalSales"];
// NSString *test2 = location[#"rowText"];
NSMutableArray *sales = [[NSMutableArray alloc]init];
NSMutableArray *storeNames = [[NSMutableArray alloc]init];
sales = location[#"rowText"];
storeNames = location[#"storeNames"];
[self loadTable:sales names:storeNames company:name];
[_labelName setText:name];
[_labelTotalSales setText:totalSales];
tday = YES;
}
errorHandler:^(NSError *error){
NSLog(#"%#", error);
}
];
}
#end
Parent.m
-(void)setUpAppForWatch{
done = NO;
if([WCSession isSupported]){
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
}
-(void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *,id> *)message replyHandler:(void (^)(NSDictionary<NSString *,id> * _Nonnull))replyHandler{
/*UIApplication *application = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier identifier = UIBackgroundTaskInvalid;
dispatch_block_t endBlock = ^ {
if (identifier != UIBackgroundTaskInvalid) {
[application endBackgroundTask:identifier];
}
identifier = UIBackgroundTaskInvalid;
};
identifier = [application beginBackgroundTaskWithExpirationHandler:endBlock];*/
[self setUpAppForWatch];
[self getTheDate];
startDate = todayDay;
endDate = tomorrow;
//[self getTodaySalesforWatch];
NSString *currency = [ftDateParser currencyFormat:totalSales];
NSDictionary *dic = #{#"label": [NSString stringWithFormat:#"%#", #"Town Crier, Inc."],
#"totalSales": currency,
#"rowText": storeSalesData,//[NSString stringWithFormat:#"%#", currency]
#"storeNames":storeNames
};
NSString *request = [message objectForKey:#"request"];
if ([request isEqualToString:#"todaySales"]) {
[self getTodaySalesforWatch];
}
else if ([request isEqualToString:#"ySales"]){
[self connectToWebService];
}
if (done) {
replyHandler(dic);
}
}
Edit:
Maybe the changes to the parent app were happening before, but I didn't know cause the app was running in the background. Still can't get it to wake the parent app.
You don't link to the source of the quote at the top of your question but it must be referring to the openParentApplication method of WatchKit 1. Devices running WatchOS 2.0 cannot call openParentApplication.
The method you're implementing in the code in your question is for a WCSession, which only works for immediate communication between a WatchKit app extension and an iOS app that are both running at the same time. This method does not cause your iOS app to launch, neither in the background nor in the foreground. Other asynchronous communication methods must be used if both apps are not running at the time.

Update UIMutableUserNotificationAction Button Title on Remote Push Notification

I have an app in iOS where I am sending quick surveys to the users. I want to make use of the new funcionality in iOS 8 where the user interacts directly on the push notification. The user will receive the survey question and respond.
I know you have to construct your actions and categories when starting the app. I have written my code and have been able to successfully perform this so far.
Now, the thing is that the text on the action button will change based on the survey question. I am including the keys and text for the action buttons on the JSON I am sending, but I haven't been able to change the action button titles when receiving the notification.
Is there a way to do this? Here is my code:
I define global variables:
//This will help configure the interactive notifications, so that the user can reply to push notification from out of the app
NSString * const notificationCategoryIdent = #"SURVEY";
NSString * const notificationActionPositiveButton = #"POSITIVE_BUTTON";
NSString * const notificationActionNegativeButton = #"NEGATIVE_BUTTON";
In my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if(pushNotificationPayload) {
urlPushData2 = #"Application was closed";
[self application:[UIApplication sharedApplication] didReceiveRemoteNotification:pushNotificationPayload];
}
//Registrar tipos de aviso para Push Notifications
//if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)]){
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0){ //Before iOS 8
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)];
}
else {
// define notification actions (In case of categorized remote push notifications)
positiveButton = [[UIMutableUserNotificationAction alloc] init];
[positiveButton setActivationMode:UIUserNotificationActivationModeForeground];
[positiveButton setTitle:notificationActionPositiveButton];
[positiveButton setIdentifier:notificationActionPositiveButton];
[positiveButton setDestructive:NO];
// this action wil be executed without necessity of passcode authentication (if locked)
[positiveButton setAuthenticationRequired:NO];
negativeButton = [[UIMutableUserNotificationAction alloc] init];
[negativeButton setActivationMode:UIUserNotificationActivationModeForeground];
[negativeButton setTitle:notificationActionNegativeButton];
[negativeButton setIdentifier:notificationActionNegativeButton];
[negativeButton setDestructive:NO];
// this action wil be executed without necessity of passcode authentication (if locked)
[negativeButton setAuthenticationRequired:NO];
// define Categories (In case of categorized remote push notifications)
UIMutableUserNotificationCategory *actionCategory;
actionCategory = [[UIMutableUserNotificationCategory alloc] init];
[actionCategory setIdentifier:notificationCategoryIdent];
[actionCategory setActions:#[positiveButton, negativeButton]
forContext:UIUserNotificationActionContextDefault];
NSSet *categories = [NSSet setWithObject:actionCategory];
UIUserNotificationType types = (UIUserNotificationTypeAlert|
UIUserNotificationTypeSound|
UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
//Boolean value for temporary app interruptions
temporaryInactivity = FALSE;
return YES;
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"remote notification: %#",[userInfo description]);
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
NSString *alert = [apsInfo objectForKey:#"alert"];
//NSLog(#"Received Push Alert: %#", alert);
NSString *sound = [apsInfo objectForKey:#"sound"];
NSLog(#"Received Push Sound: %#", sound);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
application.applicationIconBadgeNumber = [[apsInfo objectForKey:#"badge"] integerValue];
self.mainUrl = [userInfo valueForKey:#"url"];
urlPushData = [NSString stringWithFormat:#"%#", mainUrl];
//NSLog(#"urlPushData: %#",urlPushData);
self.mainUrl2 = [userInfo valueForKey:#"url2"];
urlPushData2 = [NSString stringWithFormat:#"%#", mainUrl2];
//NSLog(#"urlPushData2: %#",urlPushData2);
NSString *category = [apsInfo objectForKey:#"category"];
NSLog(#"category: %#", category);
if ([category isEqualToString:notificationCategoryIdent]) {
NSLog(#"button1: %#", [apsInfo objectForKey:#"positiveButton"]);
NSLog(#"button2: %#", [apsInfo objectForKey:#"negativeButton"]);
NSString *stringPositiveButton = [apsInfo objectForKey:#"positiveButton"];
NSString *stringNegativeButton = [apsInfo objectForKey:#"negativeButton"];
[positiveButton setTitle:stringPositiveButton];
[negativeButton setTitle:stringNegativeButton];
}
else {
if (![urlPushData2 isEqualToString:#"Application was closed"]) {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
[[NSUserDefaults standardUserDefaults] setObject:urlPushData2 forKey:#"pushNotificationURL"];
[[NSUserDefaults standardUserDefaults] setObject:alert forKey:#"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults]synchronize];
if (NSClassFromString(#"UIAlertController")) {
//make and use a UIAlertController
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:#"%#",appNameLink]
message:[NSString stringWithFormat:#"Has recibido una nueva nota: %#. ¿Deseas verla?",alert]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *Cancel = [UIAlertAction actionWithTitle:#"No"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"pushNotificationURL"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
];
UIAlertAction *OK = [UIAlertAction actionWithTitle:#"Sí"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
self.url = [[NSUserDefaults standardUserDefaults] objectForKey:#"pushNotificationURL"];
self.urlName = [[NSUserDefaults standardUserDefaults] objectForKey:#"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"pushNotificationURL"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults]synchronize];
[self setupNavigationControllerApp];
}
];
[alertView addAction:Cancel];
[alertView addAction:OK];
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alertView animated:YES completion:nil];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:[NSString stringWithFormat:#"%#",appNameLink] message:[NSString stringWithFormat:#"Has recibido una nueva nota: %#. ¿Deseas verla?",alert] delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Sí", nil];
[alertView show];
}
} else {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
//self.url = [[NSUserDefaults standardUserDefaults]objectForKey:#"pushNotificationURL"];
self.url = urlPushData2;
self.urlName = alert;
[self setupNavigationControllerApp];
}
}
}
- (void) application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {
if ([identifier isEqualToString:notificationActionPositiveButton]) {
//Testing the action button
self.url = #"http://www.google.com";
self.urlName = #"hello";
[self setupNavigationControllerApp];
}
else if ([identifier isEqualToString:notificationActionNegativeButton]) {
//Testing the action button
self.url = #"http://www.yahoo.com";
self.urlName = #"goodbye";
[self setupNavigationControllerApp];
}
// Must be called when finished
completionHandler();
}
And this is my JSON:
{"aps":
{"alert":"Who's your favorite pop singer?",
"badge":1,
"sound":"default",
"category":"SURVEY",
"positiveButton":"Katy Perry",
"negativeButton":"Miley Cyrus"
},
"url":"http://www.pretechmobile.com",
"url2":"http://goo.gl/U9p1y"
}
I am sorry, but you cannot change the title of the buttons dynamically. They are tied to the category in which they are stored when you register for notifications.
A possible workaround could be to present the two options in the text of the message labeled with an 'A' and a 'B' and have your buttons with titles 'Option A' and 'Option B'. Something like this:
---------------------------------
|Who's your favorite pop singer?|
|A: Katy Perry B: Miley Cyrus|
---------------------------------
| Option A | Option B |
---------------------------------
Also, If you have yes/no questions, you can create a category for them with the options 'Yes' and 'No' and label your notifications with this category.
I hope this helps a bit.

How to Implement iOS8 Interactive Notification

I am developing an iOS8 application which supports interactive notification. But I don't have clarity on the features supported by interactive notification and how to send/handle interactive notifications. If any one can give an example, that would be very much helpful for me.
Thanks in Advance :)
First you need to create the notification Action.
Second you need to create the notification category and set its actions.You can set for two contexts. UIUserNotificationActionContextDefault or UIUserNotificationActionContextMinimal
Third you need to create the notification setting and assign the above categories
Fourth step would be to create local notification and assign it the identifier of the category.
UIMutableUserNotificationAction *notificationAction1 = [[UIMutableUserNotificationAction alloc] init];
notificationAction1.identifier = #"Accept";
notificationAction1.title = #"Accept";
notificationAction1.activationMode = UIUserNotificationActivationModeBackground;
notificationAction1.destructive = NO;
notificationAction1.authenticationRequired = NO;
UIMutableUserNotificationAction *notificationAction2 = [[UIMutableUserNotificationAction alloc] init];
notificationAction2.identifier = #"Reject";
notificationAction2.title = #"Reject";
notificationAction2.activationMode = UIUserNotificationActivationModeBackground;
notificationAction2.destructive = YES;
notificationAction2.authenticationRequired = YES;
UIMutableUserNotificationAction *notificationAction3 = [[UIMutableUserNotificationAction alloc] init];
notificationAction3.identifier = #"Reply";
notificationAction3.title = #"Reply";
notificationAction3.activationMode = UIUserNotificationActivationModeForeground;
notificationAction3.destructive = NO;
notificationAction3.authenticationRequired = YES;
UIMutableUserNotificationCategory *notificationCategory = [[UIMutableUserNotificationCategory alloc] init];
notificationCategory.identifier = #"Email";
[notificationCategory setActions:#[notificationAction1,notificationAction2,notificationAction3] forContext:UIUserNotificationActionContextDefault];
[notificationCategory setActions:#[notificationAction1,notificationAction2] forContext:UIUserNotificationActionContextMinimal];
NSSet *categories = [NSSet setWithObjects:notificationCategory, nil];
UIUserNotificationType notificationType = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:notificationType categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10];
localNotification.alertBody = #"Testing";
localNotification.category = #"Email"; // Same as category identifier
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
I would like to extend Sourav Gupta's answer a bit. Once you have done up to what Sourav explained, you have to implement the delegates for receiving push notification actions. The delegates are,
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void(^)())completionHandler {
// Handle actions of local notifications here. You can identify the action by using "identifier" and perform appropriate operations
if(completionHandler != nil) //Finally call completion handler if its not nil
completionHandler();
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler {
// Handle actions of remote notifications here. You can identify the action by using "identifier" and perform appropriate operations
if(completionHandler != nil) //Finally call completion handler if its not nil
completionHandler();
}
You can refer remote notification payload sample here iOS8 Push notification Payload

GameCenter Invitation Handler

trying to implement a multiplayer. Using the sample from Game Center - Sending and receiving data.
Everything seems okay, but in apple documentation there is also said about invitation handler.
[GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
// Insert application-specific code here to clean up any games in progress.
if (acceptedInvite) {
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
mmvc.matchmakerDelegate = self;
[self presentModalViewController:mmvc animated:YES];
} else if (playersToInvite) {
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 2;
request.maxPlayers = 4;
request.playersToInvite = playersToInvite;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
[self presentModalViewController:mmvc animated:YES];
}
};
The problem is quite simple: I do not know where to add this code.
As stated in the docs
Your application should set the
invitation handler as early as
possible after your application is
launched; an appropriate place to set
the handler is in the completion block
you provided that executes after the
local player is authenticated.
Somewhere in your code, you should have authenticated the local player with something like this
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
if (error == nil) {
// Insert your piece of code here
} else {
// Handle the error
}
}];
Hope that helps
My code is below, and it works very well. In the authenticateLocalUser, add the code below:
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
[GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) { // Add for invite handler
// Insert application-specific code here to clean up any games in progress.
if (acceptedInvite) {
GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] ;
mmvc.matchmakerDelegate = self;
// [self presentModalViewController:mmvc animated:YES];
[_delegate matchStart];
} else if (playersToInvite) {
GKMatchRequest *request = [[GKMatchRequest alloc] init] ;
request.minPlayers = 2;
request.maxPlayers = 2;
request.playersToInvite = playersToInvite;
GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithMatchRequest:request] ;
mmvc.matchmakerDelegate = self;
// [self presentModalViewController:mmvc animated:YES];
[_delegate matchStart];
}
};
[self callDelegateOnMainThread:#selector(processGameCenterAuth:) withArg:NULL error:error];
}];