question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Xamarin.Forms Tutorial for the Push Notification Plugin breaks Android Notifications when App is Not Running or Backgrounded (Fix Included in Comments)

See original GitHub issue

tl;dr The Xamarin.Forms’ DependancyService prevents Android apps from receiving push notifications when not running or backgrounded.

I recommend updating the tutorial on the Push Notification Plugin’s GitHub page to help prevent confusion from other developers in the future: Adding Push Notification Post to your Xamarin Forms Application. I followed this tutorial to implement the Push Notification Plugin, and it lead me to this road block: my Android app could not receive push notifications when it was not running or backgrounded.

After following this step-by-step tutorial to setup the Push Notification Plugin on Xamarin.Forms, the iOS push notifications work flawlessly and the Android devices receive push notifications when the app is running or backgrounded. But on Android, if I force-close the app so that it is no longer running (e.g. press the Recent Apps button, and swipe away my app), and then send a push notification, the device shows this error message: “Unfortunately, [App Name] has stopped” (screen shot below).

The error below was appearing because I did not call the CrossPushNotification.Initialize<CrossPushNotificationListener>(Keys_Constants.GOOGLE_APIs_ID); method inside [Application] OnCreate() as is recommended on the Push Notification Plugin’s GitHub page.

But, the reason why I didn’t/couldn’t include this method in [Application] OnCreate() was because CrossPushNotificationListener requires the Xamarin.Forms’ DependencyService, which is impossible in [Application] OnCreate() because the DependencyService hasn’t been initialized yet; global::Xamarin.Forms.Forms.Init(this, bundle); is called in Android’s MainActivity which hasn’t been yet instantiated when the code is executing the [Application] class.

The remedy was to break apart my cross-platform implementation of the CrossPushNotificationListener into a platform-specific NotificationListener that now live in the platform-specific PCL (code below).

I recommend updating the tutorial on the GitHub page to implement this plugin for Xamarin.Forms. The tutorial has the user create a CrossPushNotificationListener class that uses Xamarin.Forms’ DependencyService. This tutorial works flawlessly to receive push notifications on iOS, but on Android, it will only allow the device to receive push notifications while the app is running or backgrounded.

Error When Sending a Push Notification to a App That Is Not Running and Not Backgrounded (Before implementing the fix)

screenshot_2016-02-23-19-11-58

Updated Platform-Specific Notification Listener for Android

[Application] File

using System;

using Android.OS;
using Android.App;
using Android.Content;
using Android.Runtime;

using Plugin.CurrentActivity;
using PushNotification.Plugin;

using Xamarin;

namespace MondayPundayApp.Droid
{
    //You can specify additional application information in this attribute
    [Application]

    public class Punday : Application, Application.IActivityLifecycleCallbacks
    {
        public static Context AppContext;

        public Punday(IntPtr handle, JniHandleOwnership transer)
          : base(handle, transer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();

            RegisterActivityLifecycleCallbacks(this);

            AppContext = this.ApplicationContext;

            CrossPushNotification.Initialize<AndroidPushNotificationListener>(Keys_Constants.GOOGLE_APIs_ID);

            StartPushService();
        }

        public override void OnTerminate()
        {
            base.OnTerminate();
            UnregisterActivityLifecycleCallbacks(this);
        }

        void IActivityLifecycleCallbacks.OnActivityCreated(Activity activity, Bundle savedInstanceState)
        {
            CrossCurrentActivity.Current.Activity = activity;
        }

        public void OnActivityDestroyed(Activity activity)
        {
        }

        public void OnActivityPaused(Activity activity)
        {
        }

        public void OnActivityResumed(Activity activity)
        {
            CrossCurrentActivity.Current.Activity = activity;
        }

        public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
        {
        }

        public void OnActivityStarted(Activity activity)
        {
            CrossCurrentActivity.Current.Activity = activity;
        }

