Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Xamarin forms: How to handle notification tap when the app is not in the background?(killed state)

SreeeeSreeee INMember ✭✭✭✭✭

I have implemented push notification on my xamarin forms project(chat application) using Firebase Cloud Messaging. Notification is receiving in all the states and when tapping the notification I need to show the corresponding message listing page.

Notification tapping is working when the app is in the foreground and background modes. But when the app is not present in the background(killed state), tapping is not working. Using DidReceiveRemoteNotification I am handling the notification tap when the app is in the background state. Using WillPresentNotification and DidReceiveNotificationResponse I am showing the notification and handling the notification tap in foreground mode. Codes added below:

 //Notification tapping when the app is in background mode.
 public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
        {
            HandleMessage(userInfo);

            // Print full message.
            LogInformation(nameof(DidReceiveRemoteNotification), userInfo);

            completionHandler(UIBackgroundFetchResult.NewData);

            var myData = JsonConvert.DeserializeObject<List<webContentList>>(userInfo[new NSString("webContentList")] as NSString);
            Console.WriteLine($"myData received: {myData}");
            if (UIApplication.SharedApplication.ApplicationState.Equals(UIApplicationState.Active))
            {
                //App is in foreground, no action
            }
            else
            {
                MessagingCenter.Send<object, List<webContentList>>(this, "messagedata", myData);
            }
        }

        //Showing the notification when the app is in the foreground mode.
       [Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
        public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification,
Action<UNNotificationPresentationOptions> completionHandler)
        {
            completionHandler(UNNotificationPresentationOptions.Sound | UNNotificationPresentationOptions.Alert);
        }

        //Notification tapping when the app is in the foreground mode.
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
            public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action
            completionHandler)
            {
                completionHandler();
                NSDictionary userInfo = response.Notification.Request.Content.UserInfo;
                var myData = JsonConvert.DeserializeObject<List<webContentList>>(userInfo[new NSString("webContentList")] as NSString);
                Console.WriteLine($"myData received: {myData}");
                MessagingCenter.Send<object, List<webContentList>>(this, "messagedata", myData);
            }

FinishedLaunching

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            LoadApplication(new App());

            #region Push Notification            
            Firebase.Core.App.Configure();

            // Register your app for remote notifications.
            if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
            {
                // iOS 10 or later
                var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
                UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => {
                    Console.WriteLine(granted);
                });

                // For iOS 10 display notification (sent via APNS)
                UNUserNotificationCenter.Current.Delegate = this;

                // For iOS 10 data message (sent via FCM)
                //Messaging.SharedInstance.RemoteMessageDelegate = this;
            }
            else
            {
                // iOS 9 or before
                var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
                var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
                UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
            }

            UIApplication.SharedApplication.RegisterForRemoteNotifications();

            Messaging.SharedInstance.Delegate = this;
            Messaging.SharedInstance.ShouldEstablishDirectChannel = true;
            #endregion

            return base.FinishedLaunching(app, options);
        }

My notification body: webContentList is my model data.

{
 "to" : "dmtfiSvBBM0:APA91bFnHkamMSYgxPuiSfdvKnU8hD_mOqrWijnENNgXVSkSgo1ILH3-uKVCU7Ez2PXXOhtDoobIyKBf5UshVfTmvjSqHgXMRTsqguKCSTjIfGnXrVP-_cNFq2sisshZO-BcfkwKTl-I",
 "collapse_key" : "type_a",
 "notification" : {
      "body" : "This is body",
     "title": "Tech Team",
     "priority":"high",
     "content_available":true
 },
 "data" : {
    "webContentList": [
        {
            "webContentDefinitionId": 818084,
            "pageTitle": "CCD Grade 3-4",
            "pageKwd": "CCD Grade 3-4",
            "pageDesc": "CCD Grade 3-4",
            "siteId": 45,
            "pageCreatedTime": 1555145959428,
            "pageUpdatedDate": 1555927274279,
            "modifier": {
                "userId": 12944,
                "applicationId": 32,
                "username": "robert.downey",
                "email": "[email protected]",
                "firstName": "Robert",
                "lastName": "Downey"
            },
            "creator": {
                "userId": 12944,
                "applicationId": 32,
                "username": "robert.downey",
                "email": "[email protected]",
                "firstName": "Robert",
                "lastName": "Downey"
            }
        }
        ]
 },
  "ttl": 3600
}

Issue

When the app is in the killed state only the home page is loading, not showing the message listing page. But before showing the home page in the UI, the message listing show progress(acr userdialogs) is also present in the UI. So I think LoadApplication(new App()); in FinishedLaunching is working after the notification tap function when the app is in the killed state. So how I can stop the execution of the normal app launching code and show the message listing page when the app is in the killed state?

Answers

  • ColeXColeX Member, Xamarin Team Xamurai
    edited July 2019

    If you click notification(not click itself) to open your application , the NSDictionary options in FinishedLaunching method should contain the notification message , you could pass the data to Forms Project by extending App constructor.

    AppDelegate in iOS

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
    
            var myData = JsonConvert.DeserializeObject<List<webContentList>>(options[new NSString("webContentList")] as NSString);
    
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App(myData));
    
            return base.FinishedLaunching(app, options);
        }
    

    App in Forms

    public App(List<webContentList> list)
        {
            InitializeComponent();
    
            // handle the logic 
        }
    
  • SreeeeSreeee INMember ✭✭✭✭✭

    @ColeX, In this case, how can I handle the normal launching of the app?

    Is it possible to use MessagingCenter instead of passing via arguments to App.xaml.cs? Because I have already used MessagingCenter in foreground and background modes.

  • ColeXColeX Member, Xamarin Team Xamurai
    edited July 2019

    Try to use MessagingCenter like what you've done in foreground and background modes , but ensure the code should be placed after LoadApplication(new App()); .

  • SreeeeSreeee INMember ✭✭✭✭✭

    @ColeX Update

    Tried like below. Initial launching was fine but crashing when launching via notification tap.

      LoadApplication(new App());
    
            if (options != null)
            {
                var myData = JsonConvert.DeserializeObject<List<webContentList>>(options[new NSString("webContentList")] as NSString);
                if(myData != null)
                {
                    MessagingCenter.Send<object, List<webContentList>>(this, "messagedata", myData);
                }
            }
    
  • ColeXColeX Member, Xamarin Team Xamurai

    What's the error message ? Is options null or not ?

  • SreeeeSreeee INMember ✭✭✭✭✭
    edited July 2019

    @ColeX Got nullreference exception when launching initially, So I add null check for options and myData. After that initial launching is working fine. But launching from the notification tap is crashing the app.

  • SreeeeSreeee INMember ✭✭✭✭✭

    @ColeX

    But the problem is I am working on the killed state notification tapping. For testing this I need to clear the app from background. After clearing the app from background I can't see the logs. I am using visual studio for mac for the development So is there any way to view the logs after clearing the app from background?

  • ColeXColeX Member, Xamarin Team Xamurai
    edited July 2019

    Get clear what the options is first , the exception must be caused by fetching with incorrect key options[new NSString("webContentList")]

  • GraverobberGraverobber Member ✭✭✭

    @Sreeee

    After clearing the app from background I can't see the logs. I am using visual studio for mac for the development So is there any way to view the logs after clearing the app from background?

    This is not entirely true. If your app is crashing as you say then there is a log stored that you can get via Xcode, it is what I told you in the other thread. this log is not deleted after you kill the app from TaskManager. In fact it persists for a long time, I have logs from a month ago in my list.
    Please double check that in order to get a useful log

Sign In or Register to comment.