在通知服务扩展中创建UNNotificationCategory不工作Xamarin

wd2eg0qa  于 9个月前  发布在  Go
关注(0)|答案(1)|浏览(79)

对于我的应用程序,我没有一组有限的按钮需要支持。相反,我们在通知有效负载中发送按钮。正因为如此,我需要能够在每次接收到带有有效负载中的按钮的通知时动态创建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);
}
dgjrabp2

dgjrabp21#

我终于找到了一个答案,虽然它似乎不是正确的。
在遇到https://learn.microsoft.com/en-us/xamarin/ios/platform/introduction-to-ios12/notifications/dynamic-actions时,“通知内容扩展中的操作按钮”部分简要地提到了使用ViewController's``ExtensionContext调用SetNotificationActions()。这确实有效。
完整解决方案:

public void DidReceiveNotification(UNNotification notification)
        {
            var content = notification.Request.Content;

            var actions = new List<UNNotificationAction>();
            List<SimplePushNotificationButton> buttons = new List<SimplePushNotificationButton>();

            if (content.UserInfo.TryGetValue(new NSString("buttonJSON"), out NSObject buttonsObject))
            {
                string buttonsString = buttonsObject.ToString();
                if (!string.IsNullOrEmpty(buttonsString))
                {
                    buttons = JsonConvert.DeserializeObject<List<SimplePushNotificationButton>>(buttonsString);
                    for (int i = 0; i < buttons.Count; i++)
                    {
                        // use the button text within the action id so we can match them later in AppDelegate.HandlePushNotificationButton
                        // TODO: add icon?
                        var action = UNNotificationAction.FromIdentifier(
                            $"{Guid.NewGuid()}_{buttons[i].Text}",
                            buttons[i].Text, buttons[i].Action.URLAction == URLAction.Post ? UNNotificationActionOptions.None : UNNotificationActionOptions.Foreground);

                        actions.Add(action);
                    }
                }
            }

            // This is what actually adds the buttons
            ExtensionContext.SetNotificationActions(actions.ToArray());
        }

        [Export("didReceiveNotificationResponse:completionHandler:")]
        public void DidReceiveNotification(UNNotificationResponse response, Action<UNNotificationContentExtensionResponseOption> completionHandler)
        {
            // We want to handle the button tap in the main project, not this one
            completionHandler(UNNotificationContentExtensionResponseOption.DismissAndForwardAction);
        }

我不认为这是最好的解决方案,因为没有其他地方推荐使用扩展上下文来添加按钮。在其他地方,甚至苹果的官方文档都说要用Actions创建一个Category,然后确保你的通知有一个匹配的CategoryID。
这个解决方案唯一的一个小缺点是,由于DidReceiveNotification在3D触摸通知后没有运行,按钮需要大约一秒钟才能显示出来。

相关问题