Is the a way of knowing if the user declined the push notifications permissions?
I know that didRegisterForRemoteNotificationsWithDeviceToken will be called in case the user allowed push notifications - but what will be called if he didn't?
A simple method to check whether notification is enabled in app or not.
-(BOOL)checkNotificationEnabled
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
{
return FALSE; //Notification not enabled
}
else
{
return TRUE;//Notification is enabled
}
}
else // for iOS 8 devices checking will be different
{
return [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
// if return TRUE then Notification is enabled
// if return False then Notification is not enabled
}
}
According to the UIApplicationDelegate Protocol Reference, application(_:didFailToRegisterForRemoteNotificationsWithError:) is called if an error occurs during the registration process.
After you call the registerForRemoteNotifications method of the UIApplication object, the app calls this method when there is an error in the registration process.
For more information about how to implement remote notifications in your app, see Local and Remote Notification Programming Guide.
You can implement in following way. Suppose that if user allows notification then you can store device token into user default. Now, next time you can check with same user default weather user allowed or not.
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
NSString *aStrToken = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
aStrToken = [aStrToken stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *aStrStoredToken = [_appDelegate validateString:[[NSUserDefaults standardUserDefaults]objectForKey:#"deviceID"] :#""];
if([aStrStoredToken length]==0) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"getDeviceToken" object:nil];
[self setApplicationBadgeNumber:0];
[[NSUserDefaults standardUserDefaults]setObject:aStrToken forKey:#"deviceID"];
[[NSUserDefaults standardUserDefaults]synchronize];
if(![[NSUserDefaults standardUserDefaults]objectForKey:#"setDeviceID"]) {
[[NSUserDefaults standardUserDefaults]setObject:#"0" forKey:#"setDeviceID"];
[[NSUserDefaults standardUserDefaults]synchronize];
} else {
[[NSUserDefaults standardUserDefaults]setObject:#"1" forKey:#"setDeviceID"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
}
}
Related
Currently one of my php developer provided me push notification API for iOS devices
The problem is : If i run that api with respective parameter in any Browser(Chrome/Safari/Firefox and etc..) i am getting notification on foreground of iOS device. But not in iOS app(Xcode) itself
In my app i used code like:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for Push Notitications, if running on iOS 8
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}
#pragma mark
#pragma mark -- Push Notification Delegate Methods
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings: (UIUserNotificationSettings *)notificationSettings{
//register to receive notifications
[application registerForRemoteNotifications];
}
-(void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{
// Prepare the Device Token for Registration (remove spaces and < >)
devToken = [[[[deviceToken description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"My token is: %#", devToken);
// My token is: cd2887c4093569b3eed142320f21a81e521e486cf5c40467390901d3a191398b
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:deviceToken forKey:#"deviceToken"];
}
-(void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error{
NSLog(#"Failed to get token, error: %#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSLog(#"%s..userInfo=%#",__FUNCTION__,userInfo);
}
I am getting response:(in didReceiveRemoteNotification)
{
aps = {
alert = "You're login successfully";
sound = default;
};
}
This message is not showing on Status bar(top of the screen). Is there any issue in iOS side (or) PHP side
If the issue is in iOS side--> How can i do this
Here is my Testing Push notification API:
https://shopgt.com/mobile1/iphone/register.php?device_type=2&email=sukhpal#anaad.net®Id=4d1d9067cc1382ecb8b0532831cce7fc8eb6fc388a6139060cd84712407a0ae5
Can you please help me out regarding this issue
You need to customize the view for showing Banner of Push Notification while the app in Foreground. You can use JCNotificationBannerPresenter. Follow the sample code using below link.
https://github.com/jcoleman/JCNotificationBannerPresenter
#import "JCNotificationCenter.h"
#import "JCNotificationBannerPresenterSmokeStyle.h"
- (void) application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)notification {
NSString* title = #"Push Notification";
NSDictionary* aps = [notification objectForKey:#"aps"];
NSString* alert = [aps objectForKey:#"alert"];
[JCNotificationCenter
enqueueNotificationWithTitle:title
message:alert
tapHandler:^{
NSLog(#"Received tap on notification banner!");
}];
}
Hope it Helps you..!
There is no issue, this is default behaviour.
The banner that appears at the top of the screen when you are on the Home screen does not appear when you are inside the app.
You need to get the app to do something with the notification yourself, inside didReceiveRemoteNotification. This could be showing an alert, adding a badge to the tab bar, etc. but banners only show when you are outside of the app.
in my iOS App i have an UIWebView so how i can open a specified URL in the UIWebView, with a push notification?
If somebody open the App with the notification, i want to show a specified Website in
the UIWebView.
Can I bind the URL (in background) with the push notification?
Thank you.
According to Apple...
If the app is running and receives a remote notification, the app
calls this method to process the notification. Your implementation of
this method should use the notification to take an appropriate course
of action. ... If the app is not running when a push notification
arrives, the method launches the app and provides the appropriate
information in the launch options dictionary. The app does not call
this method to handle that push notification. Instead, your
implementation of the application:willFinishLaunchingWithOptions: or
application:didFinishLaunchingWithOptions: method needs to get the
push notification payload data and respond appropriately.
So, there are three possible scenarios:
1) App is in foreground: you will have full control, just implement didReceiveNotification and do whatever you want.
2) App is running, but in background: the action won't be triggered until the user actually open your app using the received notification.
3) The app is not running: in this case you should implement didFinishLaunchingWithOptions in order to get the additional info and perform the task.
So the code should look like this for didFinishLaunchingWithOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *userInfo = [launchOptions valueForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"];
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
if(apsInfo) {
// Get the URL or any other data
}
}
And this is an approximation for didReceiveNotification
/**
* Remote Notification Received while application was open.
*/
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
#if !TARGET_IPHONE_SIMULATOR
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive)
{
NSString *message = nil;
id aps = [userInfo objectForKey:#"aps"];
if ([aps isKindOfClass:[NSDictionary class]]) {
message = [aps objectForKey:#"alert"];
}
if (message) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Notificación"
message:message
delegate:self
cancelButtonTitle:#"Aceptar"
otherButtonTitles:nil, nil];
[alertView show];
}
}
// Aditional data
NSString *url = [userInfo objectForKey:#"url"];
NSLog(#"Received Push URL: %#", url);
if(url!=nil)
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
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);
NSString *badge = [apsInfo objectForKey:#"badge"];
NSLog(#"Received Push Badge: %#", badge);
application.applicationIconBadgeNumber = [[apsInfo objectForKey:#"badge"] integerValue];
#endif
}
I want to fire some event if user taps on "Don't Allow" button on the apple's push notification alert message. Is there any notification getting fired or any other way to detect this action from the user?
I'm sure someone will need a solid and simple answer to this (like I once did) -- so here you go. Directly after calling [[UIApplication sharedApplication] registerForRemoteNotifications]; you can use NSNotificationCenter beautifully like so:
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification * _Nonnull note) {
if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]) {
//user tapped "Allow"
}
else{
//user tapped "Don't Allow"
}
}];
NOTE: My device is currently running iOS 9.2, my Xcode is version 7.2, and my Deployment Target is 8.0.
I do't thing so that we can detect what UIAlertView button user pressed as there is no any kind of callback methods or delegate etc provided in iOS.
Only if you pressed Don't Allow this will disable the push notification service for that particular iOS App and if YES then enable.
And After that through the code we can check and ensure about it using.
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
// NONE
iOS8 comes with rregisterUserNotificationSettings: delegate method. Using this method we can do some patches.Please review them and Let us know your comments.Please these is only work with iOS8.
=> Add/Register Notification.
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)])
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
}
=> Here Below method is called After Alert Notification Fire. Using Any of the Button Action(Don't allow or Allow) we force fully register Notification. and Dow with some patch Here.
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
[application registerForRemoteNotifications];
}
=>We do some trick here
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
NSLog(#"devToken: %#",devToken);
#if !TARGET_IPHONE_SIMULATOR
NSString* deviceToken = [[[[[devToken description]
stringByReplacingOccurrencesOfString: #"<" withString: #""]
stringByReplacingOccurrencesOfString: #">" withString: #""]
stringByReplacingOccurrencesOfString: #" " withString: #""] retain];
NSLog(#"deviceToken : %#",deviceToken);
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
if((![[standardDefaults valueForKey:#"DeviceToken"] isEqualToString:deviceToken]) || [standardDefaults valueForKey:#"DeviceToken"]==nil){
[self sendProviderDeviceToken:deviceToken];
}else{
//Do Some Stuff Here
}
}
My app registers the account at login in my server to enable push notification for a chat. Yet I haven't implemented yet the unregistration of the account at logout, so in this moment if I do the login with 2 accounts in the same device it can take the notification of both the accounts. At the same time, my notification center has a POST service which unregisters the 'login_name+ device token' from receive notification center. Where should I call it? Do I have to use unregisterForRemoteNotifications? I just want to unregister the account+Device token from push notification, not to disable the entire app notification forever.
Can I save my device token on didRegisterForRemoteNotificationsWithDeviceToken function like
$ [[NSUserDefaults standardUserDefaults] setObject:hexToken forKey:DEVICE_KEY];
and then, at logout, call my POST function "removeDeviceToken" like
NSString *deviceToken = [userDefaults objectForKey:DEVICE_KEY];
if(deviceToken != NULL){
[self.engine removeDeviceToken:deviceToken];
}
You can easily enable and disable push notifications in your application by calling
To register, call: registerForRemoteNotificationTypes:
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
To unregister, call: unregisterForRemoteNotificationTypes:
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
For check use
Enable or Disable iPhone Push Notifications try this code
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
// Yes it is..
I'm not sure if i got it correctly, but if you don't want to disable push notifications for the app, then you should't call the unregisterForRemoteNotifications. What you can do is, when the user taps the logout button, you can make a logout request to your server, which then removes the notificationID from that account, and after the logout request is completed, you just perform the logout locally (update UI etc).
More info about comment:
Yes, first of all, you should call registerForRemoteNotificationTypes method at every launch, because device token can change. After the delegate method
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken
is called, you can get the device token and save it to NSUserDefault. That way when the user logs in, you can get the up-to-date device token (if changed), and send it to your server to be added to that account.
So the code might look like this
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
NSString *newToken = [devToken description];
newToken = [newToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
newToken = [newToken stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *notificationID = [newToken description];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:notificationID forKey:#"notification_id"];
[prefs synchronize];
}
So, now when the user logs in, just get the notification ID and send it to your server
- (IBAction)userTappedLoginButton {
// Make your login request
// You can add the notification id as a parameter
// depending on your web service, or maybe make
// another request just to update notificationID
// for a member
NSString *notificationID = [[NSUserDefaults standardUserDefaults] objectForKey:#"notification_id"];
...
...
}
With Swift:
To Register,
UIApplication.shared.registerForRemoteNotifications()
To unregister,
UIApplication.shared.unregisterForRemoteNotifications()
In general it is a bad idea to unregisterForRemoteNotifications after logout and reregister after login. The reason is simple: if the user logins with another account and you don't specifically check for token overlapping in server, the user will start receiving double notifications.
When an application need to register for push notification (UIApplication registerForRemoteNotificationTypes) a popup show Allow/Don't choice.
Is there a way to track when the user take this choice ?
Because the solution:
NSUInteger rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
is fine, but until the user touch something it's NO by default. I should only check this config after the user make a choice.
The consequence is that in my EasyAPNS server most of the application are in 'disabled' mode until the user relaunch them (because the second time the correct config will be pushed to my sever). So with the first launch the real choice of the user is probably not taken into account (if you accept really rapidly, before my app register to EasyAPNS then your choice is reflected back on the server at first launch)
Any idea ?
There seems to be no way to determine whether the allow pop-up has been shown. I rely on user defaults to keep track of this:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
BOOL didRegisterForPush = [[NSUserDefaults standardUserDefaults] boolForKey:#"didRegisterForPush"];
if (!didRegisterForPush) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"didRegisterForPush"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
// .. send deviceToken to server
}
Now you can determine the authorization state using:
- (PushAuthorizationStatus)pushAuthorizationStatus
{
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types) {
return kPushAuthorizationStatusAuthorized;
}
BOOL didRegisterForPush = [[NSUserDefaults standardUserDefaults] boolForKey:#"didRegisterForPush"];
if (didRegisterForPush) {
return kPushAuthorizationStatusDenied;
}
return kPushAuthorizationStatusNotDetermined;
}
Using this you can send the NotDetermined state to the server instead of Denied.
Under iOS 8 and later the procedure is a little different. In iOS 8 the enabledRemoteNotificationTypes method was replaced by isRegisteredForRemoteNotifications.
However isRegisteredForRemoteNotifications always returns YES if the app attempted to register for notifications, regardless of whether the user actually allowed them or not.
To determine whether the user actually allowed notifications, use the function provided by #Lefteris here:
- (BOOL)pushNotificationsEnabled {
if ([[UIApplication sharedApplication] respondsToSelector:#selector(currentUserNotificationSettings)]) {
UIUserNotificationType types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
return (types & UIUserNotificationTypeAlert);
}
else {
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
return (types & UIRemoteNotificationTypeAlert);
}
}