Service not starting to sendRegistrationToServer while implementing Xamarin.Forms Push Notifications

AliRaza.5445AliRaza.5445 PKMember ✭✭✭

Hello guys,
I am implementing push notifications in a xamarin.forms application. iOS part works fine. I can send and receive notifications with it. But for Android, I can send notifications via an API backend but can not receive notifications. Reason is that device is not getting registered with Firebase cloud messaging. I placed degubber and came to know that method inside **MyFirebaseIIDService **that registers device with FCM never gets called. I am pasting below code for my main Activity and Android Manifest. Please have a look and suggest some solutions. Thanks

MainActivity:

using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Xamarin.Forms;
using Firebase.Messaging;
using System.Diagnostics;
using Firebase.Iid;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using Android.Gms.Common;
using Newtonsoft.Json.Linq;
using static Android.Manifest;

namespace Push.Droid
{
    [Activity(Label = "Push", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App());

            IsPlayServicesAvailable();

#if DEBUG
            // Force refresh of the token. If we redeploy the app, no new token will be sent but the old one will
            // be invalid.
            Task.Run(() =>
            {
                // This may not be executed on the main thread.
                FirebaseInstanceId.Instance.DeleteInstanceId();
                Console.WriteLine("Forced token: " + FirebaseInstanceId.Instance.Token);
            });
#endif
        }

        public bool IsPlayServicesAvailable()
        {
            int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
            if (resultCode != ConnectionResult.Success)
            {
                if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
                {
                    // In a real project you can give the user a chance to fix the issue.
                    Console.WriteLine($"Error: {GoogleApiAvailability.Instance.GetErrorString(resultCode)}");
                }
                else
                {
                    Console.WriteLine("Error: Play services not supported!");
                    Finish();
                }
                return false;
            }
            else
            {
                Console.WriteLine("Play Services available.");
                return true;
            }
        }
    }

    // This service handles the device's registration with FCM.
    [Service]
    [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
    public class MyFirebaseIIDService : FirebaseInstanceIdService
    {
        public override void OnTokenRefresh()
        {
            var refreshedToken = FirebaseInstanceId.Instance.Token;
            Console.WriteLine($"Token received: {refreshedToken}");
            SendRegistrationToServerAsync(refreshedToken);
        }

        async Task SendRegistrationToServerAsync(string token)
        {
            try
            {
                // Formats: https://firebase.google.com/docs/cloud-messaging/concept-options
                // The "notification" format will automatically displayed in the notification center if the 
                // app is not in the foreground.
                const string templateBodyFCM =
                    "{" +
                        "\"notification\" : {" +
                        "\"body\" : \"$(messageParam)\"," +
                          "\"title\" : \"Xamarin University\"," +
                        "\"icon\" : \"myicon\" }" +
                    "}";

                var templates = new JObject();
                templates["genericMessage"] = new JObject
                {
                    {"body", templateBodyFCM}
                };

                var client = new MobileServiceClient(Push.App.MobileServiceUrl);
                var push = client.GetPush();

                await push.RegisterAsync(token, templates);

                // Push object contains installation ID afterwards.
                Console.WriteLine(push.InstallationId.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Debugger.Break();
            }
        }
    }

    // This service is used if app is in the foreground and a message is received.
    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]

    public class MyFirebaseMessagingService : FirebaseMessagingService
    {
        public override void OnMessageReceived(RemoteMessage message)
        {
            base.OnMessageReceived(message);

            Console.WriteLine("Received: " + message);

            // Android supports different message payloads. To use the code below it must be something like this (you can paste this into Azure test send window):
            // {
            //   "notification" : {
            //      "body" : "The body",
            //                 "title" : "The title",
            //                 "icon" : "myicon
            //   }
            // }
            try
            {
                var msg = message.GetNotification().Body;
                MessagingCenter.Send<object, string>(this, Push.App.NotificationReceivedKey, msg);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error extracting message: " + ex);
            }
        }
    }
}

AndroidManifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.xamarin.xamarinnotif" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="15" />
    <application android:label="Push">
    <receiver android:name="com.google.android.gms.gcm.GcmReceiver"
              android:exported="true"

              android:permission="com.google.android.c2dm.permission.SEND">
      <service android:enabled="true" android:name="com.xamarin.xamarinnotif.Push.Droid" />

      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="com.xamarin.xamarinnotif" />
      </intent-filter>
    </receiver>

  </application>
  <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />
  <uses-permission android:name="android.permission.INTERNET" />
  <permission android:name="com.xamarin.xamarinnotif.permission.C2D_MESSAGE" android:protectionLevel="signature" />
  <uses-permission android:name="com.xamarin.xamarinnotif.permission.C2D_MESSAGE" />
</manifest>

Answers

  • KimJensenKimJensen USMember ✭✭

    I had the same problem when I was running in debug, but if I create an APK and install it on the Android device then I was able to get notification to work.

  • @AliRaza.5445
    Can you help me on IOS part as i want the same thing to implement on my app.

  • ponsinghponsingh Member ✭✭

    Just Rebuild your Android project.Its working

Sign In or Register to comment.