1

I used these instructions to add Azure Notification Hub FCM-based Remote Notifications to my Xamarin.Forms Android app.

https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-xamarin-forms-get-started-push

I can receive Remote Notifications when the app is open or running in the background, but when I close the application or stop the application I no longer receive Remote Notifications.

My test device is running API level 22, so I'm using the following method to to build the notification on the device.

Android.Support.V4.App.NotificationCompat.Builder builder = new Android.Support.V4.App.NotificationCompat.Builder(this)

For API level 26+, I'm using the follow method along with a channel to build the notification on the device.

var builder = new Android.App.Notification.Builder(this)

I'm thinking that I have to use a BroadcastReceiver to achieve this, but I really have no idea after reading so many comments on this subject. My app is compiled using API 27 and targets API 27.

Method 1

I'm trying to create a BroadcastReceiver that will launch MyService using an Explicit Intent when a Notification arrives. Unfortunately, this does not work on my API Level 22 test device.

//[BroadcastReceiver]
//[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
[BroadcastReceiver(Enabled = true, Exported = true)]
    [IntentFilter(new[] { "com.xamarin.example.TEST" })]
    public class MyBroadcastReceiver : BroadcastReceiver
    {

        public override void OnReceive(Context context, Intent intent)
        {
            string message = intent.GetStringExtra("message");
            string title = intent.GetStringExtra("title");
            string id = intent.GetStringExtra("id");

            //Explicit Intent to launch MyService
            Intent intent2 = new Intent(Application.Context, typeof(MyService));
            intent2.PutExtra("message", message);
            intent2.PutExtra("title", title);
            intent2.PutExtra("id", id);

            Application.Context.StartService(intent2);
        }

     }


// Service is exported and given a name so other applications can use it
    [Service(Exported = true, Name = "com.mycompany.myapp.MyService")]
    // Intent filter only needed for Implicit Intents
    //[IntentFilter(new string[] { "com.xamarin.example.TEST" })]
    public class MyService : Service
    {

        public static string PRIMARY_NOTIF_CHANNEL = "default";

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

        [return: GeneratedEnum]
        public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
        {
            var pm = PowerManager.FromContext(this);
            var wakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "Notification");
            wakeLock.Acquire();

            string message = intent.GetStringExtra("message");
            string title = intent.GetStringExtra("title");
            string id = intent.GetStringExtra("id");

            var intent2 = new Intent(this, typeof(MainActivity));
            intent2.PutExtra("id", id);
            intent2.AddFlags(ActivityFlags.ClearTop);

            var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);

            NotificationManager notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);

            Android.Support.V4.App.NotificationCompat.Builder builder = new Android.Support.V4.App.NotificationCompat.Builder(this)
                   .SetAutoCancel(true)
                   .SetContentIntent(pendingIntent)
                   .SetContentTitle(title)
                   .SetContentText(message)
                   .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification))
                   .SetVibrate(new long[1])
                   //1 is Hi
                   .SetPriority(1)
                   .SetLargeIcon(BitmapFactory.DecodeResource(Resources, SalesFlash.Droid.Resource.Drawable.Icon_lg))
                   .SetSmallIcon(MyApp.Droid.Resource.Drawable.icon)
                   .SetChannelId(PRIMARY_NOTIF_CHANNEL);

            notificationManager = NotificationManager.FromContext(this);
            notificationManager.Notify(0, builder.Build());

            wakeLock.Release();

            //return StartCommandResult.Sticky;

            return base.OnStartCommand(intent, flags, startId);
        }

        public override void OnDestroy()
        {
            base.OnDestroy();
        }
    }

According to this post, a BroadCastReceiver won't work for FCM Notifications. https://stackoverflow.com/a/44287962/5360237

This post seems to show a BroadcastReceiver accepting a Notification. https://stackoverflow.com/a/45616014/5360237

Any help is much appreciated. Thanks in advance!

Dumber_Texan2
  • 840
  • 2
  • 12
  • 34
  • Check this out :https://stackoverflow.com/q/47826887/7462031 – FreakyAli Aug 28 '18 at 08:13
  • @G.hakim Thanks for the comment. Are you suggesting that the following code snippet placed in the OnCreate method of the MainActivity will allow the app to receive Notifications when it is closed, stopped or not running? if (Intent.Extras != null) {foreach (var key in Intent.Extras.KeySet()) { var value = Intent.Extras.GetString(key)} } If so, this did not work for me. From what I've read, I need to either create a BroadcastReceiver, a StartService or use the Firebase Job Dispatcher to handle Notifications when the app is closed. – Dumber_Texan2 Aug 28 '18 at 14:58
  • You need to do nothing of such sort if you receive a push from firebase android by default sends a push you just have to handle it when you open the app – FreakyAli Aug 28 '18 at 18:41
  • @G.hakim As indicated in my original post, I can receive Notifications when my app is in the foreground and background. When the app is stopped, closed on not running is what I'm having problems with. Do you know how to handle the Notification on a device that seems to have stopped the FirebaseMessagingService when the app is closed? – Dumber_Texan2 Sep 06 '18 at 19:00
  • Even when the app is closed firebase manages it you don't have to write any extra code of any sort – FreakyAli Sep 07 '18 at 14:09
  • @G.hakim I've been working with Microsoft on this and they found a great post that explains the problem. It also provides a manual fix for the affected devices. Here is a link to the post. https://medium.freecodecamp.org/why-your-push-notifications-never-see-the-light-of-day-3fa297520793 I was able to get it working on my Alcatel One Touch Pop by navigating to Settings - Apps and then swiping over to the Restricted tab. From here, I was able to uncheck my app. – Dumber_Texan2 Sep 07 '18 at 23:09
  • So now its working fine is what you are telling me right? – FreakyAli Sep 08 '18 at 12:22
  • @G.hakim Yes, it works on my device because I had to manually remove the Restriction. This problem affects many Android devices, which is why a lot of Android users never receive Notifications. The link contains a list of manufactures. It would be great to develop a service that could automatically remove the Restriction. – Dumber_Texan2 Sep 09 '18 at 19:22
  • Quite honestly what you are saying here is not making sense to me why dont you update your question a little – FreakyAli Sep 10 '18 at 06:33

1 Answers1

0

Here is the best post that I've read that explains the problem. It also provides a manual solution for the affected devices. https://medium.freecodecamp.org/why-your-push-notifications-never-see-the-light-of-day-3fa297520793 I was able to get Notifications working (when app is closed, stopped or not running) on my Alcatel One Touch Pop by navigating to Settings - Apps and then swiping over to the Restricted tab. From here, I was able to uncheck my app.

NOTE: Messages are delivered to my Android app using the data payload. Even though I was receiving Notifications in the foreground and background, I went ahead and added the following permission to my AndroidManifest.

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  

This permission is used for Auto Start. I also used Azure App Center to distribute a signed APK to my test device. Hope this helps someone else.

UPDATE: I removed the RECEIVE_BOOT_COMPLETE permission and did a Debug Build. I closed the app out of Debug (connected to Visual Studio) by swiping it off the screen. I then sent a Notification and it did not display. I then re-opened the app (not being debugged by Visual Studio) and closed it by swiping it off the screen, sent a Notification and it worked. So, it had nothing to with the RECEIVE_BOOT_COMPLETE permission and it doesn't have to be a Release version / signed APK.

Dumber_Texan2
  • 840
  • 2
  • 12
  • 34