Cómo usar las notificaciones push en formularios Xamarin

Soy una aplicación que usa Xamarin.Forms que apuntan a IOS, Android y WP 8.

Necesito la función de notificaciones automáticas en mi aplicación.

He visto las demostraciones pushsharp y parece prometedor. Pero todos los códigos que he visto se hacen por separado para cada plataforma.

Me gustaría que se hiciera en el proyecto Xamarin.Forms, en algún lugar de App.cs, para no tener que repetir el código para registrar el dispositivo y manejar cómo deberían procesarse las notificaciones push.

Cualquier ayuda sería muy apreciada. Se aceptan códigos de muestra o referencias de tutoriales.

Editar : lo implementé en función de la respuesta de Idot. Aquí está el enlace para mi respuesta.

Acabo de implementar la notificación push hace unos días, y compartiré mi solución aquí (basada en PushSharp )

Guía paso por paso:

1) En su proyecto compartido, cree una interfaz llamada IPushNotificationRegister

 public interface IPushNotificationRegister { void ExtractTokenAndRegister(); } 

Esta interfaz se utiliza para obtener el token de inserción y luego enviarlo al servidor. este token es único por dispositivo.

2) En su proyecto compartido, debe invocar ExtractTokenAndRegister (usando su IOC favorito, lo llamé justo después de iniciar sesión).

Implementación de Android:

3) Agregue receptores para escuchar eventos recibidos por el servicio Google GCM:

un)

 [BroadcastReceiver] [IntentFilter(new[] { Intent.ActionBootCompleted })] public class GCMBootReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { MyIntentService.RunIntentInService(context, intent); SetResult(Result.Ok, null, null); } } 

segundo)

 [assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")] [assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] [assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")] [assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")] [assembly: UsesPermission(Name = "android.permission.INTERNET")] namespace Consumer.Mobile.Droid.PushNotification { [BroadcastReceiver(Permission = "com.google.android.c2dm.permission.SEND")] [IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new string[] { "@PACKAGE_NAME@" })] [IntentFilter(new string[] { "com.google.android.c2dm.intent.REGISTRATION" }, Categories = new string[] { "@PACKAGE_NAME@" })] [IntentFilter(new string[] { "com.google.android.gcm.intent.RETRY" }, Categories = new string[] { "@PACKAGE_NAME@" })] [IntentFilter (new[]{ Intent.ActionBootCompleted }, Categories = new[]{ Intent.CategoryDefault })] public class GCMBroadcastReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { MyIntentService.RunIntentInService(context, intent); SetResult(Result.Ok, null, null); } } } 

c) Servicio de agregar servicio para procesar la notificación

 using Android.App; using Android.Content; using Android.Graphics; using Android.Media; using Android.OS; using Android.Support.V4.App; using Consumer.Mobile.Infra; using Consumer.Mobile.Services.PushNotification; using Java.Lang; using XLabs.Ioc; using TaskStackBuilder = Android.Support.V4.App.TaskStackBuilder; namespace Consumer.Mobile.Droid.PushNotification { [Service] public class MyIntentService : IntentService { private readonly ILogger _logger; private readonly IPushNotificationService _notificationService; private readonly IPushNotificationRegister _pushNotificationRegister; public MyIntentService() { _logger = Resolver.Resolve(); _notificationService = Resolver.Resolve(); _pushNotificationRegister = Resolver.Resolve(); } static PowerManager.WakeLock _sWakeLock; static readonly object Lock = new object(); public static void RunIntentInService(Context context, Intent intent) { lock (Lock) { if (_sWakeLock == null) { // This is called from BroadcastReceiver, there is no init. var pm = PowerManager.FromContext(context); _sWakeLock = pm.NewWakeLock( WakeLockFlags.Partial, "My WakeLock Tag"); } } _sWakeLock.Acquire(); intent.SetClass(context, typeof(MyIntentService)); context.StartService(intent); } protected override void OnHandleIntent(Intent intent) { try { Context context = this.ApplicationContext; string action = intent.Action; if (action.Equals("com.google.android.c2dm.intent.REGISTRATION")) { HandleRegistration(context, intent); } else if (action.Equals("com.google.android.c2dm.intent.RECEIVE")) { HandleMessage(context, intent); } } finally { lock (Lock) { //Sanity check for null as this is a public method if (_sWakeLock != null) _sWakeLock.Release(); } } } private void HandleMessage(Context context, Intent intent) { Intent resultIntent = new Intent(this, typeof(MainActivity)); TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this); var c = Class.FromType(typeof(MainActivity)); stackBuilder.AddParentStack(c); stackBuilder.AddNextIntent(resultIntent); string alert = intent.GetStringExtra("Alert"); int number = intent.GetIntExtra("Badge", 0); var imageUrl = intent.GetStringExtra("ImageUrl"); var title = intent.GetStringExtra("Title"); Bitmap bitmap = GetBitmap(imageUrl); PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, (int)PendingIntentFlags.UpdateCurrent); NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .SetAutoCancel(true) // dismiss the notification from the notification area when the user clicks on it .SetContentIntent(resultPendingIntent) // start up this activity when the user clicks the intent. .SetContentTitle(title) // Set the title .SetNumber(number) // Display the count in the Content Info .SetSmallIcon(Resource.Drawable.Icon) // This is the icon to display .SetLargeIcon(bitmap) .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification)) .SetContentText(alert); // the message to display. // Build the notification: Notification notification = builder.Build(); // Get the notification manager: NotificationManager notificationManager = GetSystemService(Context.NotificationService) as NotificationManager; // Publish the notification: const int notificationId = 0; notificationManager.Notify(notificationId, notification); } private void HandleRegistration(Context context, Intent intent) { var token = intent.GetStringExtra("registration_id"); _logger.Info(this.Class.SimpleName, "Received Token : " + token); if (_pushNotificationRegister.ShouldSendToken(token)) { var uid = Android.Provider.Settings.Secure.GetString(MainActivity.Context.ContentResolver, Android.Provider.Settings.Secure.AndroidId); _notificationService.AddPushToken(token, DeviceUtils.GetDeviceType(), uid); } } private Bitmap GetBitmap(string url) { try { System.Net.WebRequest request = System.Net.WebRequest.Create(url); System.Net.WebResponse response = request.GetResponse(); System.IO.Stream responseStream = response.GetResponseStream(); return BitmapFactory.DecodeStream(responseStream); } catch (System.Net.WebException) { return null; } } } } 

d) Implementar la interfaz IPushNotificationRegister :

 using Android.App; using Android.Content; using Consumer.Mobile.Services; using Consumer.Mobile.Services.PushNotification; [assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] [assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] // Gives the app permission to register and receive messages. [assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")] // Needed to keep the processor from sleeping when a message arrives [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")] [assembly: UsesPermission(Name = "android.permission.RECEIVE_BOOT_COMPLETED")] namespace Consumer.Mobile.Droid.PushNotification { public class PushNotificationRegister : IPushNotificationRegister { public override void ExtractTokenAndRegister() { string senders = AndroidConfig.GCMSenderId; Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER"); intent.SetPackage("com.google.android.gsf"); intent.PutExtra("app", PendingIntent.GetBroadcast(MainActivity.Context, 0, new Intent(), 0)); intent.PutExtra("sender", senders); MainActivity.Context.StartService(intent); } } } 

Implementación de iOS:

4) En su AppDelegate , agregue el siguiente método:

un)

 public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { var deviceTokenString = deviceToken.ToString().Replace("<","").Replace(">", "").Replace(" ", ""); var notificationService = Resolver.Resolve(); var pushNotificationRegister = Resolver.Resolve(); if (pushNotificationRegister.ShouldSendToken(deviceTokenString)) { var uid = UIDevice.CurrentDevice.IdentifierForVendor.AsString(); notificationService.AddPushToken(deviceTokenString, DeviceUtils.GetDeviceType(), uid); } } 

b) Implementar IPushNotificationRegister :

 using Consumer.Mobile.Services; using Consumer.Mobile.Services.PushNotification; using UIKit; namespace Consumer.Mobile.iOS.PushNotification { public class iOSPushNotificationRegister : IPushNotificationRegister { public override void ExtractTokenAndRegister() { const UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound; UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes); } } } 

