如何在带有Firebase的Xamarin和带有C#后端的Apple Push Notification中实现推送通知 [英] How to implement Push Notification in Xamarin with Firebase and Apple Push Notification with C# backend

本文介绍了如何在带有Firebase的Xamarin和带有C#后端的Apple Push Notification中实现推送通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在从本机Android和iOS迁移到Xamarin.Forms的过程中,我决定使用AppCenter Push进行通知,因为它既免费又易于使用(当然,自从这是相对较新的内容,在线指导较少).您可以在如何实现AppCenter Push API中找到我的原始共享内容..

我对它感到满意,直到微软宣布它将淘汰AppCenter Push( https://devblogs.microsoft.com/appcenter/app-center-mbaas-retirement/),并鼓励用户转移到Azure(这是一项付费服务​​).我决定回过头来使用本机FCM和APN进行推送通知.

问题是没有关于如何完成整个操作的直接教程.有问题&当我的项目在不支持的.Net Framework上运行时,此处和此处的解决方案(如iOS .P8)仅适用于HTTP/2.只有.Net Core可以使用HTTP/2协议.

解决方案

我当前的项目在ASP.NET C#上作为后端运行,该后端使用Xamarin.Forms将通知发送到Xamarin.Android和Xamarin.iOS.如果您像我一样,请在下面找到我的答案,我在下面共享可正常使用的C#后端和Xamarin.Forms解决方案.这样一来,更多的用户就可以从免费服务中受益,而不是被推送到Azure付费服务.

PART 1 C#后端-C#ASP.NET后端.对于FCM和APN,它将分为2部分.

1.1)Firebase(FCM)

  1. 要设置FCM,您需要注册一个帐户.在线有大量指南,这是很好的指南之一 https://xmonkeys360.com/2019/12/08/xamarin-forms-fcm-setup-configuration-part-i/.请记住获取服务器密钥,并将 google-services.json 文件下载到您的Xamarin.Android项目中.右键单击并将构建操作设置为" GoogleServiceJson " (我在哪里可以在xamarin中添加google-services.json应用).

  2. 下面是我的Firebase

    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Web.Script.Serialization;
    
    namespace PushNotificationLibrary
    {
        public class FirebaseCloudMessagingPush
        {
            private const string WEB_ADDRESS = "https://fcm.googleapis.com/fcm/send";
    
            private const string SENDER_ID = "YOUR SENDER ID";
            private const string SERVER_KEY = "YOUR SERVER KEY";
    
            public string SendNotification(string deviceToken, string title, string message, string priority = "high", int badge = 0, List<Tuple<string, string>> parameters = null)
            {
                var result = "-1";
                var httpWebRequest = (HttpWebRequest)WebRequest.Create(WEB_ADDRESS);
    
                parameters = parameters ?? new List<Tuple<string, string>>();
    
                httpWebRequest.ContentType = "application/json";
                httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", SERVER_KEY));
                httpWebRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
                httpWebRequest.Method = "POST";
    
                if (title.Length > 100)
                    title = title.Substring(0, 95) + "...";
    
                //Message cannot exceed 100
                if (message.Length > 100)
                    message = message.Substring(0, 95) + "...";
    
                JObject jObject = new JObject();
                jObject.Add("to", deviceToken);
                jObject.Add("priority", priority);
                jObject.Add("content_available", true);
    
                JObject jObjNotification = new JObject();
                jObjNotification.Add("body", message);
                jObjNotification.Add("title", title);            
    
                jObject.Add("notification", jObjNotification);
    
                JObject jObjData = new JObject();
    
                jObjData.Add("badge", badge);
                jObjData.Add("body", message);
                jObjData.Add("title", title);
    
                foreach (Tuple<string, string> parameter in parameters)
                {
                    jObjData.Add(parameter.Item1, parameter.Item2);
                }
    
                jObject.Add("data", jObjData);
    
                var serializer = new JavaScriptSerializer();
                using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                    string json = jObject.ToString();
                    streamWriter.Write(json);
                    streamWriter.Flush();
                }
    
                var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    result = streamReader.ReadToEnd();
                }
    
                return result;
            }
        }
    }
    

1.2)iOS(APN)

  1. 对于APN,有两种处理方式.一种是使用.P12常规方式.另一种方法是使用.P8使用Apple Auth Key.我更喜欢使用.P8,因为 .P12证书每年到期,并且需要每年更新.使用.P8的问题在于,它使用的是HTTP/2,而.Net Framework不支持该HTTP/2,但值得庆幸的是,我设法克服了这一点.请参阅如何在C#中实现基于Apple令牌的推送通知(使用p8文件)?,在那篇文章中找到我的答案,以了解如何为.Net Framework实施整件事. * 如果您已经在使用.Net Core,答案将与我的类似,但是您不必使用自定义WinHTTPHandler.只需普通的HTTPClient即可.

PART 2 Xamarin.Forms -接下来,您必须在Xamarin.Forms项目中支持该通知.

  1. 对于这部分,这一点都不困难.您所要做的就是参考 https://github.com/CrossGeeks/PushNotificationPlugin ,下载Nuget并按照链接中的说明进行操作以设置Xamarin项目(Forms,Android,iOS).

  2. 我唯一要强调的是&在何处获取设备令牌.最初,我试图在下面的代码(OnTokenRefresh)上获取设备令牌.但是您很快就会注意到,此代码并不总是会被调用,我怀疑只有在刷新令牌后才会调用该代码,而不是在每次调试时才调用.为了每次获取设备令牌,只需在项目中的任何地方调用CrossPushNotification.Current.Token.将该设备令牌注册到您的服务器后端.并使用设备令牌通过我在上面第1部分中的代码发送通知.

    CrossPushNotification.Current.OnTokenRefresh += (s,p) =>
    {
        System.Diagnostics.Debug.WriteLine($"TOKEN : {p.Token}");
    };
    

