Firebase Push notifications not showing on Android 8.0+ when app is closed

FedericoCasabonaFedericoCasabona USMember ✭✭
edited February 8 in Xamarin.Android

Hello, good day.

I'm having a problem with push notifications on firebase.
On Android 7.0 or lower, it works perfectly.
On Android 8.0+, when the app is on Foreground, the notifications show normally. But, when it is on background or closed, the notifications don't show at all.
I create the notification channel, if not the notifications wouldn't show on foreground. Is there something else I am missing, like a foreground service? I am not really an expert on Android.

Here is my code for the MyFirebaseMessagingService:

[Service(Name = "com.company.firebase.MyFirebaseMessagingService", Exported=true)]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    [BroadcastReceiver(Enabled = true)]
    [IntentFilter(new[] { Intent.ActionBootCompleted })]
    public class MyFirebaseMessagingService : FirebaseMessagingService
    {
        const string TAG = "MyFirebaseMsgService";
        public override void OnMessageReceived(RemoteMessage message)
        {
                body = message.GetNotification().Body;
                title = message.GetNotification().Title;
                SendNotification(body, title, message.Data);

        }

        void SendNotification(string messageBody, string title, IDictionary<string, string> data)
        {
            var intent = new Intent(this, typeof(MainActivity));
            intent.AddFlags(ActivityFlags.ClearTop);
            foreach (var key in data.Keys)
            {
                intent.PutExtra(key, data[key]);
            }

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

            var notificationBuilder = new Notification.Builder(Application.Context, MainActivity.CHANNEL_ID)
                                      .SetSmallIcon(Resource.Drawable.icon)
                                      .SetContentTitle(title)
                                      .SetContentText(messageBody)
                                      .SetAutoCancel(true)
                                      .SetContentIntent(pendingIntent)
                                      .SetChannelId(MainActivity.CHANNEL_ID);

            var notificationManager = NotificationManagerCompat.From(this);
            notificationManager.Notify(MainActivity.NOTIFICATION_ID, notificationBuilder.Build());
        }
    }

Also, looking at the Device logs, I get this when getting a Notification with the App closed:

No Channel found for pkg=com.company.app, channelId=null, id=0, tag=GCM-Notification:2144077335, opPkg=com.company.app, callingUid=10294, userId=0, incomingUserId=0, notificationUid=10294, notification=Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE)
See the documentation of setSound() for what to use instead with android.media.AudioAttributes to qualify your playback use case
Use of stream types is deprecated for operations other than volume control
FirebaseMessaging   Unable to log event: analytics library is missing
FirebaseMessaging   java.lang.NumberFormatException: s == null
    at java.lang.Integer.parseInt(Integer.java:570)
    at java.lang.Integer.valueOf(Integer.java:794)
    at com.google.firebase.messaging.zzb.zzc(Unknown Source:60)
    at com.google.firebase.messaging.zzb.zzk(Unknown Source:2)
    at com.google.firebase.messaging.FirebaseMessagingService.zzn(Unknown Source:93)
    at com.google.firebase.messaging.FirebaseMessagingService.zzm(Unknown Source:66)
    at com.google.firebase.iid.zzb$2.run(Unknown Source:4)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
    at java.lang.Thread.run(Thread.java:764)
FirebaseMessaging   Error while parsing timestamp in GCM event

The "No Channel found for pkg=..." message really catch my eye because I do create the channel. When I searched the error all I got was "You must create a notification channel", but I already do. Is it destroyed when the app is closed or suspended?

I am really lost here. Any help would be appreciated.
Thanks.

