Facebook openActiveSessionWithReadPermission reach completion too fast with status fail - objective-c

[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:
^(FBSession *session,
FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
Well, after a while an alert show us saying that my application tries to access facebook and ask whether it's allowed or not.
However, that alert shows up AFTER completion handler is reached.
State is already FBSessionStateClosedLoginFailed by that time.
What should I do? Works fine in simulator.
Actually scrumptious sample in face book also fail on my iPhone. But I have facebook apps installed and logged in.

Facebook Login checklist:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [FBSession.activeSession handleOpenURL:url];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// We need to properly handle activation of the application with regards to SSO
// (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
[FBSession.activeSession handleDidBecomeActive];
}
- (void)applicationWillTerminate:(UIApplication *)application {
// if the app is going away, we close the session object; this is a good idea because
// things may be hanging off the session, that need releasing (completion block, etc.) and
// other components in the app may be awaiting close notification in order to do cleanup
[FBSession.activeSession close];
}
In my sessionStateChanged: I am doing this
switch ( state ) {
case FBSessionStateOpen:
[[Facebook _instance] fbDialogLogin:session.accessToken expirationDate:session.expirationDate];
break;
case FBSessionStateClosed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
case FBSessionStateClosedLoginFailed:
break;
default:
NSLog(#"FBSessionStateUnknown: %d", state);
break;
}
And dont forget to make sure that your FacebookAppID and BundleID is the same as the one you create in Facebook Developer Dashboard!

Related

IOS 8 Registering for remote notification only half-works

EDIT
I'll put this at the top as this seems to possibly be the issue. After registering user settings, I NSLog:
NSLog(#"current notifications : %#", [application currentUserNotificationSettings]);
I receive back:
current notifications : <UIUserNotificationSettings: 0x165844a0; types: (none);>
But as you can see, I am clearly registering the settings to use badge, sound, and alerts.
Also, I guess I should mention that I have turned off notifications in
my settings. However, I expect it to call
didFailToRegisterForRemoteNotificationsWithError in this case which
is where I generate my own phone ID.
-- I take back what I said above. When I delete the app and reinstall it, it turns back on Allow Notifications. --
I know this question is on here a lot, but I just cannot seem to get this working. Here is my dumbed-down code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self registerForNotifications:application];
}
- (void)registerForNotifications:(UIApplication *)application {
// Let the device know we want to receive push notifications
NSLog(#"Registering for Remote Notifications");
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
#ifdef __IPHONE_8_0
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
|UIRemoteNotificationTypeSound
|UIRemoteNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
#endif
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
NSLog(#"Done registering for Remote Notifications");
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
NSLog(#"Did register for remote notification settings");
//register to receive notifications
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
NSLog(#"There was an error?");
//handle the actions
if ([identifier isEqualToString:#"declineAction"]){
}else if ([identifier isEqualToString:#"answerAction"]){
}
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
NSLog(#"My token is: %#\nMy device token is: %#\nSend Phone ID is: %#", [self loadSettings:#"phone_id"], deviceToken, [self loadSettings:#"send_phone_id"]);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Failed to register for remote notifications");
}
For my NSLog statements, this is all I receive:
2014-11-11 14:57:11.066 eTicket[3144:988203] Registering for Remote Notifications
2014-11-11 14:57:11.083 eTicket[3144:988203] Done registering for Remote Notifications
2014-11-11 14:57:11.148 eTicket[3144:988203] Settings Validated?: NO
2014-11-11 14:57:11.219 eTicket[3144:988203] Did register for remote notification settings
Ignore the "Settings Validated" line. That's just me checking to see if they've successfully logged in already to skip some steps. That part works and doesn't have anything to do with remote notifications.
I'm getting no indication that it registered for notifications successfully or not, or that there is an error. The application does not crash or throw errors. I am lost as to why none of the bottom methods are being hit.
Thanks,
James
Well it seems that I had everything right for the most part above. However, after registering the settings, I needed to check to see if any settings were actually turned on. If not, I needed to send them to my own function. So I did this:
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
NSLog(#"Did register for remote notification settings");
NSLog(#"current notifications : %#", [[UIApplication sharedApplication] currentUserNotificationSettings]);
//register to receive notifications
if (notificationSettings.types) {
NSLog(#"user allowed notifications");
[[UIApplication sharedApplication] registerForRemoteNotifications];
}else{
NSLog(#"user did not allow notifications");
// show alert here
[self doNotRegisterForRemoteNotifications];
}
}
doNotRegisterForRemoteNotifications is my own function where I do what I need to do to generate a phone ID of my own.

iOS facebook SDK: Login already authenticated

I have had the Facebook iOS SDK running in an app I've been working on for a few months. At this point I am mostly using the SDK for SSO purposes.
Since I have started using iOS 6.0 I have been seeing an issue where the "Login to use your FB account with MY_APP" modal is blocking my current view.
The odd thing is that the user is already authenticated and apparently authorized to use my app. This is proven by the fact that I can get the user's email address and such.
It is also important to note that if I click the "X" it will close and everything is fine (user is authenticated/authorized). If I login as it tells me, it shows the "MY_APP is already authorized" modal which I cannot click the "Okay" button but I can click the "X" which again drops me back into my view with the user authenticated and authorized.
Here you can see the it:
To authenticate I am calling the following method in the appdelegate:
[appDelegate openSessionWithAllowLoginUI:YES];
The following are the relevant FB methods in my appdelegate:
// FACEBOOK STUFF
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [NSArray arrayWithObjects: #"email", nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self sessionStateChanged:session state:status error:error];
}];
}
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState)state
error:(NSError *)error {
// FBSample logic
// Any time the session is closed, we want to display the login controller (the user
// cannot use the application unless they are logged in to Facebook). When the session
// is opened successfully, hide the login controller and show the main UI.
switch (state) {
case FBSessionStateOpen: {
FBCacheDescriptor *cacheDescriptor = [FBFriendPickerViewController cacheDescriptor];
[cacheDescriptor prefetchAndCacheForSession:session];
[self sendAuthenticationStatusChangedNotification];
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
// FBSample logic
// Once the user has logged in, we want them to be looking at the root view.
[FBSession.activeSession closeAndClearTokenInformation];
//[self showLoginView];
break;
default:
break;
}
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// FBSample logic
// We need to handle URLs by passing them to FBSession in order for SSO authentication
// to work.
return [FBSession.activeSession handleOpenURL:url];
}
EDIT 1
I noticed that this is happing on one of my phones but not the other. The phone that wasn't working had an older version of the FB app installed. Updating the FB app stopped this issue from happening. I am still interested in a fix to avoid others from experiencing the same issue.
EDIT 2
The issue went away for a little but now is back even with the new facebook app installed. Please help!
The problem for me actually turned out to be a silly one. I was calling
[appDelegate openSessionWithAllowLoginUI:YES];
two times due to a button click event that was wired up twice. As soon as it was only being called once, the issue went away!

Facebook sdk: ActiveSession is still closed after I give permission

I am integrating facebook login in my application. I jsut want the user to be able to login and I get his birthday and Location.
I got the latest Facebook SDK and successfully added it to my application. I also created a new application on facebook and added the key provided to my application.
I have created a button "Login with facebook" and done the following
When the user clicks the button
// handler for button click
- (IBAction)facebookLoginTouched:(id)sender {
[self openSessionWithAllowLoginUI:YES];
}
This method will show the user the facebook login page in order to get his permission
-(BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_location",
#"user_birthday",
nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self HandleLogin];
}];
}
Then if login and permission successful
- (void)HandleLogin {
if (FBSession.activeSession.isOpen) {
//THIS IS NEVER REACHED
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection,
id<FBGraphUser> user,
NSError *error) {
//DO SOMETHING WITH THE USER INFO
}];
}
}
My problem:
When I click on the button the facebook page comes in correctly and I enter my username/password. It logged me correctly and I gave permission for the application to access my information. When I finish, I return to the app successfully.
However when the code reaches FBSession.activeSession.isOpen it returns false.
Why is the session still closed after I correctly logged in and gave permission?
Any help is greatly appreciated.
Thanks
You may be missing code to process the return from the Facebook app. Add the following in your app delegate implementation file:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBSession.activeSession handleOpenURL:url];
}

Authenticating the local player - Game Center - iOS6

I'm completely new to development in Game Center. I have watched the videos in WWDC and looked at the developer website. They suggest I enter code like this for iOS 6:
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil)
{
[self showAuthenticationDialogWhenReasonable: viewController
}
else if (localPlayer.isAuthenticated)
{
[self authenticatedPlayer: localPlayer];
}
else
{
[self disableGameCenter];
}
}];
}
I have copied this into the app delegate.m file, however it does not like it, showing errors like expecting a ] after [self showAuthenticationDialogWhenReasonable: viewController
} amongst others.
Can anyone please tell me how to authenticate the user for game center in iOS 6?
To get an introduction to GameKit, there are samples available from apple, for example:
https://developer.apple.com/library/ios/#samplecode/GKLeaderboards/Introduction/Intro.html.
In your code you are missing the closing "]", but of course you need more than just this function to connect to the gameCenter. Best start with one of the samples.
Apple has posted incorrect code, the ]; towards the end of the code belongs at the end of this line [self showAuthenticationDialogWhenReasonable: viewController
this code is not needed because this is just explaining how the method authenticateLocalPlayer works inside of Gamekit
Here's what I did without having to use the deprecated methods:
Set the authentication handler immediately in the AppDelegate by calling the function below (I put it in a singleton helper object). At this time, there is no view controller from which to show the login view controller, so if authentication fails, and the handler gives you a view controller, just save it away. This is the case when the user is not logged in.
- (void)authenticateLocalUserNoViewController {
NSLog(#"Trying to authenticate local user . . .");
GKLocalPlayer *_localPlayer = [GKLocalPlayer localPlayer];
__weak GKLocalPlayer *localPlayer = _localPlayer; // Avoid retain cycle inside block
__weak GCHelper *weakself = self;
self.authenticationViewController = nil;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
if (viewController) {
NSLog(#"User not logged in");
weakself.authenticationViewController = viewController; // save it away
} else if (localPlayer.authenticated) {
[[GKLocalPlayer localPlayer] unregisterListener:self];
[[GKLocalPlayer localPlayer] registerListener:self];
NSLog(#"Local player %# (%#) authenticated. ID = %#",localPlayer.alias, localPlayer.displayName, localPlayer.playerID);
} else {
// Probably user cancelled the login dialog
NSLog(#"Problem authenticating %#", [error localizedDescription]);
}
};
}
Then, once your main screen has loaded, and the user wants to press a button the start an online game, present the login view controller that you stashed away earlier. I put this in another method in my helper class. When the user logs in, it will trigger an execution of your original authentication block, but the viewcontroller parameter will be nil.
-(BOOL) showGameCenterLoginController:(UIViewController *)presentingViewController {
if (self.authenticationViewController) {
[presentingViewController presentViewController:self.authenticationViewController animated:YES completion:^{
}];
return YES;
} else {
NSLog(#"Can't show game center view controller!");
return NO; // Show some other error dialog like "Game Center not available"
}
}

why didRegisterForRemoteNotificationsWithDeviceToken is not called

I am making an application in which I want to implement apple push notification service. I am following the step-by-step instructions given in this tutorial.
But still, the methods are not called. I don't know what is causing the problem. Can anyone help me?
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//NSString * token = [[NSString alloc] initWithData:deviceTokenencoding:NSUTF8StringEncoding];
NSString *str = [NSString stringWithFormat:#"Device Token=%#",deviceToken];
NSLog(#"Device Token:%#",str);
//NSLog(#"Device token is called");
//const void *devTokenBytes = [deviceToken bytes];
//NSLog(#"Device Token");
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSString *str = [NSString stringWithFormat: #"Error: %#", err];
NSLog(#"Error:%#",str);
}
I had the same issue: calling registerForRemoteNotificationTypes: invoked neither application:didRegisterForRemoteNotificationsWithDeviceToken: nor application:didFailToRegisterForRemoteNotificationsWithError:
I eventually resolved this issue with the help of Apple's technical note TN2265.
This is what I did:
First off, I double-checked that I am indeed registering correctly for Push Notifications, including verifying my provisioning profile for "aps-environment" key and the codesigning of the .app file itself. I had it all set up correctly.
I then had to debug Push Notification status messages in the console (you need to install PersistentConnectionLogging.mobileconfig provisioning profile on your device and reboot it. See TN2265 under "Observing Push Status Messages"). I noticed that apns process starts a timer and calculates a minimum fire date, which made me suspect that the Push-Notification registration confirmation message, which is normally presented at this point, is supressed by APNS, as indicated in TN2265:
Resetting the Push Notifications Permissions Alert on iOS
The first time a push-enabled app registers for push notifications, iOS asks the user if they wish to receive notifications for that app. Once the user has responded to this alert it is not presented again unless the device is restored or the app has been uninstalled for at least a day.
If you want to simulate a first-time run of your app, you can leave the app uninstalled for a day. You can achieve the latter without actually waiting a day by setting the system clock forward a day or more, turning the device off completely, then turning the device back on.
So, I removed the app from the device, then manually changed the iPhone's date in Settings, rebooted the device, and re-installed the app.
The next time my code called registerForRemoteNotificationTypes, it received callbacks as expected.
This resolved the issue for me. Hope it helps.
In iOS 8, some methods are deprecated. Follow the steps below for iOS 8 compatibility
1. Register notification
if([[UIDevice currentDevice] systemVersion].floatValue >= 8.0)
{
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound|UIRemoteNotificationTypeBadge)];
}
2. Add new 2 methods
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
[application registerForRemoteNotifications];
}
//For interactive notification only
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
//handle the actions
if ([identifier isEqualToString:#"declineAction"]){
}
else if ([identifier isEqualToString:#"answerAction"]){
}
}
Note : above two new methods are required in iOS 8 in addition to didRegisterForRemoteNotificationsWithDeviceToken and didReceiveRemoteNotification..Otherwise delegate method will not be invoked.
See: Remote Notification iOS 8
In iOS 8, in addition to requesting push notification access differently, you also need to register differently.
Request Access:
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
// iOS 8
UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
// iOS 7 or iOS 6
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
Handle registered device:
// New in iOS 8
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[application registerForRemoteNotifications];
}
// iOS 7 or iOS 6
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
// Send token to server
}
Bear in mind that remote notifications are not supported in the simulator. Therefore, if you run your app in the simulator, didRegisterForRemoteNotificationsWithDeviceToken won't be called.
Make sure you call in your code (update according to supported notification kinds)
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
and the provisioning profile is APNS enabled. You may need to re-download the provisioning profile after enabing APNS. If you have troubles and you get errors, then maybe you should create an Entitlements.plist and add the key "aps-environment" with value "development" or "production" depending on the kind of build (normally this key-value pair is contained in the provisioning profile, but sometimes Xcode mess with them).
If the provisioning profiles are used before to Enable and Configure Apple Push Notification service, you will need to redownload the provisioning profiles again.
Delete provisioning profiles from Xcode Organizer and from the iPhone/iPad.
Go to Settings -> General -> Profiles -> [Your provisioning] -> Remove.
Install the new downloaded provisioning profiles. Then clean and run the project from XCode.
Now didRegisterForRemoteNotificationsWithDeviceToken should be called.
Try this it working for me ,
First Step
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
In above method add below code
UIApplication *application = [UIApplication sharedApplication];
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
|UIUserNotificationTypeSound
|UIUserNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
}
else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
Second Step
Add below code Function
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
//handle the actions
if ([identifier isEqualToString:#"declineAction"]){
}
else if ([identifier isEqualToString:#"answerAction"]){
}
}
#endif
You will get device Token in below function
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
for detail answer please refer This
Hope this is help for some one .
I made a mistake and overlooked an implementation detail that lead me here. I tried to get fancy and ask the user for Push Notifications later in the application onboarding process, so I had my registerForRemoteNotificationTypes, didRegisterForRemoteNotificationsWithDeviceToken and didFailToRegisterForRemoteNotificationsWithError all in a custom UIView.
FIX: the didRegisterForRemoteNotificationsWithDeviceToken and didFailToRegisterForRemoteNotificationsWithError need to be in the UIApplicationDelegate (YourAppDelegate.m) to be triggered.
seems obvious now, heh.
Be sure that your internet connection is on.
This took me hours to get work notifications because of internet connection.
If you have added push to an existing App ID, make sure you re-generate your provisioning profiles. If you don't, the profile will not know about your enabling of push on the App ID.
-​(BOOL)application:(UIApplication​*)application​ didFinishLaunchingWithOptions:(NSDictionary​*)launchOptions​{​​​​ ​​​​ ​​​​//​Override​point​for​customization​after​application​launch.
​​​​//​Add​the​view​controller’s​view​to​the​window​and​display. ​​​​[window​addSubview:viewController.view]; ​​​​[window​makeKeyAndVisible];
NSLog(#”Registering for push notifications...”);
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound)];
​​​​return​YES;
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
}
NSString *str = [NSString stringWithFormat:#”Device Token=%#”,deviceToken];
NSLog(#”%#”, str);
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSString *str = [NSString stringWithFormat: #”Error: %#”, err]; NSLog(#”%#”, str);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
}
for (id key in userInfo) { NSLog(#”key: %#, value: %#”, key, [userInfo objectForKey:key]);
}
Minimal Requirement to Get Device Token:No need to configure app id, provisioning or certificate etc thus no code signing set to get the delegate method didRegisterForRemoteNotificationsWithDeviceToken called.
I just created a new iOS project in Xcode 7 for single view with default settings and gave a random bundle id like com.mycompany.pushtest which is not configured in apple dev portal. With the following code, I'm getting my device token in didRegisterForRemoteNotificationsWithDeviceToken method on my iPad with internet access to WIFI. My device is attached and I'm just running the app directly from xcode and viewing the values in xcode's console.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
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, if running iOS version < 8
[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}
return YES;
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Error: %#", error.description);
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"didRegisterForRemoteNotificationsWithDeviceToken: %#", deviceToken);
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
NSLog(#"NotificationSettings: %#", notificationSettings);
}
After wasting the most annoying 3h, here are the steps to fix the issue:
Delete the app
Reset the device
Run again
It just worked
This happened to me, because I reset & deleted all the data on the phone (wanted a dev phone to use). This prevented APN from connecting at all after setting up the phone again.
I tried all sorts of things, but the only thing that fixed it was setting the phone up to work with a carrier under a new SIM card.
This link offers more hints as to what might have been going on: https://developer.apple.com/library/ios/technotes/tn2265/_index.html
It says that APN tries to connect preferentially via carrier / towers as opposed to wifi. Maybe the issue also was something was going on with the router blocking port 5223 on the wifi network, but I doubt it because it worked fine on the prior day before the global reset occurred.
I have a point on this.Recently I too face this problem.I have done everything
according to documentation but delegate method was not calling.Finally I saw
one post saying that problem with the network.Then I have changed network and
it works fine.So take care about network also because few networks can block
the APNS.
I had a different issue wherein my push notification callbacks were getting hijacked by the 3rd party libraries, that I had included, namely Firebase. These libraries swizzle push notification callback methods to get the callbacks.
Hope this helps someone.
For me what solved it was going to the build settings and under the code signing section, manually selecting the code signing identity and provisioning profile. Apparently the automatic setting wasn't picking-up the correct one and therefore the app wasn't properly authorized.
if shut down push message of app,
appdidRegisterForRemoteNotificationsWithDeviceToken will never be called
Also, don't forget to check the system status at Apple https://developer.apple.com/system-status/.
I'd tried all the solutions posted above but in the end the fault was because the APNS service was down! The next day all was working again as expected.
Also, you have a typo in your callback method:
- (void)application:(UIApplication *)appdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
As Rupesh pointed out the correct method name is:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
That's probably why you never received the token in your case!
You need to call registerForNotifications method from didFinishLaunchingWithOptions.
func registerForNotifications(){
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options:[.alert,.sound,.badge]) { (granted, error) in
if granted{
UIApplication.shared.registerForRemoteNotifications()
}else{
print("Notification permission denied.")
}
}
} else {
// For iOS 9 and Below
let type: UIUserNotificationType = [.alert,.sound,.badge];
let setting = UIUserNotificationSettings(types: type, categories: nil);
UIApplication.shared.registerUserNotificationSettings(setting);
UIApplication.shared.registerForRemoteNotifications()
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = String(format: "%#", deviceToken as CVarArg).trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "")
print(token)
}
extension AppDelegate : UNUserNotificationCenterDelegate{
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
print("Handle push from foreground”)
let info = ((notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
if let type = info.value(forKey: "type") as? Int{
if type == 0 {
// notification received ,Handle your notification here
}
}
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Handle push from background or closed")
let info = ((response.notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
if let type = info.value(forKey: "type") as? Int{
if type == 0 {
// notification received ,Handle your notification here
}
}
}
}