Xamarin.iOS 无法在推送通知中显示照片

Posted

技术标签:

【中文标题】Xamarin.iOS 无法在推送通知中显示照片【英文标题】:Xamarin.iOS Cannot display photo in Push Notification 【发布时间】:2019-01-29 00:37:58 【问题描述】:

我有一个通知服务扩展和一个 AppGroup。我将相机中的照片保存在 PCL 项目中,并将其复制到 App Group Container(共享文件夹)。

在通知服务扩展中,我尝试从 App Group 容器中下载照片并将其附加到通知中,但它并未显示在通知中。

我也无法调试服务扩展以查看发生了什么。据我所知,除非有人可以纠正我,否则目前在 Xamarin 中是不可能的。

代码如下:

1.在我的 PCL 中,当按下保存按钮时,我将照片保存到 AppGroup:

 private void ButtonSavePhoto_Clicked(object sender, EventArgs e)
            
                if (!string.IsNullOrEmpty(photoFilePath))
                
                    Preferences.Set(AppConstants.CUSTOM_PICTURE_FILE_PATH, photoFilePath);
                    Preferences.Set(AppConstants.CUSTOM_PHOTO_SET_KEY, true);

                    if (Device.RuntimePlatform == Device.ios)
                    

                        bool copiedSuccessfully = DependencyService.Get<IPhotoService>().CopiedFileToAppGroupContainer(photoFilePath);

                        if (copiedSuccessfully)
                        
                            var customPhotoDestPath = DependencyService.Get<IPhotoService>().GetAppContainerCustomPhotoFilePath();

                            // save the path of the custom photo in the AppGroup container to pass to Notif Extension Service
                            DependencyService.Get<IGroupUserPrefs>().SetStringValueForKey("imageAbsoluteString", customPhotoDestPath);

                            // condition whether to use custom photo in push notification
                            DependencyService.Get<IGroupUserPrefs>().SetBoolValueForKey("isCustomPhotoSet", true);
                        
                    

                    buttonSavePhoto.IsEnabled = false;
                         
            

2.在我的iOS项目中,当按下保存按钮时,依赖注入会调用这个方法:

    public bool CopiedFileToAppGroupContainer(string filePath)
    
                bool success = false;

                string suiteName = "group.com.company.appName";
                var appGroupContainerUrl = NSFileManager.DefaultManager.GetContainerUrl(suiteName);

                var appGroupContainerPath = appGroupContainerUrl.Path;

                var directoryNameInAppGroupContainer = Path.Combine(appGroupContainerPath, "Pictures");

                var filenameDestPath = Path.Combine(directoryNameInAppGroupContainer, AppConstants.CUSTOM_PHOTO_FILENAME);

                try
                
                    Directory.CreateDirectory(directoryNameInAppGroupContainer);

                    if (File.Exists(filenameDestPath))
                    
                        File.Delete(filenameDestPath);
                    

                    File.Copy(filePath, filenameDestPath);
                    success = true;
                
                catch (Exception ex)
                
                    Console.WriteLine(ex.Message);
                

                return success;
            

现在 App Group 容器中照片的路径是:

/private/var/mobile/Containers/Shared/AppGroup/12F209B9-05E9-470C-9C9F-AA959D940302/Pictures/customphoto.jpg

3.最后在通知服务扩展中,我尝试将照片附加到推送通知中:

