为什么不调用registerForRemoteNotificationsWithDeviceToken


88

我正在制作一个要实现苹果推送通知服务的应用程序。我正在按照本教程中的分步说明进行操作。

但是仍然没有调用这些方法。我不知道是什么引起了问题。谁能帮我?

    - (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);    
    }

无需添加任何其他代码,只需检查它即可链接stackoverflow.com/a/39849892/3269536
jenish

Answers:


73

我有同样的问题:打电话 registerForRemoteNotificationTypes:调用既不调用application:didRegisterForRemoteNotificationsWithDeviceToken:也不调用application:didFailToRegisterForRemoteNotificationsWithError:

我最终在Apple技术说明的帮助下解决了这个问题 TN2265

这就是我所做的:

首先,我仔细检查了我是否确实正确注册了“推送通知”,包括验证我的“ aps-environment”密钥的配置文件和.app文件本身的代码签名。我所有的设置都正确。

然后,我不得不在控制台中调试“推送通知”状态消息(您需要在设备上安装PersistentConnectionLogging.mobileconfig配置文件并重新启动它。请参阅“观察推送状态消息”下的TN2265)。我注意到apns进程启动了一个计时器并计算了最小触发日期,这使我怀疑此时通常显示的Push-Notification注册确认消息已被APNS禁止,如TN2265所示:

在iOS上重置推送通知权限警报

首次启用推送的应用程序注册推送通知时,iOS会询问用户是否希望接收该应用程序的通知。用户响应此警报后,除非恢复设备或将应用程序卸载至少一天,否则不会再次显示该警报。

如果要模拟应用程序的首次运行,可以将应用程序卸载一天。通过将系统时钟设置为一天或一天​​以上,完全关闭设备,然后重新打开设备,无需实际等待一天即可实现后者。

因此,我从设备上删除了该应用程序,然后在“设置”中手动更改了iPhone的日期,重新启动了设备,然后重新安装了该应用程序。

下次我的代码调用时registerForRemoteNotificationTypes,它按预期收到了回调。

这为我解决了这个问题。希望能帮助到你。


1
对我来说,关键点是我在另一台计算机上使用了较旧的开发证书。从主要开发笔记本电脑传输最新证书可以解决此问题。
Markus Rautopuro 2014年

3
启用后,需要推送通知以再次生成配置文件。
托尼

3
嗨!尽管这是一篇过时的文章,但我发现有时在关闭和打开应用程序的所有“通知”设置后,该问题都会得到解决。因为上次我记得didRegisterForRemoteNotificationsWithDeviceToken被调用,然后突然没有调用。希望能帮助到你。
otakuProgrammer

1
我只能通过添加另一个重置步骤来使其工作:1.删除应用程序2.重置设备3.转发时钟1天以上4.再次重置设备5.现在安装,它应该提示推送通知警报
etayluz

同样重要的是,要确保您在Xcode或设备本身中没有同一开发配置文件的多个“有效”副本。也许您创建了一个新的APN证书,并在前一个证书过期后重新创建了配置文件。旧的开发配置文件仍可作为开发配置文件使用,但不足以启用APN。您将看到有关“没有有效的APS权利等等”的典型错误。
jaredsinclair

66

在iOS 8中,不建议使用某些方法。请按照以下步骤操作以实现iOS 8兼容性

1.注册通知

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.添加新的2种方法

- (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"]){
    }
}

注意:除了didRegisterForRemoteNotificationsWithDeviceToken和之外,iOS 8还需要以上两个新方法。否则,didReceiveRemoteNotification将不会调用委托方法。

请参阅:远程通知iOS 8


1
那两个新方法应该放在Appdelegate.m中吗?
伊桑·帕克

-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {//注册以接收通知[application registerForRemoteNotifications]; }添加以下内容很危险,它使我的手机崩溃了,此时我什至无法恢复出厂设置。
约翰

如果您要在这里结束,这可能就是您要寻找的答案。奇怪的是,今天早些时候没有我添加这些方法之一就给该代表打电话。现在好像我都需要它们。
2015年

我的应用程序与此行崩溃[application registerForRemoteNotifications];
smithyy 2015年

26

iOS 8中,除了请求请求推送通知的方式不同之外,您还需要进行其他注册。

申请进入:

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)];
}

处理注册的设备:

// 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
}

非常有帮助。我不知道为什么我的通知失败了。
GoldenJoe 2014年

4
如何在iOS 8中获取令牌?
Yossi 2014年

@Yossi它存储在application:didRegisterForRemoteNotificationsWithDeviceToken:
Kyle Clegg

我的应用程序在此行崩溃[application registerForRemoteNotifications];
铁匠铺

13

请记住,模拟器不支持远程通知。因此,如果您在模拟器中运行应用程序,didRegisterForRemoteNotificationsWithDeviceToken则不会被调用。


@hochl:我更新了答案,以便更具体地回答问题。
埃里克

1
请注意,didFailToRegisterForRemoteNotificationsWithError也不会被调用。实际上,如果您在“设置”中(无论是在设备上还是在模拟器上)为应用程序禁用了推送通知,则不会调用任何通知。苹果似乎并不认为这是一个错误stackoverflow.com/questions/9199935/...
扎克莫里斯

12

确保调用您的代码(根据支持的通知类型进行更新)

[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];

