Azure 通知中心收到无法解释的 'APNS Channel Expired' 错误
Azure Notification Hub receiving unexplained 'APNS Channel Expired' errors
我在使用 Azure 通知中心时遇到问题。我的 iOS 设备最初已正确注册并接收推送。然而,偶尔会有一两个设备莫名其妙地停止接收推送通知。调试此问题似乎是由于 APNS 使设备注册的通道过期:
设备注册和推送停止之间经过的时间不超过 10 分钟。我可以 100% 保证此设备不是通过通知中心手动注销的。我正常使用该应用程序,收到一些推送,然后它停止接收任何推送。
作为参考,应用程序通过 WebAPI 后端注册到 Azure 通知中心。作为参考,这里是注册设备以在用户登录或应用程序 returns 到前台时进行推送的代码。如果我在此逻辑中做错了什么,请告诉我:
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 过期?
设备必须定期向 APNS 重新注册,以确保它们拥有有效的令牌。如果他们不这样做,那么他们将不会收到推送(一旦失败回调触发其删除,您将看到设备注册在通知中心消失)。这是设计使然:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html
问题是因为默认情况下 AppleTemplateRegistrationDescriptions
将 0
指定为超时值。这意味着一旦 APNS 未能向设备发送一条消息,它就会立即被删除;这是没有余地的。为了解决这个问题,我指定了 class 的 Expiry
属性,以便在发送通知和设备确认通知之间存在延迟。这意味着此后没有任何设备被 APNS 不当取消注册。
AppleTemplateRegistrationDescription registration = new AppleTemplateRegistrationDescription(DeviceToken)
{
BodyTemplate = new CDataMember(ApnsBodyTemplate)
};
registration.Expiry = DateTime.UtcNow.AddHours(2);
await client.CreateRegistrationAsync(registration);
我在使用 Azure 通知中心时遇到问题。我的 iOS 设备最初已正确注册并接收推送。然而,偶尔会有一两个设备莫名其妙地停止接收推送通知。调试此问题似乎是由于 APNS 使设备注册的通道过期:
设备注册和推送停止之间经过的时间不超过 10 分钟。我可以 100% 保证此设备不是通过通知中心手动注销的。我正常使用该应用程序,收到一些推送,然后它停止接收任何推送。
作为参考,应用程序通过 WebAPI 后端注册到 Azure 通知中心。作为参考,这里是注册设备以在用户登录或应用程序 returns 到前台时进行推送的代码。如果我在此逻辑中做错了什么,请告诉我:
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 过期?
设备必须定期向 APNS 重新注册,以确保它们拥有有效的令牌。如果他们不这样做,那么他们将不会收到推送(一旦失败回调触发其删除,您将看到设备注册在通知中心消失)。这是设计使然:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html
问题是因为默认情况下 AppleTemplateRegistrationDescriptions
将 0
指定为超时值。这意味着一旦 APNS 未能向设备发送一条消息,它就会立即被删除;这是没有余地的。为了解决这个问题,我指定了 class 的 Expiry
属性,以便在发送通知和设备确认通知之间存在延迟。这意味着此后没有任何设备被 APNS 不当取消注册。
AppleTemplateRegistrationDescription registration = new AppleTemplateRegistrationDescription(DeviceToken)
{
BodyTemplate = new CDataMember(ApnsBodyTemplate)
};
registration.Expiry = DateTime.UtcNow.AddHours(2);
await client.CreateRegistrationAsync(registration);