Xamarin 通知服务扩展问题 [英] Xamarin Notification Service Extension issue

查看:15
本文介绍了Xamarin 通知服务扩展问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对通知服务扩展有疑问.我遵循了分步文档https://developer.xamarin.com/guides/ios/platform_features/introduction-to-ios10/user-notifications/enhanced-user-notifications/#Working_with_Service_Extensions

I have an issue with Notification Service Extension. I have followed step by step documentation https://developer.xamarin.com/guides/ios/platform_features/introduction-to-ios10/user-notifications/enhanced-user-notifications/#Working_with_Service_Extensions

为了实现,我是这样做的.

To implement, I have done in that way.

  • 添加了与我的应用具有相同前缀的通知服务扩展(添加后缀,例如:APP:com.testapp.main - EXT:com.testapp.main.notificationextension)
  • 在 Apple 会员中心创建了 APPID 标识符 com.testapp.main.notificationextension
  • 创建证书和配置文件以发送 APP ID com.testapp.main.notificationextension 的推送通知
  • 导入 Xcode 和 Xamarin 证书和配置
  • 参考通知扩展参考构建我的应用.
  • 创建存档以上传到 TestFlight
  • 使用分发证书和配置文件签名的应用
  • 带有分发证书和配置文件的签名扩展
  • 已上传到 TestFlight
  • 为我的应用下载并允许推送通知
  • 使用 Localytics Dashboard 发送丰富的推送通知以进行消息传递- 设备接收推送通知但不通过通知服务扩展的 NotificationService.cs 代码!

这是我的 NotificationService 代码:

This is my NotificationService code:

using System;
using Foundation;
using UserNotifications;

namespace NotificationServiceExtension
{
    [Register("NotificationService")]
    public class NotificationService : UNNotificationServiceExtension
    {
        Action<UNNotificationContent> ContentHandler { get; set; }
        UNMutableNotificationContent BestAttemptContent { get; set; }
        const string ATTACHMENT_IMAGE_KEY = "ll_attachment_url";
        const string ATTACHMENT_TYPE_KEY = "ll_attachment_type";
        const string ATTACHMENT_FILE_NAME = "-localytics-rich-push-attachment.";

        protected NotificationService(IntPtr handle) : base(handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }

        public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
        {
            System.Diagnostics.Debug.WriteLine("Notification Service DidReceiveNotificationRequest");
            ContentHandler = contentHandler;
            BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();
            if (BestAttemptContent != null)
            {
                string imageURL = null;
                string imageType = null;
                if (BestAttemptContent.UserInfo.ContainsKey(new NSString(ATTACHMENT_IMAGE_KEY)))
                {
                    imageURL = BestAttemptContent.UserInfo.ValueForKey(new NSString(ATTACHMENT_IMAGE_KEY)).ToString();
                }
                if (BestAttemptContent.UserInfo.ContainsKey(new NSString(ATTACHMENT_TYPE_KEY)))
                {
                    imageType = BestAttemptContent.UserInfo.ValueForKey(new NSString(ATTACHMENT_TYPE_KEY)).ToString();
                }

                if (imageURL == null || imageType == null)
                {
                    ContentHandler(BestAttemptContent);
                    return;
                }
                var url = NSUrl.FromString(imageURL);
                var task = NSUrlSession.SharedSession.CreateDownloadTask(url, (tempFile, response, error) =>
                {
                    if (error != null)
                    {
                        ContentHandler(BestAttemptContent);
                        return;
                    }
                    if (tempFile == null)
                    {
                        ContentHandler(BestAttemptContent);
                        return;
                    }
                    var cache = NSSearchPath.GetDirectories(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomain.User, true);
                    var cachesFolder = cache[0];
                    var guid = NSProcessInfo.ProcessInfo.GloballyUniqueString;
                    var fileName = guid + ATTACHMENT_FILE_NAME + imageType;
                    var cacheFile = cachesFolder + fileName;
                    var attachmentURL = NSUrl.CreateFileUrl(cacheFile, false, null);
                    NSError err = null;
                    NSFileManager.DefaultManager.Move(tempFile, attachmentURL, out err);
                    if (err != null)
                    {
                        ContentHandler(BestAttemptContent);
                        return;
                    }
                    UNNotificationAttachmentOptions options = null;
                    var attachment = UNNotificationAttachment.FromIdentifier("localytics-rich-push-attachment", attachmentURL, options, out err);
                    if (attachment != null)
                    {
                        BestAttemptContent.Attachments = new UNNotificationAttachment[] { attachment };
                    }
                    ContentHandler(BestAttemptContent);
                    return;
                });
                task.Resume();
            }
            else {
                ContentHandler(BestAttemptContent);
            }
        }