Posts

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai
    edited February 9

    I do not see you creating a notification channel in the code above. See the Android docs: https://developer.android.com/training/notify-user/channels

    So you should have something like ( in Java):

    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
    

    Which ports closely to the following C#:

    if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
    {
        string channelID = "YourChannelID";
        string name = "YourChannelName";
        string description = "ChannelDescription";
        var importance = Android.App.NotificationImportance.Default;
    
        NotificationChannel channel = new NotificationChannel(channelID, name, importance);
        channel.Description = description;
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = (NotificationManager)GetSystemService("NotificationManager");
        notificationManager.CreateNotificationChannel(channel);
    }
    
  • FedericoCasabonaFedericoCasabona USMember ✭✭

    Hi @JGoldberger, thanks for your response.

    I create the Notification Channel on my Main Activity. I forgot to add the code:

     public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
        {
            static readonly string TAG = "MainActivity";
    
            internal static readonly string CHANNEL_ID = "MyChannel";
            internal static readonly int NOTIFICATION_ID = 100;
    
            protected override void OnCreate(Bundle bundle)
            {
            (...)
                if (IsPlayServicesAvailable())
                {
                    CreateNotificationChannel();
                    if (!string.IsNullOrEmpty(FirebaseInstanceId.Instance.Token))
                    {
                    SendTokenToServer(FirebaseInstanceId.Instance.Token);
                    }
                }
            }
    
            bool IsPlayServicesAvailable()
            {
                int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
                return resultCode == ConnectionResult.Success;
            }
    
            void CreateNotificationChannel()
            {
                if (Build.VERSION.SdkInt < BuildVersionCodes.O)
                {
                    // Notification channels are new in API 26 (and not a part of the
                    // support library). There is no need to create a notification
                    // channel on older versions of Android.
                    return;
                }
    
                var channel = new NotificationChannel(CHANNEL_ID,
                                                      "FCM Notifications",
                                                      NotificationImportance.Default)
                {
    
                    Description = "Firebase Cloud Messages appear in this channel"
                };
    
                var notificationManager = (NotificationManager)GetSystemService(Android.Content.Context.NotificationService);
                notificationManager.CreateNotificationChannel(channel);
            }
    
    

    Also, this is how I send the notifications in my server:

    private void SendPushNotification_FCM()
            {
                WebRequest tRequest = WebRequest.Create("ht tps:// fcm.googleapis.com /fcm /send");  //I can't post link on the forum.
                tRequest.Method = "POST";
                tRequest.Headers.Add("Authorization", string.Format("key={0}", GCMSenderKey));
                tRequest.Headers.Add("Sender", string.Format("id={0}", Sender));
                tRequest.ContentType = "application/json";
                var payload = new
                {
                    to = DeviceToken,
                    message_id = MessageId,
                    priority = "high",
                    content_available = true,
                    notification = new
                    {
                        body = Body,
                        title = Title,
                        badge = 1,
                        icon= "icon"
                    },
                };
    
                string postbody = JsonConvert.SerializeObject(payload).ToString();
                Byte[] byteArray = Encoding.UTF8.GetBytes(postbody);
                tRequest.ContentLength = byteArray.Length;
                using (Stream dataStream = tRequest.GetRequestStream())
                {
                    dataStream.Write(byteArray, 0, byteArray.Length);
                    using (WebResponse tResponse = tRequest.GetResponse())
                    {
                        using (Stream dataStreamResponse = tResponse.GetResponseStream())
                        {
                            if (dataStreamResponse != null) 
                    using (StreamReader tReader = new StreamReader(dataStreamResponse))
                                {
                                    String sResponseFromServer = tReader.ReadToEnd();
                                    if (sResponseFromServer.Contains("Unauthorized"))
                                    {
                                        LogInterface.Log(this, sResponseFromServer);
                                    }
                                    else if (sResponseFromServer.Contains("NotRegistered"))
                                    {
                                        DeviceTokenInvalidOrExpired(DeviceToken,long.Parse(ID), PushNotificationProvider.FCM);
                                    }
                                    else
                                    {
                                        _SentIDs.Add(long.Parse(ID));
                                    }
                                }
                        }
                    }
                }
            }
    
  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai

    That all looks good then.

    If you would like the MS Xamarin support team to dive deeper to help you, please open a free Xamarin email support case. You can open a free Xamarin support case here: https://support.microsoft.com/en-us/getsupport?wf=0&tenant=classiccommercial&oaspworkflow=start_1.0.0.0&locale=en-us&supportregion=en-us&pesid=16068&forceorigin=esmc&ccsid=636645150473349054

  • FedericoCasabonaFedericoCasabona USMember ✭✭

    @JGoldberger, Thanks for your response.

    I solved the issue by sending data-only payloads from my server instead of notifications:

                var payload = new
                {
                    to = DeviceToken,
                    message_id = MessageId,
                    priority = "high",
                    content_available = true,
                    data = new
                    {
                        body = Body,
                        title = Title,
                        badge = 1,
                        icon = "icon",
                        android_channel_id = "channel_id"
                    }
                };
    

    Then, in MyFirebaseMessagingService, I edited the OnMessageReceived method:

            public override void OnMessageReceived(RemoteMessage message)
            {
                var notification = message.GetNotification();
                var data = message.Data;
                string body = "";
                string title = "";
                if (data != null && data.ContainsKey("body") && data.ContainsKey("title"))
                {
                    body = data["body"];
                    title = data["title"];
                }
                else if (notification != null)
                {
                    body = message.GetNotification().Body;
                    title = message.GetNotification().Title;
                }
    
                if(!string.IsNullOrEmpty(body) && !string.IsNullOrEmpty(title))
                    SendNotification(body, title, message.Data);
    
            }
    

    It's working perfectly now.

Sign In or Register to comment.