远程通知 iOS 8

Posted

技术标签:

【中文标题】远程通知 iOS 8【英文标题】:Remote Notification iOS 8 【发布时间】:2014-06-14 04:40:35 【问题描述】:

如何在 ios 8 中获取用于远程通知的设备令牌? 我在 iOS AppDelegate 中使用了 didRegisterForRemoteNotificationsWithDeviceToken 方法,它返回了设备令牌。但在 iOS 8 中,它不会。

【问题讨论】:

这真的有效..! ***.com/questions/4086599/… 【参考方案1】:

阅读 UIApplication.h 中的代码。

你会知道怎么做的。

第一:

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

添加这样的代码

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) 
#ifdef __IPHONE_8_0
  UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert 
      | UIUserNotificationTypeBadge 
      | UIUserNotificationTypeSound) categories:nil];
  [application registerUserNotificationSettings:settings];
#endif
 else 
  UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
  [application registerForRemoteNotificationTypes:myTypes];

如果你没有同时使用 Xcode 5 和 Xcode 6,试试这个代码

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) 
  UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
      |UIRemoteNotificationTypeSound
      |UIRemoteNotificationTypeAlert) categories:nil];
  [application registerUserNotificationSettings:settings];
 else 
  UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
  [application registerForRemoteNotificationTypes:myTypes];

(感谢@zeiteisen @dmur 的提醒)


第二:

添加此功能

#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

你可以得到 deviceToken in

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

如果还是不行,使用这个函数并 NSLog error

-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error

【讨论】:

这个。够愚蠢的是,Apple 未能更新他们的 UIUserNotificationSettingsUIApplication 文档,谈论 iOS 8 的要求。相反,它隐藏在他们的 API 差异中。 这将在低于 iOS 8 的 iOS 版本上崩溃。#ifdef 是一个编译器函数,并在编译时进行评估。您仍然需要运行时检查! 使用此宏检查 iOS 8:#define isAtLeastiOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) 。 __IPHONE_8_0 不是一个好的检查,因为您希望此代码也继续在未来的版本上运行。 也就是说,在这种情况下,#ifdef 是不必要的,除非您的团队同时使用 Xcode 5 和 Xcode 6。相反,您应该进行 if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) 检查,就像 zeiteisen 在他的回答中所做的那样。 对已弃用的枚举 UIRemoteNotificationType 进行少量更正:NS_ENUM_DEPRECATED_IOS(3_0, 8_0, "使用 UIUserNotificationType 进行用户通知,而 registerForRemoteNotifications 用于接收远程通知。");因此,对于 iOS 8 及更高版本,您必须使用 UIUserNotificationTypeBadge、UIUserNotificationTypeSound、UIUserNotificationTypeAlert。 (UIUserNotificationType 用于新版本,UIRemoteNotificationType - 用于旧版本)。 中定义的枚举【参考方案2】:

注册 iOS 8 并继续支持旧版本的方式

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

并在应用程序委托中添加

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings 
    [application registerForRemoteNotifications];

iOS8 可以在不请求许可的情况下接收静默通知。称呼 - (void)registerForRemoteNotifications。在此之后application:didRegisterForRemoteNotificationsWithDeviceToken: 将被调用

注意:仅当应用程序已使用以下功能成功注册用户通知或启用后台应用程序刷新时,才会调用带有令牌的回调。

如果启用了任何通知类型,请检查您应用的设置。如果没有,您将不会获得设备令牌。

您现在可以使用

获得静默通知
aps 
content-available: 1

在通知负载中

但出现的通知仍需要许可。打电话

UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[application registerUserNotificationSettings:notificationSettings];

此代码应请求许可。

您现在应该准备好接收推送通知了

【讨论】:

感谢OS8 can receive silent notifications without asking for permission 位。这让我发疯了,这是我唯一发现有帮助的地方! @zeiteisen,在您的第一个if 语句中,您应该使用UIUserNotificationTypeSound 而不是UIRemoteNotificationTypeSound,因为UIRemoteNotificationType 在iOS 8 中已被弃用。 有人能解释一下为什么只有在后台应用刷新启用时才会调用带有令牌的回调吗?我虽然应该在启用推送通知权限时调用它......【参考方案3】:

在我的例子中,我已经进行了必要的更新来请求 iOS 7 和 iOS 8 的推送通知访问权限,但是当 iOS 8 用户授予访问权限时,我还没有实现新的回调。我需要将此方法添加到我的应用委托中。

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings 
    [application registerForRemoteNotifications];

【讨论】:

【参考方案4】:

如果您使用 Xamarin.iOS 构建您的移动应用程序,您可以使用此代码的 sn-p 请求推送通知注册

if (UIDevice.CurrentDevice.CheckSystemVersion(8,0))

    UIUserNotificationType userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
    UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(userNotificationTypes, null);
    UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);

else

    UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
    UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
 

您还需要重写 DidRegisterUserNotificationSettings 方法以获取从 APNS 服务器返回的设备令牌:

public override void DidRegisterUserNotificationSettings(UIApplication application, UIUserNotificationSettings notificationSettings)

    application.RegisterForRemoteNotifications();

【讨论】:

【参考方案5】:

麻道(https://***.com/a/24488562/859742)的回答是对的但是......

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge

应该更“正确”

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];

这些标志具有相同的位掩码值,这就是为什么两者都可以工作,但UIUserNotificationSettings 需要UIUserNotificationType 而不是UIRemoteNotificationType

除此之外我会打电话给

[application registerUserNotificationSettings:settings];

AppDelegate 方法中(取决于授予的权限),

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings

【讨论】:

有什么区别? UIUserNotificationTypeBadge 和 UIRemoteNotificationTypeBadge 是相同的位掩码,但含义不同 =)【参考方案6】:

我认为保持向后兼容性的更好方法是我们可以采用这种方法,它适用于我的情况,希望对你有用。也很容易理解。

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    
    else
    
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
    

【讨论】:

【参考方案7】:
UIUserNotificationType types = UIUserNotificationTypeBadge |
    UIUserNotificationTypeSound | UIUserNotificationTypeAlert;

    UIUserNotificationSettings *mySettings =
    [UIUserNotificationSettings settingsForTypes:types categories:nil];

    [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];

    [application registerForRemoteNotifications];

【讨论】:

以上是关于远程通知 iOS 8的主要内容,如果未能解决你的问题,请参考以下文章

IOS 远程通知在 IOS 8 的后台不起作用

IOS 8 注册远程通知只成功了一半

iOS8 - 请求远程推送通知

iOS推送通知和远程通知的区别?

iOS开发--本地通知与远程通知

iOS(本地通知与远程通知)