iOS7支持后台推送,但iOS8不支持,如何解决?

3

我有一个应用程序正在使用后台推送,当应用程序在运行iOS 7的设备上时一切正常,但如果在运行iOS 8的设备上,当应用程序在后台时推送不会被传递到应用程序。

以下是我的注册代码:

- (void) registerForRemoteNotification
{
    // Check for the presense of iOS8 notification API
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)])
    {
        NSLog(@"iOS8 detected");
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
    else
    {
        // iOS version < 8
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    }
}

我也尝试了这个变体:

- (void) registerForRemoteNotification
{
    // Check for the presense of iOS8 notification API
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)])
    {
        NSLog(@"iOS8 detected");
        [[UIApplication sharedApplication] registerForRemoteNotifications];
        UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
        UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
    }
    else
    {
        // iOS version < 8
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    }
}

这是推送负载的内容:

aps =     {
    "content-available" = 1;
    somePayload = "The payload";
    sound = "";
};

这就是正在发生的事情:
1) On iOS7 when app is in the foreground -> push is delivered to the app as expected
2) On iOS7 when app is in the background -> push is delivered to the app as expected
3) On iOS8 when app is in the foreground -> push is delivered to the app as expected
4) On iOS8 when app is in the background -> push is NOT delivered to the app
5) On iOS8 when app is in the foreground and running via Xcode -> push is delivered to the app as expected
6) On iOS8 when app is in the background and running via Xcode -> push is delivered to the app as expected

在每种情况下,didRegisterForRemoteNotificationsWithDeviceToken:方法都会被调用,而didFailToRegisterForRemoteNotificationsWithError:方法则不会被调用。 我不知道这是否相关,但是请看第4)和第6)之间的区别,我发现通过Xcode运行应用程序与否之间存在差异。 我的问题是,为什么案例4)中推送消息不能传递给应用程序?它在iOS7上可行,我认为在iOS8上运行时注册远程通知的代码是正确的(并且确实,如果通过Xcode执行应用程序,则它可以工作),那么为什么在独立于iOS 8的Xcode上运行应用程序时它不起作用? **更新。在发布此赏金后,我浏览了苹果开发者论坛。似乎有很多人遇到类似的问题。对于一些人来说,必须启用wifi才能获得背景推送,但对我来说,那行不通-我必须充电手机才能收到它们。如果不充电(即使电池已满),则它们将无法传递。苹果表示,他们在iOS 8中关于后台推送所做的事情是故意的而不是bug,但我的结论是他们要么搞砸了,要么做了某些非常不合逻辑的事情,以至于被认为是一个搞砸。因此,我希望他们会意识到他们所做的是一堆烂摊子,并在将来的版本中进行更改。 如果您想获得背景,请前往相关开发论坛并阅读一些相关主题。

是的,它可以。你的应用程序呢? - Gruntcakes
你尝试过对推送消息的内容进行实验吗?最初,当后台推送首次发布时,我发现唯一能够使其在后台传递的方法是添加一个“声音”部分到推送中。最近我看到了这篇文章http://docs.urbanairship.com/reference/troubleshooting/ios-background-push.html。所以苹果对于本应该是静默推送的推送内容有着绝对荒谬、可笑和愚蠢的要求。虽然这种方法已经不再适用于我,但也许对你有用,声音名称可以为空。 - Gruntcakes
我已经实现了这个,只是没有在问题中发布它,我调整了问题以明确这一点。 - Gruntcakes
我没有解决方案,但至少可以告诉你不是在想象事情:D 我也遇到了同样的问题!有时候iOS8会传递推送,但大多数情况下不会——将其连接到Xcode上,它就可以100%工作——这完全取决于使用的设备。 - Daij-Djan
@Daij-Djan。它在连接Xcode时能够工作的原因是因为它从USB电缆中获取了绘图功率。我发现,在iOS8中,如果某些设备在推送到达时正在充电,它们只会在后台接收到推送通知。尝试使用电源线,插上它就可以工作,拔掉它就不行了! - Gruntcakes
显示剩余5条评论
4个回答

0
我找到了在iOS8上接收远程通知所需的方法。苹果已经更改了需要调用的方法。首先,他们已经弃用了方法registerForRemoteNotificationTypes,现在你应该使用registerForRemoteNotifications。但这并不是所有的变化——你仍然需要指定允许通知的类型。
以下是文档中的内容(https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/#//apple_ref/occ/instm/UIApplication/registerForRemoteNotifications):
如果您希望您的应用程序的推送通知显示警报、播放声音或执行其他面向用户的操作,则必须调用registerUserNotificationSettings:方法请求要使用的通知类型。如果您不调用该方法,则系统会将所有推送通知静默地传递给您的应用程序。由于注册过程考虑了用户的首选通知设置,因此请求访问面向用户的通知类型也不能保证它们将被授予。要查找可用的通知设置,请使用currentUserNotificationSettings方法。
尝试调用currentUserNotificationSettings,你会发现没有任何类型的通知被允许,所以不奇怪它们没有被接收。

试试这个:

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

它完成了任务!


很遗憾,这对我不起作用,我的代码已经包含了你发布的代码。苹果文档中说:“如果您不调用该方法,则系统会将所有推送通知静默地传递给您的应用程序。”但是你似乎通过做与文档相反的事情使其工作了! - Gruntcakes

0

以下代码在我的iOS7和iOS8应用中运行正常:

if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
    // iOS 8 Notifications
    [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];

    [application registerForRemoteNotifications];
}
else
{
    // iOS < 8 Notifications
    [application registerForRemoteNotificationTypes:
     (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}

希望这能帮到你!


谢谢,那正是我已经拥有的。我发现苹果在iOS8中故意对后台推送做了一些事情,在某些情况下不会传递推送,但他们没有公布详细信息。我有5个手机,其中3个始终可以使用,其中一个间歇性地使用,另一个几乎从来没有使用。所以这不是一个编码问题,苹果不会披露其他因素。 - Gruntcakes

0

试试这个,我发现苹果的文档有问题,我使用Parse,它有一个更好的帮助部分。

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    [Parse setApplicationId:@"asdasd" clientKey:@"asdasd"];
    UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
                                                    UIUserNotificationTypeBadge |
                                                    UIUserNotificationTypeSound);
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes
                                                                             categories:nil];
    [application registerUserNotificationSettings:settings];
    [application registerForRemoteNotifications];
} else {
    // Register for Push Notifications before iOS 8
    [Parse setApplicationId:@"asdasd" clientKey:@"asdasd"];
    [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
                                                     UIRemoteNotificationTypeAlert |
                                                     UIRemoteNotificationTypeSound)];
}

谢谢,但这与我在问题中发布的代码没有区别,其中写着“我也尝试了这个变体:”,除了UIApplication方法的调用顺序不同之外。您是否意味着顺序非常重要? - Gruntcakes
你应该试一下,我记得在使用这段代码之前我也遇到了问题,但是尝试后问题解决了。我会回头查看我的代码,看看我还做了什么来解决这个问题。 - Anthony Taylor

0

我认为你需要设置推送通知授权密钥。

aps-environment,iOS中接收推送通知

请参考此链接推送通知授权密钥


如果那是问题的话,应用程序将无法接收到任何推送。我的问题不是应用程序总体上不能接收推送,而是它无法接收后台推送。 - Gruntcakes
请确认在设置中开启了后台通知。 - Saurabh Shukla
如果你指的是背景模式,那么"后台获取"和"远程通知"已经启用了。 - Gruntcakes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接