且配置文件已启用APNS。启用APNS后,您可能需要重新下载配置文件。如果遇到麻烦并且遇到错误,那么也许您应该创建一个Entitlements.plist并根据构建的类型添加键“ aps-environment”,其值为“ development”或“ production”(通常,此键值对是包含在配置文件中,但有时Xcode会将它们弄乱了)。


注意:“并且供应配置文件启用了APNS。” 单击项目树顶部的>功能>推送通知应设置为ON。
trevorgrayson

6

如果在启用和配置Apple Push Notification服务之前使用了配置文件,则需要再次重新下载配置文件。

从Xcode Organizer和iPhone / iPad中删除配置文件。转到Settings -> General -> Profiles -> [Your provisioning] -> Remove

安装新的下载的配置文件。然后从XCode清理并运行项目。现在didRegisterForRemoteNotificationsWithDeviceToken应该调用。


它对我有用。只是选择了已为该应用程序注册了APN的认证和配置。

我从iphone(ios9)删除了所有配置文件,然后在收到设备令牌后。花了四个小时解决了这个问题(尽管我学到了很多东西)。谢谢
Shobhakar Tiwari 2015年

3

我犯了一个错误,却忽略了导致我出现在此处的实现细节。我试图让幻想,后来问推送通知用户在应用部署过程,所以我有我的registerForRemoteNotificationTypesdidRegisterForRemoteNotificationsWithDeviceToken并且didFailToRegisterForRemoteNotificationsWithError都在一个自定义的UIView。

FIX:didRegisterForRemoteNotificationsWithDeviceTokendidFailToRegisterForRemoteNotificationsWithError需要在UIApplicationDelegateYourAppDelegate.m)中被触发。

现在看来很明显,呵呵。


是的,方法必须在中AppDelegate。不敢相信我在这个简单的答案上浪费了我的过去几个小时
甚至Cheng

3

确保您的互联网连接已打开。由于互联网连接,我花了几个小时才能收到工作通知。


3

如果已将推送添加到现有的应用程序ID,请确保重新生成配置文件。如果您不这样做,则配置文件将不知道您是否启用了对应用程序ID的推送。


3

试试这个对我有用

第一步

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

在上面的方法中添加以下代码

 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];
     }

第二步

添加以下代码功能

 #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

您将在以下功能中获取设备令牌

 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 

有关详细答案,请参阅

希望这对某人有帮助。


2
-​(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)]; 
​​​​returnYES;
}


- (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]);
}

2

获取设备令牌的最低要求:

无需配置应用程序ID,配置或证书等,因此无需设置代码签名即可获取委托方法didRegisterForRemoteNotificationsWithDeviceToken

我刚刚使用默认设置在Xcode 7中为单个视图创建了一个新的iOS项目,并给出了一个随机的包ID(如com.mycompany.pushtest),但未在Apple开发人员门户中进行配置。

通过以下代码,我可以通过具有互联网访问权限的iPad在iPad上的didRegisterForRemoteNotificationsWithDeviceToken方法中获取设备令牌。我的设备已连接,我只是直接从xcode运行应用程序,然后在xcode的控制台中查看值。

- (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);
}

1

我对此有一点看法,最近我也面临这个问题。我已经按照文档完成了所有工作,但委托方法没有调用。最后我看到一个帖子说了网络问题,然后我更换了网络并且工作正常。因此也要注意网络,因为很少有网络可以阻止APNS。


1

在浪费了最烦人的3小时之后,请按照以下步骤解决此问题:

  1. 删除应用

  2. 重置设备

  3. 再次运行

它刚刚起作用


0

这发生在我身上,因为我重置并删除了手机上的所有数据(希望使用开发手机)。再次设置电话后,APN根本无法连接。

我尝试了各种方法,但是唯一解决问题的方法是将手机设置为可以在新SIM卡下与运营商一起使用。

该链接提供了有关可能发生的情况的更多提示:https : //developer.apple.com/library/ios/technotes/tn2265/_index.html

它说,APN尝试通过运营商/塔优先连接,而不是wifi。也许问题还出在路由器阻止wifi网络上的端口5223上,但我对此表示怀疑,因为它在全局重置发生之前的前一天工作正常。


0

对我来说,解决问题的方法是转到构建设置,然后在代码签名部分下,手动选择代码签名标识和设置配置文件。显然,自动设置未采用正确的设置,因此未正确授权该应用。


0

如果关闭应用程序的推送消息,

appdidRegisterForRemoteNotificationsWithDeviceToken将永远不会被调用


0

另外,不要忘记在Apple https://developer.apple.com/system-status/上检查系统状态。

我尝试了上面发布的所有解决方案,但最后的错误是因为APNS服务已关闭!第二天,所有工作又恢复了预期。

另外,您的回调方法中有一个错字:

- (void)application:(UIApplication *)appdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

正如Rupesh指出的那样,正确的方法名称是:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

这可能就是为什么您从未收到过令牌的原因!


实际上方法名不正确,应该是-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken参数之间有一个空格
Rupesh

谢谢,已更新答案以包含您的评论。可以肯定的是,这是解决OP问题的方法,但我们可能永远找不到!
布雷特

0

您需要从didFinishLaunchingWithOptions中调用registerForNotifications方法。

 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
            }
        }
    }
}

0

我遇到了一个不同的问题,其中我的推送通知回调被包括的第三方库(即Firebase)劫持了。这些库通过推送通知回调方法来获取回调。

希望这对某人有帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.