        public void OnActivityStopped(Activity activity)
        {
        }
        public static void StartPushService()
        {
            AppContext.StartService(new Intent(AppContext, typeof(PushNotificationService)));

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
            {

                PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(PushNotificationService)), 0);
                AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(Context.AlarmService);
                alarm.Cancel(pintent);
            }
        }

        public static void StopPushService()
        {
            AppContext.StopService(new Intent(AppContext, typeof(PushNotificationService)));

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
            {
                PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(PushNotificationService)), 0);
                AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(Context.AlarmService);
                alarm.Cancel(pintent);
            }
        }
    }
}

AndroidPushNotificationListener.cs

using PushNotification.Plugin;
using PushNotification.Plugin.Abstractions;

using Newtonsoft.Json.Linq;
using MondayPundayApp.Droid;

namespace MondayPundayApp.Droid
{
    public class AndroidPushNotificationListener : IPushNotificationListener
    {
        AzureNotificationHubService_Android _azureNotificationHubService;

        public AndroidPushNotificationListener()
        {
            _azureNotificationHubService = new AzureNotificationHubService_Android();
        }

        public async void OnRegistered(string Token, DeviceType deviceType)
        {
            await _azureNotificationHubService.RegisterNativeAsync(Token);
        }

        public async void OnUnregistered(DeviceType deviceType)
        {
            await _azureNotificationHubService.UnregisterNativeAsync();
        }

        public void OnError(string message, DeviceType deviceType)
        {
        }

        public void OnMessage(JObject values, DeviceType deviceType)
        {
        }

        public bool ShouldShowNotification()
        {
            return true;
        }
    }
}

AzureNotificationHubService_Android.cs

using System;
using System.Threading.Tasks;

using Microsoft.WindowsAzure.MobileServices;

using Xamarin;

namespace MondayPundayApp.Droid
{
    public class AzureNotificationHubService_Android 
    {
        private MobileServiceClient _mobileServiceClient;
        private Push _push;

        public string CurrentDeviceId { get; private set; }

        public AzureNotificationHubService_Android()
        {
            try
            {
                _mobileServiceClient = new MobileServiceClient(Keys_Constants.AzureMobileService_URL, Keys_Constants.AzureMobileService_KEY);
                _push = _mobileServiceClient.GetPush();
            }
            catch (Exception e)
            {
                Insights.Report(e);
            }
        }

        public async Task UnregisterNativeAsync()
        {
            try
            {
                await _push.UnregisterNativeAsync();
            }
            catch (Exception e)
            {
                Insights.Report(e);
            }
        }

        public async Task RegisterNativeAsync(string deviceId)
        {
            try
            {
                CurrentDeviceId = deviceId;
                await _push.RegisterNativeAsync(deviceId);
            }
            catch (Exception e)
            {
                Insights.Report(e);
            }
        }
    }
}

Issue Analytics

  • State:open
  • Created 8 years ago
  • Reactions:1
  • Comments:38

github_iconTop GitHub Comments

2reactions
brminnickcommented, Feb 21, 2017

@lanceking @MKahmen I recommend creating your own implementation too, because the Push Notification Plugin doesn’t provide much added-value.

The Xamarin Evolve app implements Push for both iOS and Android and it’s what I reference when implementing push notifications now: https://github.com/xamarinhq/app-evolve

Read more comments on GitHub >

github_iconTop Results From Across the Web

Xamarin.Android push notification is breaking the app ...
Hi, I am trying to get push notifications when application is not running on background but not luck. Have you got notifications for...
Read more >
Xamarin Forms Android Push Notifications not received ...
The app will happily receive notifications when it is running in the foreground or background but when I try to send a notification...
Read more >
SOS! Xamarin Forms Push Notifications is driving me crazy ...
I am using the CrossGeeks Push Notification Plugin and Firebase Cloud Messaging. I am currently working on the Android App and have yet...
Read more >
Release Notes for Acoustic Mobile SDKs
Fixed issues with DisplayWeb and Calendar Plugin not working. Updated Inbox plugin to display the read status correctly and the inbox push notifications...
Read more >
Service | Android Developers
A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found