        public override void TimeWillExpire()
        {
            // Called just before the extension will be terminated by the system.
            // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
            ContentHandler(BestAttemptContent);
            return;
        }

    }
}

推荐答案

您做的一切都正确,这是其他一些 xamarin 开发人员提出的问题.据我所知,只要你运行 NSURLSession 来下载一些东西,即使它超级小,你也会超过这种类型的扩展允许的内存限制.这很可能是 xamarin 特有的.这是 bugzilla 的链接.https://bugzilla.xamarin.com/show_bug.cgi?id=43985

You are doing everything correctly, this is an issue raised by a few other xamarin developers. From what I can tell, as soon as you run the NSURLSession to download something, even if it's super super small, you go above the memory limit allowed for this type of extension. This is most probably very specific to xamarin. Here is the link to the bugzilla. https://bugzilla.xamarin.com/show_bug.cgi?id=43985

我发现的变通方法/hack 远非理想.我在objective-c的xcode中重写了这个应用程序扩展(我想你也可以使用swift).这是一个相当小的(1 类)扩展.然后使用相同的代码签名证书/配置文件在 xcode 中构建它,然后在 xcode 的输出中找到 .appex 文件.

The work-around/hack I found is far from ideal. I rewrote this app extension in xcode in objective-c (you could use swift too I suppose). It is a fairly small (1 class) extension. Then built it in xcode using the same code signature certificate / provisioning profile and then found the .appex file in the xcode's output.

从那时起,您可以采取便宜的方式",并在辞职和提交应用程序之前手动交换 .ipa 文件夹中的此 .appex 文件.如果这对你来说足够好,你可以停在这里.

From then, you can take the "cheap way", and swap this .appex file in your .ipa folder manually just before resigning and submitting the app. If that's good enough for you, you can stop here.

或者您可以自动执行此过程,为此,将 appex 文件放在 csproj 的扩展名中,并将构建操作设置为内容".然后在这个 csproj 的文件中(你需要直接编辑)你可以添加这样的东西.(在本例中,该文件名为 Notifications.appex,并放置在名为 NativeExtension 的文件夹中)

Or you can automate this process, to to so, place the appex file in the csproj's extension and set the build-action as "content". Then in this csproj's file (you'll need to edit directly) you can add something like this. (In this case, the file is called Notifications.appex and is placed in a folder called NativeExtension)

<Target Name="BeforeCodeSign">
    <ItemGroup>
        <NativeExtensionDirectory Include="NativeExtensionDebug***.*" />
    </ItemGroup>

    <!-- cleanup the application extension built with Xamarin (too heavy in memory)-->
    <RemoveDir SessionId="$(BuildSessionId)"
               Directories="biniPhoneDebugNotifications.appex"/>

    <!-- copy the native one, built in obj-c -->
    <Copy
            SessionId="$(BuildSessionId)"
            SourceFiles="@(NativeExtensionDirectory)"
            DestinationFolder="biniPhoneDebugNotifications.appex"
            SkipUnchangedFiles="true"
            OverwriteReadOnlyFiles="true"
            Retries="3"
            RetryDelayMilliseconds="300"/>
</Target>

这给了你一般的想法,但很明显,如果你想支持临时分发签名,iOS应用商店分发签名,你需要在其中添加更多代码(并可能在csproj中添加一个本地appex每个不同签名的文件),我建议将此类 xml 代码放在单独的.targets"文件中,并在 csproj 中使用条件调用目标.像这样:

This gives you the general idea, but obviously if you want to support ad-hoc distribution signature, iOS app-store distribution signature you will need to add a bit more code into this (and possibly add in the csproj a native appex file for each different signature), I would suggest putting such xml code in separate ".targets" file and use conditional calltargets in the csproj. Like this:

<Target Name="BeforeCodeSign">
    <CallTarget Targets="ImportExtension_Debug" Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' " />
    <CallTarget Targets="ImportExtension" Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' " />
 </Target>

这篇关于Xamarin 通知服务扩展问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