Is it possible to use BOTH a Notification Service Extension and Notification Content Extension?

Cdn_EuroCdn_Euro Member ✭✭✭

For my application I am using a Notification Service Extension to modify the way the notification is displayed to the user.
I also want to display a photo in its content, for this I understand I would need to use a Notification Content Extension.

Is it possible to use both? I don't really see how that would be.

How can I add a photo in my notification and where would that photo need to reside? Can be it in the Library folder?

Best Answers

  • Cdn_EuroCdn_Euro ✭✭✭
    Accepted Answer

    @LandLu Thanks once more for your help and clarity of answers :)

Answers

  • Cdn_EuroCdn_Euro Member ✭✭✭
    Accepted Answer

    @LandLu Thanks once more for your help and clarity of answers :)

  • LandLuLandLu Member, Xamarin Team Xamurai
    edited January 16
    Wish you have a happy coding day.
  • Cdn_EuroCdn_Euro Member ✭✭✭
    edited January 25

    @LandLu im doing something wrong. The Photo does not display here is my code:

    The custom photo resides in(which is also the value for "imageAbsoluteString"):

    /var/mobile/Containers/Data/Application/FA51C686-2BA2-4141-A354-AC54F7A41899/Documents/../Library/Pictures/customphoto.jpg

    Also tried with:

    /var/mobile/Containers/Data/Application/FA51C686-2BA2-4141-A354-AC54F7A41899/Documents/customphoto.jpg

    public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
            {
                ContentHandler = contentHandler;
                BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();
                string imgUrl;
    
                string notificationBody = BestAttemptContent.Body;
    
                string suiteName = "com.company.appname";  
    
                NSUserDefaults groupUserDefaults = new NSUserDefaults(suiteName, NSUserDefaultsType.SuiteName);     
    
                string userPreference = groupUserDefaults.StringForKey("userprefrence_key");
    
                // extracting some part of the notification body to display in subtitle
                string[] notificationBodySplitAtDelimiterArray = notificationBody.Split(',');
                incomingNotifData = notificationBodySplitAtDelimiterArray[0];
    
                bool isCustomAlertSet = groupUserDefaults.BoolForKey("isCustomAlert");
                bool isCustomPhotoSet = groupUserDefaults.BoolForKey("isCustomPhotoSet");
    
                string alarmPath = isCustomAlertSet == true ? "customalert.wav" : "defaultsound.m4a";
    
                if (isCustomPhotoSet)
                {
                    imgUrl = groupUserDefaults.StringForKey("imageAbsoluteString");
                }
                else
                {
                    imgUrl = null;          // this will be a default photo later on
                }     
    
                if (!string.IsNullOrEmpty(userPreference))
                {
                    if (BestAttemptContent.Body.Contains(userPrefrence))
                    {     
                        BestAttemptContent.Title = "MyCustomTitle";
                        BestAttemptContent.Subtitle = "MyCustomSubtitle" + incomingNotifData;
                        BestAttemptContent.Body = "CustomBodyContent";
                        BestAttemptContent.Sound = UNNotificationSound.GetSound(alarmPath);
    
                        if (!string.IsNullOrEmpty(imgUrl))
                        {
                            loadAttachmentForUrlString(imgUrl, "jpg", (attach) =>
                            {
                                if (attach != null)
                                {
                                    BestAttemptContent.Attachments = new UNNotificationAttachment[] { attach };
                                }
                            });
                        }                                   
    
                    }
                    else
                    {
                           // create some other type of notification style
                    }
    
                ContentHandler(BestAttemptContent);
            }
    
            delegate void CompletionHandler(UNNotificationAttachment attach);
            void loadAttachmentForUrlString(string urlString, string type, CompletionHandler completionHandler)
            {
                NSUrl attachmentURL = new NSUrl(urlString);
    
                NSUrlSession session = NSUrlSession.FromConfiguration(NSUrlSessionConfiguration.DefaultSessionConfiguration);
                session.CreateDownloadTask(attachmentURL, (url, response, error) => {
    
                    if (error != null)
                    {
                        // Fail
                    }
                    else
                    {
    
                        /*             ---> commented this out because the photo is already local
                        NSFileManager fileManager = NSFileManager.DefaultManager;
                        NSUrl localUrl = new NSUrl(url.Path + "." + type, false);
                        NSError moveError = null;
                        fileManager.Move(url, localUrl, out moveError);
                        */
    
    
                        NSError attachmentError = null;
                        UNNotificationAttachment attachment = UNNotificationAttachment.FromIdentifier("", attachmentURL, options: null, error: out attachmentError);
                        if (attachmentError != null)
                        {
                            // Fail
                        }
                        else
                        {
                            completionHandler(attachment);
                        }
                    }
                }).Resume();
            }
            */
    
            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);
            }
    
  • Cdn_EuroCdn_Euro Member ✭✭✭
    edited January 29

    @LandLu I am struggling with this one, here is the updated code, no photo appears, just the title customizations but I went over the logic and I cannot find what I am doing wrong....:

    The Path of the the custom photo after saving in AppGroup Container:

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

    1. in my PCL I save the photo to the AppGroup when a save button is pressed:

          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. in my iOS project, Dependency injection calls this method when pressing save button:

      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;
              }
      
    3. Finally in the Notification Service Extension I try to attach the photo to the push notification:

      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)
                  {
                       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";
                  }                         
                  ContentHandler(BestAttemptContent);
              }
      
  • Cdn_EuroCdn_Euro Member ✭✭✭

    @LandLu worked like a charm. I was trying wrongfully to download from App Container instead of just copying, makes sense. Thank you so much for your help.

Sign In or Register to comment.