web-dev-qa-db-fra.com

Comment utiliser les notifications push dans les formulaires Xamarin

J'ai une application utilisant Xamarin.Forms ciblant IOS, Android et WP 8. 

J'ai besoin d'une fonctionnalité de notification Push dans mon application. 

J'ai vu les démos pushsharp et cela semble prometteur. Mais tous les codes que j'ai vus sont effectués séparément pour chaque plate-forme. 

J'aimerais que cela se fasse dans le projet Xamarin.Forms, quelque part dans le fichier App.cs, de sorte que je n'ai pas besoin de répéter le code pour enregistrer un périphérique et de gérer le traitement des notifications Push. 

Toute aide serait grandement appréciée. Des exemples de codes ou des références de tutoriel sont les bienvenus. 

Edit: je l'ai implémenté à partir de answer d'Idot. Voici le link pour ma réponse. 

45

Je viens de mettre en œuvre la notification Push il y a quelques jours et je vais partager ici ma solution (basé sur PushSharp )

Guide étape par étape:

1) Dans votre projet partagé, créez une interface appelée IPushNotificationRegister

public interface IPushNotificationRegister
{
    void ExtractTokenAndRegister();
}

Cette interface est utilisée pour récupérer le jeton Push, puis l'envoyer au serveur. Ce jeton est unique par appareil.

2) Dans votre projet partagé, vous devez invoquer ExtractTokenAndRegister (en utilisant votre CIO préféré, je l'ai appelé juste après la connexion).

Implémentation Android:

3) Ajoutez des destinataires pour écouter les événements reçus par le service Google GCM:

une)

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

b) 

[Assembly: Permission(Name = "@[email protected]_MESSAGE")]
[Assembly: UsesPermission(Name = "Android.permission.WAKE_LOCK")]
[Assembly: UsesPermission(Name = "@[email protected]_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) Ajouter un service d'intention pour traiter la notification 

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<ILogger>();
            _notificationService = Resolver.Resolve<IPushNotificationService>();
            _pushNotificationRegister = Resolver.Resolve<IPushNotificationRegister>();
        }

        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) Implémenter l'interface IPushNotificationRegister:

using Android.App;
using Android.Content;
using Consumer.Mobile.Services;
using Consumer.Mobile.Services.PushNotification;
[Assembly: Permission(Name = "@[email protected]_MESSAGE")]
[Assembly: UsesPermission(Name = "@[email protected]_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);
        }


    }
}

implémentation iOS:

4) Dans votre AppDelegate, ajoutez la méthode suivante:

une) 

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    var deviceTokenString = deviceToken.ToString().Replace("<","").Replace(">", "").Replace(" ", "");
    var notificationService = Resolver.Resolve<IPushNotificationService>();
    var pushNotificationRegister = Resolver.Resolve<IPushNotificationRegister>();

    if (pushNotificationRegister.ShouldSendToken(deviceTokenString))
    {
        var uid = UIDevice.CurrentDevice.IdentifierForVendor.AsString();
        notificationService.AddPushToken(deviceTokenString, DeviceUtils.GetDeviceType(), uid);
    }
}

b) Implémentez 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 ce qui concerne WP, je ne l'ai pas implémenté.

Si vous avez besoin du code côté serveur avec PushSharp, faites-le moi savoir.

Vous pouvez vérifier les exemples de clients sur lesquels j'ai fondé ma solution ici

48
IdoT

On m'a suggéré d'utiliser le plugin suivant par le support et les formulaires xamarin. 

Ce plugin fonctionne bien

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

Mettra à jour la réponse une fois que je l'obtenir au travail. 

METTRE À JOUR :

_ {Les notifications Push fonctionnent pour iOS et Android.

J'ai utilisé Google Cloud Messaging Client , un excellent composant pour Android, sans avoir à écrire une grande partie du code mentionné dans cette réponse

Mon implémentation iOS était similaire à this , pas beaucoup de code nécessaire. 

Et pour pousser les notifications du serveur, j'ai utilisé le paquet nuget de PushSharp

Je n'ai pas mis en œuvre dans WP, car cela n'était pas requis dans mon projet.

Cette aide Aide Xamarin sur les notifications Push mérite une lecture si vous souhaitez implémenter des notifications Push. 

Mise à jour (juin 2018) - Utilisez le plug-in suivant pour FCM sur iOS et Android. Il prend en charge Xamarin.Forms - FirebasePushNotificationPlugin

16

Dans Xamarin Forms, vous pouvez également utiliser un SDK de notification comme Donky (l’équivalent européen de l’American Urban Airship); vous pouvez facilement créer un projet de notifications évolutif en une seule journée. J'ai construit à deux reprises des shells de clone WhatsApp en moins de 35 minutes à l'aide de ce kit de développement logiciel. Voir http://docs.mobiledonky.com

2
Xamtastic

Vous pouvez regarder le composant Appboy qui prend en charge cette fonctionnalité immédiatement. https://components.xamarin.com/view/appboy-sdk-bindings

Comme d'autres l'ont déjà dit, vous ne pouvez pas faire de manière générique sans certains composants spécifiques à la plate-forme.

1
Brian Wheeler

Il y a récemment un article de blog sur l'implémentation des notifications Push sur Xamarin Forms (ainsi que sur chaque plate-forme car il n'y a pas d'implémentation basée sur Forms), utilisant Azure Mobile Services.

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

1
Adam Pedley

Cela n'est pas possible dans Xamarin.Forms pur, mais il est relativement simple d'implémenter une solution permettant de les gérer dans le fichier App.cs (bien que cela nécessite des implémentations spécifiques à la plate-forme). 

Jetez un coup d'œil à l'implémentation IXForms du projet Xamarin.Forms.Labs où les notifications sont redirigées vers le projet Forms:

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

et plus précisément:

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

0
JordanMazurke