En cuanto a WP, no lo implementé.

Si necesita el código en el servidor usando PushSharp, hágamelo saber.

Puede verificar las muestras del cliente. He basado mi solución aquí.

Se me ha sugerido usar el siguiente complemento mediante el soporte y formularios de xamarin.

Este plugin funciona bien

https://github.com/rdelrosario/xamarin-plugins/tree/master/PushNotification

Actualizaré la respuesta una vez que lo haga funcionar.

ACTUALIZAR:

Recibí notificaciones push que funcionan tanto para iOS como para Android.

Utilicé Google Cloud Messaging Client , un excelente componente para Android, y no tuve que escribir gran parte del código como se menciona en esta respuesta .

Mi implementación de iOS fue similar a esto , no se requiere mucho código.

Y para Empujar las notificaciones desde el Servidor, utilicé el paquete nuget de PushSharp .

No implementé en WP, ya que eso no se requería en mi proyecto.

Vale la pena leer esta Ayuda de Xamarin sobre Notificaciones Push si va a implementar Notificaciones Push.

Actualización (junio de 2018): utilice el siguiente complemento para FCM en iOS y Android, ti compatible con Xamarin.Forms – FirebasePushNotificationPlugin

En Xamarin Forms también puede usar un SDK de notificaciones como Donky (que es el equivalente europeo del American Urban Airship); usted puede hacer fácilmente un proyecto de notificaciones escalable en un solo día, he construido dos capas de clones de WhatsApp dos veces en menos de 35 minutos cada vez que uso este SDK. Ver http://docs.mobiledonky.com

Esto no se puede hacer en Xamarin.Forms puros, pero es relativamente trivial implementar una solución que los pueda manejar en la App.cs (aunque esto requerirá implementaciones específicas de la plataforma).

Eche un vistazo a la implementación de IXForms dentro del proyecto Xamarin.Forms.Labs donde las notificaciones se canalizan nuevamente al proyecto de formularios:

https://github.com/XLabs/Xamarin-Forms-Labs

y mas especificamente:

https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/src/Platform/XLabs.Platform/Mvvm

Recientemente, hay una publicación en el blog sobre la implementación de notificaciones push en formularios Xamarin (bien en cada plataforma individual porque no hay implementación basada en formularios), utilizando Azure Mobile Services.

http://www.xamarinhelp.com/push-notifications/

Puede ver el componente de Appboy que tiene soporte para esto de manera inmediata. https://components.xamarin.com/view/appboy-sdk-bindings

Como han dicho otros, no se puede hacer genéricamente sin algunos componentes específicos de la plataforma.