Firebase ile Push Notification İşlemleri

Merhabalar,

En popüler push notification servisleri ile Xamarin entegrasyonunu gerçekleştirmiştik ama direkt Firebase kullanımını hep atladık. Bunun en büyük sebebi aracı servislerin çok kolay entegre edilmesi ve zengin özellikli olmasıydı. Fakat geldiğimiz noktada en popüler pn servislerinden biri olan AppCenter, push notification servisini kapattı, OneSignal entegrasyonu ise gereksiz efor ve bence OneSignal iOS entegrasyonu işkence seviyesinde.

Olayın hikaye kısmını geçip hızlı bir şekilde firebase console ayarlarımızı yapıp, kodlarımızı yazalım.

Vitamini Çekirdeğinde

https://console.firebase.google.com adresine gidip yeni bir proje oluşturalım.

Kullanacağımız plugin : Firebase Push Notification Plugin for Xamarin iOS and Android

Android

AndroidManifest içerisinde application tagleri arasına,

    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="com.firebase.xamocan" />
      </intent-filter>
    </receiver>

Firebase console üzerindeki Cloud messaging sekmesinden Android uygulamamızı ekleyelim

Paket ve uygulama adını girdikten sonra google-services.json dosyasını Android projenizin içine ekleyerek gerekli ayarların buradan okunacağını gösterebilirsiniz fakat ben genelde bunu direkt kullandığımız yardımcı plugin aracılığıyla yapıyorum.

MainApplication.cs

[Application]
    public class MainApplication : Application, Application.IActivityLifecycleCallbacks
    {
        public MainApplication(IntPtr handle, JniHandleOwnership transer) : base(handle, transer)
        {

        }

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

            RegisterActivityLifecycleCallbacks(this);

            var options = new FirebaseOptions.Builder()
                  .SetApplicationId("1:631842******************")
                  .SetApiKey("AIza*********************")
                  .SetDatabaseUrl("https://xamo*******firebaseio.com")
                  .SetStorageBucket("xamo********appspot.com")
                  .SetGcmSenderId("6318**********").Build();
            var fapp = FirebaseApp.InitializeApp(this, options);

            if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
            {
                FirebasePushNotificationManager.DefaultNotificationChannelId = "DefaultChannel";
                FirebasePushNotificationManager.DefaultNotificationChannelName = "General";
            }


#if DEBUG
            FirebasePushNotificationManager.Initialize(this, new NotificationUserCategory[]
            {
            new NotificationUserCategory("message",new List<NotificationUserAction> {
                new NotificationUserAction("Reply","Reply",NotificationActionType.Foreground),
                new NotificationUserAction("Forward","Forward",NotificationActionType.Foreground)

            }),
            new NotificationUserCategory("request",new List<NotificationUserAction> {
                new NotificationUserAction("Accept","Accept",NotificationActionType.Default,"check"),
                new NotificationUserAction("Reject","Reject",NotificationActionType.Default,"cancel")
            })

            }, true);
#else
	            FirebasePushNotificationManager.Initialize(this,new NotificationUserCategory[]
		    {
			new NotificationUserCategory("message",new List<NotificationUserAction> {
			    new NotificationUserAction("Reply","Reply",NotificationActionType.Foreground),
			    new NotificationUserAction("Forward","Forward",NotificationActionType.Foreground)

			}),
			new NotificationUserCategory("request",new List<NotificationUserAction> {
			    new NotificationUserAction("Accept","Accept",NotificationActionType.Default,"check"),
			    new NotificationUserAction("Reject","Reject",NotificationActionType.Default,"cancel")
			})

		    }, false);
#endif

            //CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
            //{
            //    System.Diagnostics.Debug.WriteLine("NOTIFICATION RECEIVED", p.Data);
            //};
        }

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

        public void 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)
        {
        }
    }

CurrentActivity plugin’i de yüklemeyi unutmayalım : Plugin.CurrentActivity

FirebaseOptions.Builder() için gerekli bilgileri indirdiğiniz .json dosyasında bulabilirsiniz.

MainActivity.cs

protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
            FirebasePushNotificationManager.NotificationActivityType = typeof(MainActivity);
            FirebasePushNotificationManager.NotificationActivityFlags = ActivityFlags.SingleTop;
            FirebasePushNotificationManager.DefaultNotificationChannelImportance = NotificationImportance.Min;
            FirebasePushNotificationManager.ProcessIntent(this, Intent);
        }


