【问题标题】:Azure Notification Hub receiving unexplained 'APNS Channel Expired' errorsAzure 通知中心收到无法解释的“APNS 通道已过期”错误
【发布时间】:2016-09-12 12:57:28
【问题描述】:

我在使用 Azure 通知中心时遇到问题。我的 iOS 设备最初已正确注册并接收推送。然而,偶尔一两个设备会莫名其妙地停止接收推送通知。调试此问题似乎是由于 APNS 使设备注册的通道过期:

设备注册和推送停止之间的时间不超过 10 分钟。我可以 100% 保证此设备没有通过通知中心手动取消注册。我正常使用该应用程序,并收到了一些推送,然后它停止接收任何推送。

作为参考,应用通过 WebAPI 后端注册到 Azure 通知中心。作为参考,这里是每当用户登录或应用程序返回前台时注册设备以进行推送的代码。如果我在这个逻辑中做错了什么,请告诉我:

private async Task<string> RegisterDevice(string token)
{
    string newRegistrationId = null;

    if (!string.IsNullOrWhiteSpace(token))
    {
        var registrations = await _notificationHub.GetRegistrationsByChannelAsync(token, 100);
        foreach (var registration in registrations)
        {
            if (newRegistrationId == null)
            {
                newRegistrationId = registration.RegistrationId;
            }
            else
            {
                await _notificationHub.DeleteRegistrationAsync(registration);
            }
        }
    }

    return newRegistrationId ?? await _notificationHub.CreateRegistrationIdAsync();
}

public async Task<string> CreateOrUpdateRegistration(string userId, string token, string platform, string registrationId = null)
{
    var userDetail = await _userDetailRepo.GetAsync(userId);
    if (userDetail == null)
        throw new ApiException(HttpStatusCode.BadRequest, "User details could not be found");

    if (string.IsNullOrWhiteSpace(registrationId))
        registrationId = await RegisterDevice(token);

    RegistrationDescription registration;
    switch (platform)
    {
        case Settings.Platforms.Android:
            var gcmTemplate = "[REDACTED]"
            registration = new GcmTemplateRegistrationDescription(token, gcmTemplate);
            break;
        case Settings.Platforms.Ios:
            var apnsTemplate = "[REDACTED]";
            registration = new AppleTemplateRegistrationDescription(token, apnsTemplate);
            break;
        default:
            throw new ApiException(HttpStatusCode.BadRequest, "Platform not recognised");
    }

    registration.RegistrationId = registrationId;
    SetDeviceRegistrationTags(registration, userId, userDetail.TwingleAcceptedNotificationEnabled, userDetail.TwingleDeclinedNotificationEnabled, userDetail.MessageReceivedNotificationEnabled, userDetail.ConnectionDeletedNotificationEnabled);

    var registrationStale = false;
    try
    {
        await _notificationHub.CreateOrUpdateRegistrationAsync(registration);
    }
    catch (MessagingException e)
    {
        var webEx = e.InnerException as WebException;
        if (webEx != null && webEx.Status == WebExceptionStatus.ProtocolError)
        {
            var response = (HttpWebResponse)webEx.Response;
            if (response.StatusCode == HttpStatusCode.Gone)
            {
                registrationStale = true;
            }
        }
    }

    // if the registration is stale and/or removed then it needs to be re-created with a new registrationId
    if (registrationStale)
        registrationId = await CreateOrUpdateRegistration(userId, token, platform);

    return registrationId;
}

如果没有对设备(最初成功的)注册进行任何更改,谁能告诉我是什么导致设备在 APNS 中过期?

【问题讨论】:

标签: c# azure notifications apple-push-notifications azure-notificationhub


【解决方案1】:

设备必须定期向 APNS 重新注册,以确保它们拥有有效的令牌。如果他们不这样做,那么他们将不会收到推送(一旦失败回调触发其删除,您将看到设备注册在通知中心消失)。这是设计使然:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html

【讨论】:

  • 感谢您的回答。据我了解,设备令牌的使用寿命通常为 90 天左右。我承认不能保证,但是这个设备令牌显然在几分钟内就过期了,这让我相信这不仅仅是一个令牌有效性问题。
【解决方案2】:

问题是因为默认情况下AppleTemplateRegistrationDescriptions 指定0 作为超时值。这意味着一旦 APNS 无法向设备传递一条消息,它就会立即被删除;这是没有退路的。为了解决这个问题,我指定了类的Expiry 属性,以便在发送通知和设备确认通知之间存在延迟。这意味着此后没有任何设备被 APNS 不当取消注册。

AppleTemplateRegistrationDescription registration = new AppleTemplateRegistrationDescription(DeviceToken) 
{ 
    BodyTemplate = new CDataMember(ApnsBodyTemplate)
};
registration.Expiry = DateTime.UtcNow.AddHours(2);
await client.CreateRegistrationAsync(registration);

【讨论】:

  • 这不会将有效期设置为注册创建后 2 小时吗?不是通知发送后 2 小时?还是DateTime.UtcNow.AddHours(2) 直到发送时间才被评估?
  • 是否有关于此的任何文档,因为您的解释没有任何意义。您将 Expiry 设置为未来 2 小时的特定时间,而不是“2 小时”的间隔。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 2016-01-11
  • 2015-11-26
相关资源
最近更新 更多