无法在 iOS 上在 Azure NotificationHub 中注册设备,无回调
Cannot register device in Azure NotificationHub on iOS, no callbacks
我正在尝试通过 Azure NotificationHub 设置推送通知(使用 these guides)。 Android 进行得很好,但是 iOS...
无论我做什么,我都没有收到来自 RegisterNative / RegisterTemplate SBNotificationHub[ 方法的任何回调=71=],并且没有注册出现在集线器中。
我的代码(非常简单):
public static void SubscribeToAzure(NSData deviceToken, string[] subscriptionTags = null, bool bUnsubscribe = false)
{
try
{
var Hub = new SBNotificationHub(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);
Logger.WriteLine($"Unsubscribing from AzureHub [{deviceToken}]....");
Hub.UnregisterAll(deviceToken, (error) =>
{
if (error != null)
{
Logger.WriteLine($"SubscribeToAzure: Unable to call unregister, {error}");
return;
}
RuntimeInfo.AzureSubscribed = false;
if (bUnsubscribe)
return;
Logger.WriteLine($"Register native in AzureHub [{deviceToken}]....");
var tags = subscriptionTags != null ? new NSSet(subscriptionTags.ToArray()) : new NSSet("default");
Hub.RegisterNative(deviceToken, tags, errorCallback =>
{
// !!! never got here !!!
if (errorCallback != null)
Logger.WriteLine($"RegisterNative error: {errorCallback}");
else
Logger.WriteLine($"RegisterNative OK");
});
Logger.WriteLine("Register template in AzureHub....");
var templateExpiration = DateTime.Now.AddDays(120).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));
Hub.RegisterTemplate(deviceToken, "defaultTemplate", AppConstants.APNTemplateBody, templateExpiration, tags, errorCallback =>
{
// !!! never got here !!!
if (errorCallback != null)
{
Logger.WriteLine($"RegisterTemplateAsync error: {errorCallback}");
}
else
{
Logger.WriteLine("Subscribed to Azure successfully.");
RuntimeInfo.AzureSubscribed = true;
}
});
Logger.WriteLine("Registrations passed....");
});
}
catch(Exception e)
{
Logger.WriteLine($"SubscribeToAzure: Whole deal failed, {e.Message}");
}
}
始终获取此日志消息(未调用回调):
[22.10.2020 18:13:43]: Unsubscribing from AzureHub [{length = 32, bytes = 0x342c9bc5 d75ffb0b d68078d0 47e94320 ... e08989c9 66a13a37}]....
[22.10.2020 18:13:44]: Register native in AzureHub [{length = 32, bytes = 0x342c9bc5 d75ffb0b d68078d0 47e94320 ... e08989c9 66a13a37 }]....
[22.10.2020 18:13:44]: Register template in AzureHub....
[22.10.2020 18:13:44]: Registrations passed....
并且在中心没有 iOS 注册。任何地方都没有错误。
我尝试了证书和令牌身份验证模式,但没有成功。
我对所有证书、状态、密钥、ID 等进行了双重、三重和四重检查
使用 iOS SDK 14.0,iPhone X iOS 14.0.1,Xamarin Forms 4.8.0.1560,Xamarin.Azure.NotificationHubs.iOS 3.1.0.
=======
我被建议从 SBNotificationHub 移动到 MSNotificationHub.
得到完全相同的结果:无论是否出错都没有响应。并且中心没有注册。
public static void SubscribeToAzure(NSData deviceToken, string[] subscriptionTags = null, bool bUnsubscribe = false)
{
RuntimeInfo.AzureSubscribed = false;
if (bUnsubscribe)
{
// ??
}
else
{
try
{
Logger.WriteLine("Subscribing to Azure Hub....");
MSNotificationHub.Start(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);
MSNotificationHub.SetDelegate(new NotificationDelegate());
MSNotificationHub.SetLifecycleDelegate(new InstallationLifecycleDelegate());
MSNotificationHub.ClearTags();
if (subscriptionTags != null)
foreach (string tag in subscriptionTags)
{
MSNotificationHub.AddTag(tag);
}
var template = new MSInstallationTemplate();
template.Body = AppConstants.APNTemplateBody;
if (subscriptionTags != null)
foreach (string tag in subscriptionTags)
{
template.AddTag(tag);
}
MSNotificationHub.SetTemplate(template, key: "defaultTemplate");
Logger.WriteLine($"SubscribeToAzure: done subscribing routine");
}
catch (Exception e)
{
Logger.WriteLine($"SubscribeToAzure: Whole deal failed, {e.Message}");
}
}
}
public class InstallationLifecycleDelegate : MSInstallationLifecycleDelegate
{
public override void DidFailToSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation, NSError error)
{
Logger.WriteLine($"Subscribing to Azure failed with exception: {error.LocalizedDescription}");
}
public override void DidSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation)
{
RuntimeInfo.AzureSubscribed = true;
Logger.WriteLine($"Subscribed to Azure successfully with Installation ID: {installation.InstallationId}");
}
}
public class NotificationDelegate : MSNotificationHubDelegate
{
public override void DidReceivePushNotification(MSNotificationHub notificationHub, MSNotificationHubMessage message)
{
NSDictionary userInfo = message.UserInfo;
if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Background)
{
Logger.WriteLine($"Message received in the background with title {message.Title} and body {message.Body}");
ProcessNotification(userInfo, true);
}
else
{
Logger.WriteLine($"Message received in the foreground with title {message.Title} and body {message.Body}");
ProcessNotification(userInfo, true);
}
}
}
日志仅显示所有代码部分均已通过:
[23.10.2020 18:34:33]: Subscribing to Azure Hub....
[23.10.2020 18:34:33]: SubscribeToAzure: done subscribing routine
还尝试自动 swizzle disabling 记录每一步,结果相同。
更新
经过几天的努力,我发现如果执行从主线程滑落,iOS 会阻止请求并且 Xamarin.Azure.NotificationHubs.iOS 不会对此发表任何意见。 运行 它在主线程中强行推动了它。
可悲的是,它仍然不起作用。
使用 SBNotificationHub 的第一种方法无法注册模板。上面的代码执行 RegisterNative 并且我在通知中心获得本机条目。但是 RegisterTemplate return 'Bad Request'.
[28.10.2020 15:26:10]: RegisterTemplateAsync error: URLRequest failed for <NSMutableURLRequest: 0x282bac6e0> { URL: https://webtutormobile.servicebus.windows.net//Registrations/8635975298502840400-8846379580641729326-3?api-version=2013-04 } with status code: bad request
使用 MSNotificatoinHub 的第二种方法无法从 MSNotificationHubMessage.UserInfo getter 获取 NSDictionary,并在此行中断:
public override void DidReceivePushNotification(MSNotificationHub notificationHub, MSNotificationHubMessage message)
{
var userInfo = message.UserInfo; // MSNotificationHubMessage.UserInfo has type NSDictionary<NSString, NSString>
有例外:
[28.10.2020 16:22:58]: Received azure notification error: Unable to cast object of type 'Foundation.NSDictionary' to type 'Foundation.NSDictionary`2[[Foundation.NSString, Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065],[Foundation.NSString, Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]]'
终于有了结论。如果有人感兴趣:
集线器注册必须在主线程中调用。否则 Xamarin.Azure.NotificationHubs.iOS 甚至不会给出出错的提示。
当实际类型为 NSDictionary 时,MSNotificationHub 的新方法在获取 UserInfo 并将其转换为 NSDictionary 时存在错误。 GitHub已经发布了一段时间了,但是还没有得到团队的任何回应,所以如果你通过推送通知传递消息以外的任何数据,抱歉,不行。
使用 SBNotificationHub 的旧方法具有严格的模板格式。首先,您应该使用 RegisterTemplate 方法来排除错误,而不是使用回调方法,因为前者是唯一出于某种原因给出错误描述的方法。
其次,你不能使用 {$(field)} 构造子定义模板,你需要指定属性的插入格式,如: "alert":"$( messageParam)","badge":"#(badge)","content-available":"#(contentAvailable)" 等。您还需要修改调度程序,以便它始终发送未加引号的参数。
IOS 实现非常原始,half-done 被遗忘了。我知道与 Apple 交互是完全地狱般的痛苦,但仍然...
希望它能为人们节省很多很多时间。
除了 Serg 的回答,您还需要使用 MainThread.BeginInvokeOnMainThread
进行 MSNotificationHub
注册。
不要使用Device.BeginInvokeOnMainThread
,它不起作用。
除了我的回答。我现在有 azure pushes,但我的解决方案混合了新旧方法。他们每个人都不能单独工作。
对于android:
当我使用新方法时,会在 azure 通知中心进行注册,但不会收到通知。
当我使用旧方法时,没有来自 azure 通知中心的通知。
- 必须在
RunOnUiThread
中为新方法调用集线器注册:
NotificationHub.Start(MainActivity.Instance.Application, NotificationHubName, ConnectionString);
NotificationHub.SetListener(new AzureListener());
-
AzureListener
的实现 class 是存根:
/// <summary>
/// It does nothing, but registrasion doesn't work without it.
/// </summary>
public class AzureListener : Java.Lang.Object, INotificationListener
{
/// <summary>
/// Stub
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
public void OnPushNotificationReceived(Context context, INotificationMessage message)
{}
}
- 对于旧方法,必须在非主线程中调用集线器注册:
await Task.Run(async () =>
{
await Task.Delay(1);
this.notificationHub = new WindowsAzure.Messaging.NotificationHub(NotificationHubName,ConnectionString, MainActivity);
notificationHub.UnregisterAll(PnsHandle);
notificationHub.Register(PnsHandle, new string[] { });
}
- 接收推送需要实现
FirebaseMessagingService
class。
对于iOS:
当我使用新方法时,天蓝色通知中心没有注册。
当我使用旧方法时,在 azure hub 进行了注册,但没有来自 azure 通知中心的通知。
- 必须在
MainThread
中为新方法调用集线器注册:
MSNotificationHub.Start(ConnectionString, NotificationHubName);
MSNotificationHub.SetDelegate(new AzureNotificationHubListener());
- 对于旧方法,必须在 xamarin 主线程中调用集线器注册:
await Device.InvokeOnMainThreadAsync(async () =>
{
Hub = new SBNotificationHub(connectionParameters.ConnectionString, connectionParameters.NotificationHubName);
await Hub.RegisterNativeAsync(AppDelegate.PnsHandle, null);
});
接收推送需要实现AzureNotificationHubListener
class
需要在Info.plist
中添加key:
NSAppTransportSecurity
<字典>
NSAllowsArbitraryLoads
我正在尝试通过 Azure NotificationHub 设置推送通知(使用 these guides)。 Android 进行得很好,但是 iOS...
无论我做什么,我都没有收到来自 RegisterNative / RegisterTemplate SBNotificationHub[ 方法的任何回调=71=],并且没有注册出现在集线器中。
我的代码(非常简单):
public static void SubscribeToAzure(NSData deviceToken, string[] subscriptionTags = null, bool bUnsubscribe = false)
{
try
{
var Hub = new SBNotificationHub(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);
Logger.WriteLine($"Unsubscribing from AzureHub [{deviceToken}]....");
Hub.UnregisterAll(deviceToken, (error) =>
{
if (error != null)
{
Logger.WriteLine($"SubscribeToAzure: Unable to call unregister, {error}");
return;
}
RuntimeInfo.AzureSubscribed = false;
if (bUnsubscribe)
return;
Logger.WriteLine($"Register native in AzureHub [{deviceToken}]....");
var tags = subscriptionTags != null ? new NSSet(subscriptionTags.ToArray()) : new NSSet("default");
Hub.RegisterNative(deviceToken, tags, errorCallback =>
{
// !!! never got here !!!
if (errorCallback != null)
Logger.WriteLine($"RegisterNative error: {errorCallback}");
else
Logger.WriteLine($"RegisterNative OK");
});
Logger.WriteLine("Register template in AzureHub....");
var templateExpiration = DateTime.Now.AddDays(120).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));
Hub.RegisterTemplate(deviceToken, "defaultTemplate", AppConstants.APNTemplateBody, templateExpiration, tags, errorCallback =>
{
// !!! never got here !!!
if (errorCallback != null)
{
Logger.WriteLine($"RegisterTemplateAsync error: {errorCallback}");
}
else
{
Logger.WriteLine("Subscribed to Azure successfully.");
RuntimeInfo.AzureSubscribed = true;
}
});
Logger.WriteLine("Registrations passed....");
});
}
catch(Exception e)
{
Logger.WriteLine($"SubscribeToAzure: Whole deal failed, {e.Message}");
}
}
始终获取此日志消息(未调用回调):
[22.10.2020 18:13:43]: Unsubscribing from AzureHub [{length = 32, bytes = 0x342c9bc5 d75ffb0b d68078d0 47e94320 ... e08989c9 66a13a37}]....
[22.10.2020 18:13:44]: Register native in AzureHub [{length = 32, bytes = 0x342c9bc5 d75ffb0b d68078d0 47e94320 ... e08989c9 66a13a37 }]....
[22.10.2020 18:13:44]: Register template in AzureHub....
[22.10.2020 18:13:44]: Registrations passed....
并且在中心没有 iOS 注册。任何地方都没有错误。
我尝试了证书和令牌身份验证模式,但没有成功。
我对所有证书、状态、密钥、ID 等进行了双重、三重和四重检查
使用 iOS SDK 14.0,iPhone X iOS 14.0.1,Xamarin Forms 4.8.0.1560,Xamarin.Azure.NotificationHubs.iOS 3.1.0.
=======
我被建议从 SBNotificationHub 移动到 MSNotificationHub.
得到完全相同的结果:无论是否出错都没有响应。并且中心没有注册。
public static void SubscribeToAzure(NSData deviceToken, string[] subscriptionTags = null, bool bUnsubscribe = false)
{
RuntimeInfo.AzureSubscribed = false;
if (bUnsubscribe)
{
// ??
}
else
{
try
{
Logger.WriteLine("Subscribing to Azure Hub....");
MSNotificationHub.Start(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);
MSNotificationHub.SetDelegate(new NotificationDelegate());
MSNotificationHub.SetLifecycleDelegate(new InstallationLifecycleDelegate());
MSNotificationHub.ClearTags();
if (subscriptionTags != null)
foreach (string tag in subscriptionTags)
{
MSNotificationHub.AddTag(tag);
}
var template = new MSInstallationTemplate();
template.Body = AppConstants.APNTemplateBody;
if (subscriptionTags != null)
foreach (string tag in subscriptionTags)
{
template.AddTag(tag);
}
MSNotificationHub.SetTemplate(template, key: "defaultTemplate");
Logger.WriteLine($"SubscribeToAzure: done subscribing routine");
}
catch (Exception e)
{
Logger.WriteLine($"SubscribeToAzure: Whole deal failed, {e.Message}");
}
}
}
public class InstallationLifecycleDelegate : MSInstallationLifecycleDelegate
{
public override void DidFailToSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation, NSError error)
{
Logger.WriteLine($"Subscribing to Azure failed with exception: {error.LocalizedDescription}");
}
public override void DidSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation)
{
RuntimeInfo.AzureSubscribed = true;
Logger.WriteLine($"Subscribed to Azure successfully with Installation ID: {installation.InstallationId}");
}
}
public class NotificationDelegate : MSNotificationHubDelegate
{
public override void DidReceivePushNotification(MSNotificationHub notificationHub, MSNotificationHubMessage message)
{
NSDictionary userInfo = message.UserInfo;
if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Background)
{
Logger.WriteLine($"Message received in the background with title {message.Title} and body {message.Body}");
ProcessNotification(userInfo, true);
}
else
{
Logger.WriteLine($"Message received in the foreground with title {message.Title} and body {message.Body}");
ProcessNotification(userInfo, true);
}
}
}
日志仅显示所有代码部分均已通过:
[23.10.2020 18:34:33]: Subscribing to Azure Hub....
[23.10.2020 18:34:33]: SubscribeToAzure: done subscribing routine
还尝试自动 swizzle disabling 记录每一步,结果相同。
更新
经过几天的努力,我发现如果执行从主线程滑落,iOS 会阻止请求并且 Xamarin.Azure.NotificationHubs.iOS 不会对此发表任何意见。 运行 它在主线程中强行推动了它。 可悲的是,它仍然不起作用。
使用 SBNotificationHub 的第一种方法无法注册模板。上面的代码执行 RegisterNative 并且我在通知中心获得本机条目。但是 RegisterTemplate return 'Bad Request'.
[28.10.2020 15:26:10]: RegisterTemplateAsync error: URLRequest failed for <NSMutableURLRequest: 0x282bac6e0> { URL: https://webtutormobile.servicebus.windows.net//Registrations/8635975298502840400-8846379580641729326-3?api-version=2013-04 } with status code: bad request
使用 MSNotificatoinHub 的第二种方法无法从 MSNotificationHubMessage.UserInfo getter 获取 NSDictionary,并在此行中断:
public override void DidReceivePushNotification(MSNotificationHub notificationHub, MSNotificationHubMessage message)
{
var userInfo = message.UserInfo; // MSNotificationHubMessage.UserInfo has type NSDictionary<NSString, NSString>
有例外:
[28.10.2020 16:22:58]: Received azure notification error: Unable to cast object of type 'Foundation.NSDictionary' to type 'Foundation.NSDictionary`2[[Foundation.NSString, Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065],[Foundation.NSString, Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]]'
终于有了结论。如果有人感兴趣:
集线器注册必须在主线程中调用。否则 Xamarin.Azure.NotificationHubs.iOS 甚至不会给出出错的提示。
当实际类型为 NSDictionary 时,MSNotificationHub 的新方法在获取 UserInfo 并将其转换为 NSDictionary
时存在错误。 GitHub已经发布了一段时间了,但是还没有得到团队的任何回应,所以如果你通过推送通知传递消息以外的任何数据,抱歉,不行。 使用 SBNotificationHub 的旧方法具有严格的模板格式。首先,您应该使用 RegisterTemplate 方法来排除错误,而不是使用回调方法,因为前者是唯一出于某种原因给出错误描述的方法。 其次,你不能使用 {$(field)} 构造子定义模板,你需要指定属性的插入格式,如: "alert":"$( messageParam)","badge":"#(badge)","content-available":"#(contentAvailable)" 等。您还需要修改调度程序,以便它始终发送未加引号的参数。
IOS 实现非常原始,half-done 被遗忘了。我知道与 Apple 交互是完全地狱般的痛苦,但仍然...
希望它能为人们节省很多很多时间。
除了 Serg 的回答,您还需要使用 MainThread.BeginInvokeOnMainThread
进行 MSNotificationHub
注册。
不要使用Device.BeginInvokeOnMainThread
,它不起作用。
除了我的回答。我现在有 azure pushes,但我的解决方案混合了新旧方法。他们每个人都不能单独工作。
对于android: 当我使用新方法时,会在 azure 通知中心进行注册,但不会收到通知。 当我使用旧方法时,没有来自 azure 通知中心的通知。
- 必须在
RunOnUiThread
中为新方法调用集线器注册:
NotificationHub.Start(MainActivity.Instance.Application, NotificationHubName, ConnectionString);
NotificationHub.SetListener(new AzureListener());
-
AzureListener
的实现 class 是存根:
/// <summary>
/// It does nothing, but registrasion doesn't work without it.
/// </summary>
public class AzureListener : Java.Lang.Object, INotificationListener
{
/// <summary>
/// Stub
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
public void OnPushNotificationReceived(Context context, INotificationMessage message)
{}
}
- 对于旧方法,必须在非主线程中调用集线器注册:
await Task.Run(async () =>
{
await Task.Delay(1);
this.notificationHub = new WindowsAzure.Messaging.NotificationHub(NotificationHubName,ConnectionString, MainActivity);
notificationHub.UnregisterAll(PnsHandle);
notificationHub.Register(PnsHandle, new string[] { });
}
- 接收推送需要实现
FirebaseMessagingService
class。
对于iOS: 当我使用新方法时,天蓝色通知中心没有注册。 当我使用旧方法时,在 azure hub 进行了注册,但没有来自 azure 通知中心的通知。
- 必须在
MainThread
中为新方法调用集线器注册:
MSNotificationHub.Start(ConnectionString, NotificationHubName);
MSNotificationHub.SetDelegate(new AzureNotificationHubListener());
- 对于旧方法,必须在 xamarin 主线程中调用集线器注册:
await Device.InvokeOnMainThreadAsync(async () =>
{
Hub = new SBNotificationHub(connectionParameters.ConnectionString, connectionParameters.NotificationHubName);
await Hub.RegisterNativeAsync(AppDelegate.PnsHandle, null);
});
接收推送需要实现
AzureNotificationHubListener
class需要在
Info.plist
中添加key:NSAppTransportSecurity <字典>NSAllowsArbitraryLoads