FirebaseRegistrar.cs

public class FirebaseRegistrar
    {
        public static void FirebaseInit()
        {
            CrossFirebasePushNotification.Current.OnTokenRefresh += (s, p) =>
            {
                System.Diagnostics.Debug.WriteLine($"TOKEN REC: {p.Token}");
                CrossFirebasePushNotification.Current.Subscribe("general");
            };

            CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
            {
            };

            CrossFirebasePushNotification.Current.OnNotificationOpened += (s, p) =>
            {
            };


            CrossFirebasePushNotification.Current.OnNotificationAction += (s, p) =>
            {
                System.Diagnostics.Debug.WriteLine("Action");
                if (!string.IsNullOrEmpty(p.Identifier))
                {
                    System.Diagnostics.Debug.WriteLine($"ActionId: {p.Identifier}");
                    foreach (var data in p.Data)
                    {
                        System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
                    }
                }
            };

            CrossFirebasePushNotification.Current.OnNotificationDeleted += (s, p) =>
            {
                System.Diagnostics.Debug.WriteLine("Dismissed");
            };
        }
    }
  • Tek bir kullanıcıya bildirim göndermek istiyorsanız OnTokenRefresh eventinin size verdiği token özelliğini kullanmanız gerekiyor.
  • Belirli bir tag içerisindeki kullanıcılara bildirim göndermek istiyorsanız CrossFirebasePushNotification.Current.Subscribe(“general”); methoduna kullanarak kullanıcıları tagleyebilirsiniz. Örnek olması açısından doğum yerine göre tagleme yapabilirsiniz.
    CrossFirebasePushNotification.Current.Subscribe(“Mersin”);
    CrossFirebasePushNotification.Current.Subscribe(“Adana”);

İlk testi yapalım

FirebaseRegistrar sınıfı sayesinde zaten tüm yardımcı eventlere sahibiz. Yardımcı sınıfımız zaten shared katmanda olduğu için iOS ve Android özelinde bir geliştirme yapmamıza da gerek yok.

iOS

AppDelegate.cs

LoadApplication(new App()); methodunun hemen altına;

FirebasePushNotificationManager.Initialize(options, new NotificationUserCategory[]
            {
                    new NotificationUserCategory("message",new List<NotificationUserAction> {
                        new NotificationUserAction("Reply","Reply",NotificationActionType.Foreground)
                    }),
                    new NotificationUserCategory("request",new List<NotificationUserAction> {
                        new NotificationUserAction("Accept","Accept"),
                        new NotificationUserAction("Reject","Reject",NotificationActionType.Destructive)
                    })

            });

            FirebasePushNotificationManager.CurrentNotificationPresentationOption = 
                UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Badge | UNNotificationPresentationOptions.Sound;

İndirdiğimiz GoogleService-Info.plist dosyasını bu sefer iOS projemizin içine atıp Build Action kısmını BundleResource olarak seçelim.

info.plist içerisinden background işlemlerinden remote notifications seçeneğini açmalıyız.

Firebase console üzerinde yapmamız gereken çok ufak bir işlem kaldı o da .p12 dosyasını oluşturup yüklemek.

.p12 dosyası oluşturmayı bilmeyenler linkteki videonun ilk 25 dakikasını izlesinler.

Postman üzerinden denemek isterseniz
https://fcm.googleapis.com/fcm/send adresini kullanabilirsiniz. Header kısmın’a Authorization eklemeyi unutmayın.

{
  "to": "/topics/Adana",
  "notification": {
    "title": "Adana İle İlgili Sözler",
    "body": "Nerelisin dedikleri zaman Adanalıyık deriz",
    "sound": "default",
    "content_available" : true
  }
}

Takıldığınız yerler olursa yorum olarak sorabilirsiniz.

Yiğit

Xamarin Developer, Consultant & Architect. Community Leader and Director of Xamarin Türkiye

21 Comments

