Como implementar a Notificação Push no Xamarin com Firebase e a Apple Push Notification com back-end C #
Durante minha migração de Native Android e iOS para Xamarin.Forms, decidi usar AppCenter Push para minha notificação, já que é grátis e fácil de usar (é claro que gastei um bom tempo para fazê-lo funcionar, já que é relativamente novo coisa com menos orientação online). Você pode encontrar meu compartilhamento original em Como implementar API AppCenter Push? .
Fiquei feliz com isso até a Microsoft anunciar que estava retirando o AppCenter Push (https://devblogs.microsoft.com/appcenter/app-center-mbaas-retirement/) e incentivou o usuário a mudar para o Azure (que é um serviço pago). Decidi voltar a usar o FCM e APN nativos para minha notificação push.
O problema é que não há tutoriais diretos sobre como fazer a coisa toda. Existem problemas e soluções aqui e ali, como iOS. P8 só funciona em HTTP / 2 enquanto meu projeto está em execução em .Net Framework que não é compatível. Apenas .Net Core pode usar o protocolo HTTP / 2.
Respostas
Meu projeto atual é executado em ASP.NET C # como back-end, que envia uma notificação para Xamarin.Android e Xamarin.iOS usando Xamarin.Forms. Se você for como eu, encontre minha resposta abaixo, estou compartilhando o back-end C # totalmente funcional e a solução Xamarin.Forms abaixo. Para que mais usuários possam se beneficiar do serviço GRATUITO em vez de serem enviados ao serviço pago do Azure.
PARTE 1 Back - end C # - O back-end C # ASP.NET. Ele será dividido em 2 partes, para FCM e APNs.
1.1) Firebase (FCM)
Para configurar o FCM, você precisa registrar uma conta. Existem toneladas de diretrizes online, esta é uma das boashttps://xmonkeys360.com/2019/12/08/xamarin-forms-fcm-setup-configuration-part-i/. Lembre-se de obter a chave do servidor e baixar o arquivo google-services.json para o seu projeto Xamarin.Android. Clique com o botão direito e defina a ação de construção como " GoogleServiceJson " ( onde posso adicionar google-services.json no aplicativo xamarin ).
Abaixo está meu 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)
- Para APNs, existem 2 maneiras de fazer as coisas. Um está usando o modo convencional .P12. Outra maneira é usar as Apple Auth Keys usando .P8. Eu prefiro usar .P8 porque .P12 cert expira todos os anos e precisa ser atualizado anualmente . O problema de usar .P8 é que está usando HTTP / 2, que não é compatível com .Net Framework, mas felizmente, consegui superar isso. Consulte Como implementar notificações push com base em tokens da Apple (usando arquivo p8) em C #? , encontre minha resposta nesse post sobre como implementar tudo para .Net Framework. * SE você já estiver usando .Net Core, a resposta será semelhante à minha, mas você não precisa usar o WinHTTPHandler personalizado. Apenas o HTTPClient normal fará.
PARTE 2 Xamarin.Forms - Em seguida, você terá que oferecer suporte à notificação em seu projeto Xamarin.Forms.
Para esta parte, não é nada difícil. Tudo que você precisa fazer é consultarhttps://github.com/CrossGeeks/PushNotificationPlugin, baixe o Nuget e siga as instruções no link para configurar seus projetos Xamarin (Forms, Android, iOS).
A única coisa que desejo destacar é como e onde obter o token do seu dispositivo. Inicialmente, estava tentando obter o token do dispositivo no código abaixo (OnTokenRefresh). Mas você logo perceberá que esse código nem sempre é chamado. Suspeito que ele só será chamado quando o token for atualizado, e não sempre que você depurar. Para obter o seu token de dispositivo todas as vezes, basta chamar
CrossPushNotification.Current.Tokenem qualquer lugar em seu projeto. Registre esse token de dispositivo no back-end do servidor. E use o token do dispositivo para enviar a notificação usando meu código na PARTE 1 acima.CrossPushNotification.Current.OnTokenRefresh += (s,p) => { System.Diagnostics.Debug.WriteLine($"TOKEN : {p.Token}"); };
É isso aí! É muito fácil, mas passei semanas tentando e errar antes de juntá-los. Espero que seja capaz de economizar um tempo precioso de outras pessoas.