public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
        
            ContentHandler = contentHandler;
            BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();

            string imgPath;
            NSUrl imgUrl;

            string notificationBody = BestAttemptContent.Body;
            string notifBodyInfo = "unknown";

            string suiteName = "group.com.company.appname";  

            NSUserDefaults groupUserDefaults = new NSUserDefaults(suiteName, NSUserDefaultsType.SuiteName);           

            string pref1_value = groupUserDefaults.StringForKey("user_preference1");

            string[] notificationBodySplitAtDelimiterArray = notificationBody.Split(',');
            userPrefRegion = notificationBodySplitAtDelimiterArray[0];

            bool isCustomAlertSet = groupUserDefaults.BoolForKey("isCustomAlert");
            bool isCustomPhotoSet = groupUserDefaults.BoolForKey("isCustomPhotoSet");

            string alarmPath = isCustomAlertSet == true ? "customalert.wav" : "default_alert.m4a";

            if (isCustomPhotoSet)
            
                 // this is the App Group url of the custom photo saved in PCL
                 imgPath = groupUserDefaults.StringForKey("imageAbsoluteString");             
            
            else
            
                imgPath = null;
            

            if (imgPath != null )
                            
                imgUrl = NSUrl.FromString(imgPath);
            
            else
            
                imgUrl = null;
            

            if (!string.IsNullOrEmpty(pref1_value))
            
                if (BestAttemptContent.Body.Contains(pref1_value))
                

                   if (imgUrl != null)
                   

                        // download the image from the AppGroup Container
                        var task = NSUrlSession.SharedSession.CreateDownloadTask(imgUrl, (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 + "customphoto.jpg";
                            var cacheFile = cachesFolder + fileName;
                            var attachmentUrl = NSUrl.CreateFileUrl(cacheFile, false, null);

                            NSError err = null;
                            NSFileManager.DefaultManager.Copy(tempFile, attachmentUrl, out err);

                            if (err != null)
                            
                                ContentHandler(BestAttemptContent);
                                return;
                            

                            UNNotificationAttachmentOptions options = null;
                            var attachment = UNNotificationAttachment.FromIdentifier("image", attachmentUrl, options, out err);

                            if (attachment != null)
                            
                                BestAttemptContent.Attachments = new UNNotificationAttachment[]  attachment ;
                                
                        );
                        task.Resume();
                                                           
                    BestAttemptContent.Title = "My Custom Title";
                    BestAttemptContent.Subtitle = "My Custom Subtitle";
                    BestAttemptContent.Body = "Notification Body";
                    BestAttemptContent.Sound = UNNotificationSound.GetSound(alarmPath);        
                                 
            
            else
            
               pref1_value = "error getting extracting user pref";
                    

            // finally display customized notification                 
            ContentHandler(BestAttemptContent);
        

【问题讨论】:

【参考方案1】:

/private/var/mobile/Containers/Shared/AppGroup/12F209B9-05E9-470C-9C9F-AA959D940302/Pictures/customphoto.jpg

从共享代码中,当图像从 AppGroup 中获取时。您可以检查文件路径是否在该项目中有效。

imgPath = groupUserDefaults.StringForKey("imageAbsoluteString"); 

如果没有从该路径获取文件。您可以直接从AppGroup 获取Url。示例如下:

var FileManager = new NSFileManager();
var appGroupContainer = FileManager.GetContainerUrl("group.com.company.appName");
NSUrl fileURL = appGroupContainer.Append("customphoto.jpg", false);

如果fileURL不能直接使用,也可以转换成NSData保存到本地文件系统。这个也可以试试。

下面是一个从本地文件系统中获取的示例:

public static void Sendlocalnotification()
       
    var localURL = "...";
    NSUrl url = NSUrl.FromString(localURL) ;

    var attachmentID = "image";
    var options = new UNNotificationAttachmentOptions();
    NSError error;
    var attachment = UNNotificationAttachment.FromIdentifier(attachmentID, url, options,out error);


    var content = new UNMutableNotificationContent();
    content.Attachments = new UNNotificationAttachment[]  attachment ;
    content.Title = "Good Morning ~";
    content.Subtitle = "Pull this notification ";
    content.Body = "reply some message-BY Ann";
    content.CategoryIdentifier = "message";

    var trigger1 = UNTimeIntervalNotificationTrigger.CreateTrigger(0.1, false);

    var requestID = "messageRequest";
    var request = UNNotificationRequest.FromIdentifier(requestID, content, trigger1);

    UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
     
         if (err != null)
         
             Console.Write("Notification Error");
         
     );


【讨论】:

以上是关于Xamarin.iOS 无法在推送通知中显示照片的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.iOS - 设备关闭时推送通知

Xamarin.IOS 和 Signalr 推送通知

Xamarin iOS - 推送通知 - 区分点击的推送通知与到达

Xamarin.iOS:Firebase 推送通知不起作用

xamarin.ios 本地通知推送

后台未调用 DidReceiveRemoteNotification - Xamarin iOS - 推送通知