对于我的应用程序,我没有一组有限的按钮需要支持。相反,我们在通知有效负载中发送按钮。正因为如此,我需要能够在每次接收到带有有效负载中的按钮的通知时动态创建UNNotificationCategory。
为了实现这一点,我创建了一个NotificationServiceExtension来拦截通知、解析有效负载、创建类别并更新推送通知的类别。这一切看起来都是可行的,但实际上,当从Notification Service Extension中创建UNNotificationCategory时,推送通知没有该类别的操作。
测试:我在FinishedLaunching中放置了一段代码来打印所有的UNNotificationCategories,它总是返回空。我不确定这是否是合理的信息,因为我不确定FinishedLaunching是否在通知外部之前运行。我有一种感觉,UNUserNotificationCenter.Current示例在不同的项目之间是不同的,但我创建了一个测试库项目,在那里我创建了Categories,它们可以在主项目中使用。
其他注意事项:当在FinishedLaunching中创建测试UNNotificationCategories,然后只更新通知扩展中推送通知的categoryID时,它会工作。但这不是动态的。
为什么我在Notification Service Extension中创建的类别不可用于推送通知?
代码:
AppDelegate.cs(主项目)
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Rg.Plugins.Popup.Popup.Init();
global::Xamarin.Forms.Forms.Init();
IOSMigrationHelper migrationHelper = new IOSMigrationHelper();
// must be done before Firebase.Core.App.Configure() to migrate the saved fcm token
// and before LoadApplication() so we don't run the initial setup process
// and after Xamarin.Forms.Forms.Init() so we can use DependencyService
migrationHelper.Migrate();
Forms9Patch.iOS.Settings.Initialize(this);
LoadApplication(new App());
bool success = base.FinishedLaunching(app, options);
if (success)
{
AllGesturesRecognizer allGesturesRecognizer = new AllGesturesRecognizer(delegate
{
SessionManager.Instance.ExtendSession();
});
Window.AddGestureRecognizer(allGesturesRecognizer);
}
if (string.IsNullOrEmpty(AppPreferences.DeviceIdentifier))
{
// this will change if the user removes and reinstalls the app but there isn't anything else to use
AppPreferences.DeviceIdentifier = UIDevice.CurrentDevice.IdentifierForVendor.ToString();
}
// Test Categories. Creating them here and then just updating the categoryID in the notification extension works
var actions1 = new List<UNNotificationAction>();
var action11 = UNNotificationAction.FromIdentifier($"C1 B1", "C1 B1", UNNotificationActionOptions.None); // TODO: change to foregound if urlaction != post
var action12 = UNNotificationAction.FromIdentifier($"C1 B2", "C1 B2", UNNotificationActionOptions.None);
var actions2 = new List<UNNotificationAction>();
var action21 = UNNotificationAction.FromIdentifier($"C2 B1", "C2 B1", UNNotificationActionOptions.None);
var action22 = UNNotificationAction.FromIdentifier($"C2 B2", "C2 B2", UNNotificationActionOptions.None);
actions1.Add(action11);
actions1.Add(action12);
actions2.Add(action21);
actions2.Add(action22);
var intentIDs = new string[] { };
var category1 = UNNotificationCategory.FromIdentifier("cat1", actions1.ToArray(), intentIDs, UNNotificationCategoryOptions.AllowInCarPlay | UNNotificationCategoryOptions.AllowAnnouncement);
var category2 = UNNotificationCategory.FromIdentifier("cat2", actions2.ToArray(), intentIDs, UNNotificationCategoryOptions.AllowInCarPlay | UNNotificationCategoryOptions.AllowAnnouncement);
// Register category
var categories = new UNNotificationCategory[] { category1, category2 };
UserNotificationCenter.Current.SetNotificationCategories(new NSSet<UNNotificationCategory>(categories));
PrintCategories();
SetupPushNotifications(app);
return success;
}
async void PrintCategories()
{
try
{
NSSet<UNNotificationCategory> categories = await iOSNotificationCenter.Current.GetNotificationCategoriesAsync();
// Categories is null when the categories created in the AppDelegate are commented out and moved to the Notification Extension
if (categories == null)
{
App.Current.MainPage.DisplayAlert($"No categories", "", "Ok");
return;
}
foreach (UNNotificationCategory c in categories)
{
App.Current.MainPage.DisplayAlert($"Category: {c.Identifier}", "", "Ok");
}
}
catch (Exception e)
{
App.Current.MainPage.DisplayAlert(e.ToString(), "", "Ok");
}
}
NotificationService.cs(通知服务扩展)
public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
{
ContentHandler = contentHandler;
BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();
var categoryID = "but1";
// creating the categories in the notification service extension doesn't work. The notification doesn't have any buttons
var actions = new List<UNNotificationAction>();
var action1 = UNNotificationAction.FromIdentifier($"Button 1", "Button 1", UNNotificationActionOptions.None);
var action2 = UNNotificationAction.FromIdentifier($"Button 2", "Button 2", UNNotificationActionOptions.None);
actions.Add(action1);
actions.Add(action2);
var intentIDs = new string[] { };
var category = UNNotificationCategory.FromIdentifier(categoryID, actions.ToArray(), intentIDs, UNNotificationCategoryOptions.AllowInCarPlay | UNNotificationCategoryOptions.AllowAnnouncement);
//// Register category
var categories = new UNNotificationCategory[] { category };
UNUserNotificationCenter.Current.SetNotificationCategories(new NSSet<UNNotificationCategory>(categories));
BestAttemptContent.CategoryIdentifier = categoryID;
ContentHandler(BestAttemptContent);
}
1条答案
按热度按时间dgjrabp21#
我终于找到了一个答案,虽然它似乎不是正确的。
在遇到https://learn.microsoft.com/en-us/xamarin/ios/platform/introduction-to-ios12/notifications/dynamic-actions时,“通知内容扩展中的操作按钮”部分简要地提到了使用
ViewController's``ExtensionContext
调用SetNotificationActions()
。这确实有效。完整解决方案:
我不认为这是最好的解决方案,因为没有其他地方推荐使用扩展上下文来添加按钮。在其他地方,甚至苹果的官方文档都说要用Actions创建一个Category,然后确保你的通知有一个匹配的CategoryID。
这个解决方案唯一的一个小缺点是,由于
DidReceiveNotification
在3D触摸通知后没有运行,按钮需要大约一秒钟才能显示出来。