就是这样!这很容易,但是我花了数周的时间尝试并出错,然后再将它们拼凑在一起.希望它可以节省与他人的宝贵时间.

During my migration from Native Android and iOS to Xamarin.Forms, I had decided to use AppCenter Push for my notification, since it is free and easy to use (of course I spent a good amount of time to make it works since it's relatively new thing with less guidance online). You can find my original sharing at How to implement AppCenter Push API?.

I was happy with it until Microsoft announced that it is retiring AppCenter Push (https://devblogs.microsoft.com/appcenter/app-center-mbaas-retirement/) and encouraged user to move over to Azure (which is a paid service). I decided to move back to use the native FCM and APN for my push notification.

The problem is there is no direct tutorials on how to do the entire thing. There are problems & solutions here and there such as iOS .P8 only works on HTTP/2 while my project is running on .Net Framework which is not supported. Only .Net Core could HTTP/2 protocol.

解决方案

My current project runs on ASP.NET C# as the backend, which send notification to Xamarin.Android and Xamarin.iOS using Xamarin.Forms. If you're like me, please find my answer below, I am sharing the fully working C# backend and Xamarin.Forms solution below. So that more user can benefit from FREE service instead of being pushed to Azure paid service.

PART 1 C# Backend - The C# ASP.NET backend. It will be split to 2 parts, for FCM and APNs.

1.1) Firebase (FCM)

  1. To setup FCM, you'll need to register an account. There are tonnes of guideline online, this is one of the good one https://xmonkeys360.com/2019/12/08/xamarin-forms-fcm-setup-configuration-part-i/. Remember to get the Server Key and download the google-services.json file to your Xamarin.Android project. Right-click and set the build action to "GoogleServiceJson" (Where can i add google-services.json in xamarin app).

  2. Below is my Firebase

    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Web.Script.Serialization;
    
    namespace PushNotificationLibrary
    {
        public class FirebaseCloudMessagingPush
        {
            private const string WEB_ADDRESS = "https://fcm.googleapis.com/fcm/send";
    
            private const string SENDER_ID = "YOUR SENDER ID";
            private const string SERVER_KEY = "YOUR SERVER KEY";
    
            public string SendNotification(string deviceToken, string title, string message, string priority = "high", int badge = 0, List<Tuple<string, string>> parameters = null)
            {
                var result = "-1";
                var httpWebRequest = (HttpWebRequest)WebRequest.Create(WEB_ADDRESS);
    
                parameters = parameters ?? new List<Tuple<string, string>>();
    
                httpWebRequest.ContentType = "application/json";
                httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", SERVER_KEY));
                httpWebRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
                httpWebRequest.Method = "POST";
    
                if (title.Length > 100)
                    title = title.Substring(0, 95) + "...";
    
                //Message cannot exceed 100
                if (message.Length > 100)
                    message = message.Substring(0, 95) + "...";
    
                JObject jObject = new JObject();
                jObject.Add("to", deviceToken);
                jObject.Add("priority", priority);
                jObject.Add("content_available", true);
    
                JObject jObjNotification = new JObject();
                jObjNotification.Add("body", message);
                jObjNotification.Add("title", title);            
    
                jObject.Add("notification", jObjNotification);
    
                JObject jObjData = new JObject();
    
                jObjData.Add("badge", badge);
                jObjData.Add("body", message);
                jObjData.Add("title", title);
    
                foreach (Tuple<string, string> parameter in parameters)
                {
                    jObjData.Add(parameter.Item1, parameter.Item2);
                }
    
                jObject.Add("data", jObjData);
    
                var serializer = new JavaScriptSerializer();
                using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                    string json = jObject.ToString();
                    streamWriter.Write(json);
                    streamWriter.Flush();
                }
    
                var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    result = streamReader.ReadToEnd();
                }
    
                return result;
            }
        }
    }
    

1.2) iOS (APNs)

  1. For APNs, there are 2 ways of doing things. One is using .P12 conventional way. Another way is to use Apple Auth Keys using .P8. I prefer to use .P8 because .P12 cert expiry every year and need to update annually. The problem with using .P8 is that, it's using HTTP/2 which is not supported in .Net Framework but thankfully, I managed to overcome that. Please refer to How to implement apple token based push notifications (using p8 file) in C#?, find my Answer on that post on how to implement the whole thing for .Net Framework. *IF you're already using .Net Core, the answer will be similar to mine, but you do not have to use the custom WinHTTPHandler. Just the normal HTTPClient will do.

PART 2 Xamarin.Forms - Next, you'll have to support the notification in your Xamarin.Forms project.

  1. For this part, it's not very difficult at all. All you have to do is refer to https://github.com/CrossGeeks/PushNotificationPlugin, download the Nuget and follow the instructions in the link to setup for your Xamarin projects (Forms, Android, iOS).

  2. The only thing that I wish to highlight is how & where to get your device token. Initially I was trying to get the device token at the code below (OnTokenRefresh). But you'll soon to notice that this code doesn't always get called, I suspect it will only get called once the token is refreshed, and not every time when you debug. In order to obtain your Device Token every time, just call CrossPushNotification.Current.Token anywhere in your project. Register that device token to your server backend. And use the device token to send the notification using my code at PART 1 above.

    CrossPushNotification.Current.OnTokenRefresh += (s,p) =>
    {
        System.Diagnostics.Debug.WriteLine($"TOKEN : {p.Token}");
    };
    

That's it! It's pretty easy, but I spent weeks to try and error before piecing them together. Hope that it's able to save precious time from others.

这篇关于如何在带有Firebase的Xamarin和带有C#后端的Apple Push Notification中实现推送通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