You can post comments in this post.


  • Hocam merhaba , xamarin ile push notification göndermek istiyorum ama Firebase Admin SDK dışında XMPP protocolü ile cihazdan cihaza upstream message göndermek istiyorum.Xamarinde yeniyim ve yaklaşık 2 haftadır araştırma yapıyorum . Android studio da smack library kullanarak ve php server ile yapan bi arkadaş gördüm ama ben xamarin ve web service kullanarak yapmak istiyorum . Xamarinde yeni olduğum için mimariyi kafamda oturtamadım yardımcı olabilme şansınız var mı ?

    Ali Akçekoce 4 sene ago Reply


    • Bu islem icin direkt SignalR kullanman daha guzel olabilir 🙂

      Yiğit 4 sene ago Reply


  • cihaza özel token i nasıl okuyacağız?
    hangi dosyalar hangi katmanda olacak, yardımcı olabilir misiniz?

    HuseyinCelik 3 sene ago Reply


    • FirebaseRegistrar classi icerisindeki CrossFirebasePushNotification.Current.OnTokenRefresh event’i sana yardimci olacaktir 🙂

      Yiğit 3 sene ago Reply


  • Merhabalar,
    acaba yapılan örnek projeyi paylaşabilmeniz mümkün mü?

    Muhammet Deregözü 3 sene ago Reply


    • Selam,
      Ilgili yaziyi adim-adim takip ederseniz sorunsuz bir sekilde entegrasyonu yapabilirsiniz. Maalesef kodlari paylasmamisim github uzerinde.

      Yiğit 3 sene ago Reply


  • Android için bütün adımları izliyorum fakat bildirim yolladığım zaman FirebaseRegistrar’a düşmüyor. Gördüğüm tek fark google.json’da DatabaseUrl yok. Json entegrasyon kısmını farklı bir şekilde entegre edebilir miyiz?

    Kagan 3 sene ago Reply


    • MainApplication.cs kısmındaki gibi de ekleyebilirsiniz.

      Yiğit 3 sene ago Reply


  • Push atarken örnek veriyorum 20.000 kişi veya üzeri kişiye push atmaya çalıştığımda limit’e takılıyorum. Firebase’de böyle bir limit kısıtlaması var mıdır ? Varsa eğer, çözümü varsa nedir ?

    Ahmet Selçuk 3 sene ago Reply


  • web.api veya service ile nasıl bildirim gönderebiliriz.

    SAİM HASANUSTA 3 sene ago Reply


  • Hocam merhaba,
    Birden fazla projeye (farklı packagename sahip) eş zamanlı olarak bildirim gönderebilmek mümkün mü? Packagename değiştiğiştirdiğimiz de hata almaktayız.

    Hamza Duman 3 sene ago Reply


    • Projenizin packagename’i firebase icerisinde actiginiz projeniz ile eslestiriliyor. Bu yuzden hata vermesi normal 🙂

      Yiğit 3 sene ago Reply


  • Merhabalar,

    Tüm adımları gerçekleştirdim. Fakat loglarda başarılı görünmesine rağmen CrossFirebasePushNotification.Current.OnTokenRefresh metoduna düşmedi. Nereye bakmam gerek?

    [FirebaseApp] Device unlocked: initializing all Firebase APIs for app [DEFAULT]
    [FirebaseInitProvider] FirebaseApp initialization successful

    Zafer Uygur 3 sene ago Reply


  • Hocam Mobil tarafta gelen Key Value Datalarımızı yakalıyoruz. Peki diğer taraftan hidden birşey Id gibi göndermek istersek ne yapmalıyız

    Ahmet Talha Şahin 2 sene ago Reply


  • Hocam Notification’ı pushlarken title ve body gönderdiğimiz gibi hidden bir değer nasıl gönderebilirim

    Ahmet Talha Şahin 2 sene ago Reply


  • Proje nereden başlıyor. Eklenen sınıfları tetikleme işlemi nasıl yapılıyor. Onları da buraya ekleseydiniz iyi olurdu. Projenin içerisine dediğiniz sınıfları ekledik. Bildirim gönderiyoruz. Hiç bir yere etkileşimde olduğu yok. Projenin dosyalarının olduğu resmi ekleseydiniz en sona hiç olmazsa oradan anlaşılırdı

    MURAT GÜLER 2 sene ago Reply


    • Yapılan işlemler ve tüm kodlar post içerisinde paylaşıldı. Eksik olan bir durum yok. Post paylaşılalı neredeyse iki yıl olacak 🙂 Paketlerde veya Firebase ayarlarında farklılıklar oluşmuş olabilir.

      Yiğit 2 sene ago Reply


      • FirebaseInit methoduna nereden başvuru yapılıyor? Çok fazla eksi bilgi var…

        Mehmet 2 sene ago Reply


  • Zaten yazdığınnız kodlar çok kısa bu yazdıklarınızı github’a atsanız bundan sonra faydalanacak olanlar içinde çok iyi olur.

    MURAT GÜLER 2 sene ago Reply


Post A Reply