Подтвердить что ты не робот

Как использовать Push-уведомления в форматах Xamarin

У меня есть приложение, использующее Xamarin.Forms для IOS, Android и WP 8.

Мне нужна функция push-уведомлений в моем приложении.

Я видел демоверсии pushsharp и это кажется многообещающим. Но все коды, которые я видел, сделаны отдельно для каждой платформы.

Я хотел бы, чтобы это было сделано в проекте Xamarin.Forms, где-то в App.cs, чтобы мне не нужно было повторять код для регистрации устройства и обрабатывать обработку push-уведомлений.

Любая помощь будет принята с благодарностью. Примеры кодов или учебные ссылки приветствуются.

Изменить: я реализовал это на основе ответа Idot. Вот ссылка на мой ответ.

4b9b3361

Ответ 1

Я только что реализовал push-уведомление несколько дней назад, и я поделюсь своим решением здесь (на основе PushSharp)

Пошаговое руководство:

1) В вашем общем проекте создайте интерфейс под названием IPushNotificationRegister

public interface IPushNotificationRegister
{
    void ExtractTokenAndRegister();
}

Этот интерфейс используется для получения push-токена и последующей отправки его на сервер. этот токен уникален для каждого устройства.

2) В вашем совместном проекте вы должны вызвать ExtractTokenAndRegister (используя ваш любимый IOC, я назвал его сразу после входа в систему).

Реализация Android:

3) Добавьте приемники для прослушивания событий, полученных службой Google GCM:

а)

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

б)

[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[] { "@[email protected]" })]
    [IntentFilter(new string[] { "com.google.android.c2dm.intent.REGISTRATION" }, Categories = new string[] { "@[email protected]" })]
    [IntentFilter(new string[] { "com.google.android.gcm.intent.RETRY" }, Categories = new string[] { "@[email protected]" })]
    [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) добавить сервис Intent для обработки уведомления

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

        }

    }
}

г) Реализовать интерфейс 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);
        }


    }
}

реализация iOS:

4) В вашем AppDelegate добавьте следующий метод:

а)

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

б) Реализовать 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);
        }
    }
}

Что касается WP, я его не реализовал.

Если вам нужен код на стороне сервера, использующий PushSharp, дайте мне знать.

Вы можете проверить образцы клиентов, на которых я основал свое решение, здесь.

Ответ 2

Мне предложили использовать следующий плагин с поддержкой и формами xamarin.

Этот плагин работает хорошо

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

Обновлю ответ, как только получу его на работу.

ОБНОВИТЬ :

Я получил push-уведомления для iOS и Android.

Я использовал Google Cloud Messaging Client, отличный компонент для Android, и мне не пришлось писать большую часть кода, как указано в этом ответе.

Моя реализация iOS была похожа на это, не требуется много кода.

А для Push-уведомлений с Сервера я использовал пакет nuget PushSharp.

Я не реализовал в WP, поскольку это не требовалось в моем проекте.

Эту справку Xamarin по push-уведомлениям стоит прочитать, если вы собираетесь использовать Push-уведомления.

Обновление (июнь 2018 г.) - используйте следующий плагин для FCM на iOS и Android, пока он поддерживает Xamarin.Forms - FirebasePushNotificationPlugin

Ответ 3

В Xamarin Forms вы также можете использовать SDK уведомлений, такой как Donky (который является европейским эквивалентом американского городского дирижабля); вы можете легко создать масштабируемый проект уведомлений за один день, я дважды создавал оболочки для клонирования WhatsApp менее 35 минут каждый раз, используя этот SDK. См. http://docs.mobiledonky.com

Ответ 4

Вы можете посмотреть компонент Appboy, который поддерживает это из коробки. https://components.xamarin.com/view/appboy-sdk-bindings

Как говорили другие, вы не можете делать в общем случае без каких-либо компонентов, специфичных для платформы.

Ответ 5

Это невозможно сделать в чистых Xamarin.Forms, но относительно тривиально реализовать решение, с помощью которого они могут обрабатываться в App.cs(хотя для этого потребуются конкретные реализации платформы).

Взгляните на реализацию IXForms в проекте Xamarin.Forms.Labs, где уведомления отправляются обратно в проект Forms:

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

и более конкретно:

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

Ответ 6

Недавно появилось сообщение в блоге о внедрении Push-уведомлений о форматах Xamarin (а ​​также каждая отдельная платформа, потому что нет реализации на основе форм), используя Azure Mobile Services.

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

Ответ 7

Я использовал AppCenter для реализации Push-уведомлений в Android и IOS. Это довольно легко и хорошо работает для обеих платформ. Вы можете посмотреть здесь.

https://docs.microsoft.com/en-us/appcenter/sdk/push/xamarin-ios для Ios https://docs.microsoft.com/en-us/appcenter/sdk/push/android для Android

Android использует Firebase для отправки push-уведомлений, а iOS использует Apns для того же. S, вам нужно настроить оба игнорирующих для отправки уведомлений в ваше приложение.

Для получения дополнительной информации, перейдите по этой https://appcenter.ms/apps