如何使用Firebase在Xamarin中实现Push Notification,以及使用C#后端在Apple中实现Pu



在我从原生Android和iOS迁移到Xamarin.Forms的过程中,我决定使用AppCenter Push进行通知,因为它是免费且易于使用的(当然,我花了大量时间使其发挥作用,因为它相对较新,在线指导较少(。您可以在"如何实现AppCenterPushneneneba API?"中找到我的原始分享?。

我很高兴,直到微软宣布它将退出AppCenter推送(https://devblogs.microsoft.com/appcenter/app-center-mbaas-retirement/)并鼓励用户转移到Azure(这是一项付费服务(。我决定重新使用本地FCM和APN来进行推送通知。

问题是没有关于如何完成整件事的直接教程。存在问题&这里和那里的解决方案,如iOS.P8只在HTTP/2上工作,而我的项目运行在不支持的.Net Framework上。只有.Net Core可以使用HTTP/2协议。

我当前的项目运行在ASP.NET C#作为后端,它使用Xamarin.Forms向Xamarin.Android和Xamarin.iOS发送通知。如果你和我一样,请在下面找到我的答案,我将在下面分享完全可用的C#后端和Xamaring.Forms解决方案。这样更多的用户可以从免费服务中受益,而不是被推到Azure付费服务。

第1部分C#后端-C#ASP.NET后端。它将分为两部分,分别用于FCM和APN。

1.1(Firebase(FCM(

  1. 要设置FCM,您需要注册一个帐户。网上有很多指南,这是一个很好的指南https://xmonkeys360.com/2019/12/08/xamarin-forms-fcm-setup-configuration-part-i/.请记住获取服务器密钥并将谷歌服务.json文件下载到您的Xamarin.Android项目中。右键单击并将构建操作设置为">谷歌服务Json";(我在哪里可以在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密钥。我更喜欢使用.P8,因为.P12证书每年到期,需要每年更新。使用.P8的问题是,它使用的是HTTP/2,这在.Net Framework中不受支持,但谢天谢地,我成功地克服了这一点。请参阅如何在C#中实现基于apple令牌的推送通知(使用p8文件(?,请在关于如何为.Net Framework实现整个功能的帖子中找到我的答案*如果您已经在使用.Net Core,答案将与我的类似,但您不必使用自定义的WinHTTPHandler。正常的HTTPClient就可以了

第2部分Xamarin.Forms-接下来,您必须在Xamarin.Form项目中支持通知。

  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}");
    };
    

就是这样!这很容易,但在把它们拼凑起来之前,我花了几个星期的时间反复尝试。希望它能节省别人宝贵的时间。

服务器:

请尝试服务器端的FirebaseAdmin。这个包裹真是太棒了。

https://github.com/firebase/firebase-admin-dotnet

遵循以下设置说明:

https://firebase.google.com/docs/admin/setup#c

对于Xamarin应用程序:

我决定不想使用CrossGeeks插件,它非常简单。

对于Android:

安装相关的Xamarin.Firebase包,并在继承包FirebaseMessagingService的Android项目中创建自己的Firebase消息类。

[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
class PushNotificationFirebaseMessagingService : FirebaseMessagingService
{
private static string foregroundChannelId = "9001";
public override void OnNewToken(string refreshedToken)
{
base.OnNewToken(refreshedToken);
SendRegistrationToServer(refreshedToken);
}
private void SendRegistrationToServer(string token)
{
//Your code here to register device token on server
}
public override void OnMessageReceived(RemoteMessage message)
{
SendNotification(message);
base.OnMessageReceived(message);
}
private void SendNotification(RemoteMessage message)
{
try
{
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
var notificationChannel = new NotificationChannel(foregroundChannelId, "messaging_channel", NotificationImportance.High);
var audioAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
var notificationUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
notificationChannel.EnableLights(true);
notificationChannel.EnableVibration(true);
notificationChannel.SetSound(notificationUri, audioAttributes);

notificationManager.CreateNotificationChannel(notificationChannel);
var remoteNotification = message.GetNotification();
var builder = new Notification.Builder(this, foregroundChannelId)
.SetContentTitle(remoteNotification.Title)
.SetContentText(remoteNotification.Body)
.SetSmallIcon(Resource.Mipmap.icon);
var notification = builder.Build();
notificationManager.Notify(0, notification);
}
catch (Exception ex)
{
}
}
}

将以下内容添加到Application标记中的AndroidManifest.xml中。

<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="${applicationId}" />
</intent-filter>
</receiver>

最新更新