yerel bildirimler Xamarin.Forms

Yerel bildirimler, mobil cihazda yüklü uygulamalar tarafından gönderilen uyarılardır. Yerel bildirimler genellikle aşağıdakiler gibi özellikler için kullanılır:

  • Takvim olayları
  • Anımsatıcılar
  • Konum tabanlı tetikleyiciler

Her platform yerel bildirimlerin oluşturulmasını, görüntülenmesini ve tüketimini farklı şekilde işler. Bu makalede ile Xamarin.Formsyerel bildirimler göndermek, zamanlamak ve almak için platformlar arası soyutlamanın nasıl oluşturulacağı açıklanır.

iOS ve Android'de yerel bildirimler uygulaması

Platformlar arası arabirim oluşturma

Uygulamanın Xamarin.Forms temel platform uygulamalarıyla ilgilenmeden bildirimler oluşturması ve kullanması gerekir. Aşağıdaki INotificationManager arabirim paylaşılan kod kitaplığında uygulanır ve uygulamanın bildirimlerle etkileşime geçmek için kullanabileceği platformlar arası bir API tanımlar:

public interface INotificationManager
{
    event EventHandler NotificationReceived;
    void Initialize();
    void SendNotification(string title, string message, DateTime? notifyTime = null);
    void ReceiveNotification(string title, string message);
}

Bu arabirim her platform projesinde uygulanacaktır. Olay, NotificationReceived uygulamanın gelen bildirimleri işlemesine olanak tanır. yöntemi, Initialize bildirim sistemini hazırlamak için gereken tüm yerel platform mantığını gerçekleştirmelidir. SendNotification yöntemi isteğe bağlı DateTimeolarak bir bildirim göndermelidir. Bir ReceiveNotification ileti alındığında yöntemi temel platform tarafından çağrılmalıdır.

arabirimini kullanma Xamarin.Forms

Bir arabirim oluşturulduktan sonra, platform uygulamaları henüz oluşturulmamış olsa bile paylaşılan Xamarin.Forms projede kullanılabilir. Örnek uygulama, aşağıdaki içeriğe sahip MainPage.xaml adlı bir ContentPage içerir:

<StackLayout Margin="0,35,0,0"
             x:Name="stackLayout">
    <Label Text="Click the button below to create a local notification."
           TextColor="Red"
           HorizontalOptions="Center"
           VerticalOptions="Start" />
    <Button Text="Create Notification"
            HorizontalOptions="Center"
            VerticalOptions="Start"
            Clicked="OnSendClick" />
    <Label Text="Click the button below to schedule a local notification for in 10 seconds time."
           TextColor="Red"
           HorizontalOptions="Center"
           VerticalOptions="Start" />
    <Button Text="Create Notification"
            HorizontalOptions="Center"
            VerticalOptions="Start"
            Clicked="OnScheduleClick" />
</StackLayout>

Düzen, yönergeleri açıklayan öğeleri ve Button dokunulduğunda bildirim gönderen veya zamanlayan öğeleri içerirLabel.

Arka MainPage planda kod sınıfı, bildirimlerin gönderilmesini ve alınmasını işler:

public partial class MainPage : ContentPage
{
    INotificationManager notificationManager;
    int notificationNumber = 0;

    public MainPage()
    {
        InitializeComponent();

        notificationManager = DependencyService.Get<INotificationManager>();
        notificationManager.NotificationReceived += (sender, eventArgs) =>
        {
            var evtData = (NotificationEventArgs)eventArgs;
            ShowNotification(evtData.Title, evtData.Message);
        };
    }

    void OnSendClick(object sender, EventArgs e)
    {
        notificationNumber++;
        string title = $"Local Notification #{notificationNumber}";
        string message = $"You have now received {notificationNumber} notifications!";
        notificationManager.SendNotification(title, message);
    }

    void OnScheduleClick(object sender, EventArgs e)
    {
        notificationNumber++;
        string title = $"Local Notification #{notificationNumber}";
        string message = $"You have now received {notificationNumber} notifications!";
        notificationManager.SendNotification(title, message, DateTime.Now.AddSeconds(10));
    }

    void ShowNotification(string title, string message)
    {
        Device.BeginInvokeOnMainThread(() =>
        {
            var msg = new Label()
            {
                Text = $"Notification Received:\nTitle: {title}\nMessage: {message}"
            };
            stackLayout.Children.Add(msg);
        });
    }
}

MainPage Sınıf oluşturucu, Xamarin.FormsDependencyService platforma özgü bir örneğini INotificationManageralmak için öğesini kullanır. OnSendClick ve OnScheduleClicked yöntemleri, yeni bildirimler göndermek ve zamanlamak için örneğini INotificationManager kullanır. ShowNotification yöntemi, olaya bağlı NotificationReceived olay işleyicisinden çağrılır ve olay çağrıldığında sayfaya yeni Label bir ekler.

Olay işleyicisi NotificationReceived , olay bağımsız değişkenlerini öğesine NotificationEventArgsyayınlar. Bu tür paylaşılan Xamarin.Forms projede tanımlanır:

public class NotificationEventArgs : EventArgs
{
    public string Title { get; set; }
    public string Message { get; set; }
}

hakkında Xamarin.FormsDependencyServicedaha fazla bilgi için bkz Xamarin.Forms . DependencyService.

Android arabirim uygulamasını oluşturma

Uygulamanın Android'de Xamarin.Forms bildirim gönderip alabilmesi için uygulamanın arabiriminin INotificationManager bir uygulamasını sağlaması gerekir.

AndroidNotificationManager sınıfını oluşturma

AndroidNotificationManager sınıfı arabirimini INotificationManager uygular:

using System;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using AndroidX.Core.App;
using Xamarin.Forms;
using AndroidApp = Android.App.Application;

[assembly: Dependency(typeof(LocalNotifications.Droid.AndroidNotificationManager))]
namespace LocalNotifications.Droid
{
    public class AndroidNotificationManager : INotificationManager
    {
        const string channelId = "default";
        const string channelName = "Default";
        const string channelDescription = "The default channel for notifications.";

        public const string TitleKey = "title";
        public const string MessageKey = "message";

        bool channelInitialized = false;
        int messageId = 0;
        int pendingIntentId = 0;

        NotificationManager manager;

        public event EventHandler NotificationReceived;

        public static AndroidNotificationManager Instance { get; private set; }

        public AndroidNotificationManager() => Initialize();

        public void Initialize()
        {
            if (Instance == null)
            {
                CreateNotificationChannel();
                Instance = this;
            }
        }

        public void SendNotification(string title, string message, DateTime? notifyTime = null)
        {
            if (!channelInitialized)
            {
                CreateNotificationChannel();
            }

            if (notifyTime != null)
            {
                Intent intent = new Intent(AndroidApp.Context, typeof(AlarmHandler));
                intent.PutExtra(TitleKey, title);
                intent.PutExtra(MessageKey, message);

                PendingIntent pendingIntent = PendingIntent.GetBroadcast(AndroidApp.Context, pendingIntentId++, intent, PendingIntentFlags.CancelCurrent);
                long triggerTime = GetNotifyTime(notifyTime.Value);
                AlarmManager alarmManager = AndroidApp.Context.GetSystemService(Context.AlarmService) as AlarmManager;
                alarmManager.Set(AlarmType.RtcWakeup, triggerTime, pendingIntent);
            }
            else
            {
                Show(title, message);
            }
        }

        public void ReceiveNotification(string title, string message)
        {
            var args = new NotificationEventArgs()
            {
                Title = title,
                Message = message,
            };
            NotificationReceived?.Invoke(null, args);
        }

        public void Show(string title, string message)
        {
            Intent intent = new Intent(AndroidApp.Context, typeof(MainActivity));
            intent.PutExtra(TitleKey, title);
            intent.PutExtra(MessageKey, message);

            PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId++, intent, PendingIntentFlags.UpdateCurrent);

            NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
                .SetContentIntent(pendingIntent)
                .SetContentTitle(title)
                .SetContentText(message)
                .SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.xamagonBlue))
                .SetSmallIcon(Resource.Drawable.xamagonBlue)
                .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);

            Notification notification = builder.Build();
            manager.Notify(messageId++, notification);
        }

        void CreateNotificationChannel()
        {
            manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);

            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                var channelNameJava = new Java.Lang.String(channelName);
                var channel = new NotificationChannel(channelId, channelNameJava, NotificationImportance.Default)
                {
                    Description = channelDescription
                };
                manager.CreateNotificationChannel(channel);
            }

            channelInitialized = true;
        }

        long GetNotifyTime(DateTime notifyTime)
        {
            DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(notifyTime);
            double epochDiff = (new DateTime(1970, 1, 1) - DateTime.MinValue).TotalSeconds;
            long utcAlarmTime = utcTime.AddSeconds(-epochDiff).Ticks / 10000;
            return utcAlarmTime; // milliseconds
        }
    }
}

Ad assembly alanının üzerindeki özniteliği, arabirim uygulamasını ile DependencyServicekaydederINotificationManager.

Android, uygulamaların bildirimler için birden çok kanal tanımlamasına olanak tanır. yöntemi, Initialize örnek uygulamanın bildirim göndermek için kullandığı temel bir kanal oluşturur. yöntemi, SendNotification bildirim oluşturmak ve göndermek için gereken platforma özgü mantığı tanımlar. yöntemi ReceiveNotification , bir ileti alındığında Android işletim sistemi tarafından çağrılır ve olay işleyicisini çağırır.

SendNotification yöntemi hemen veya tam DateTimeolarak bir yerel bildirim oluşturur. Bir bildirim, sınıfı kullanılarak AlarmManager tam DateTime olarak zamanlanabilir ve bildirim sınıfından türetilen BroadcastReceiver bir nesne tarafından alınır:

[BroadcastReceiver(Enabled = true, Label = "Local Notifications Broadcast Receiver")]
public class AlarmHandler : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        if (intent?.Extras != null)
        {
            string title = intent.GetStringExtra(AndroidNotificationManager.TitleKey);
            string message = intent.GetStringExtra(AndroidNotificationManager.MessageKey);

            AndroidNotificationManager manager = AndroidNotificationManager.Instance ?? new AndroidNotificationManager();
            manager.Show(title, message);
        }
    }
}

Önemli

Varsayılan olarak, sınıfı kullanılarak zamanlanan bildirimler cihazın yeniden başlatılmasından AlarmManager sonra devam etmeyecektir. Ancak, cihaz yeniden başlatıldığında bildirimleri otomatik olarak yeniden zamanlamanız için uygulamanızı tasarlayabilirsiniz. Daha fazla bilgi için developer.android.com'de yinelenen alarmları zamanlama bölümünde cihaz yeniden başlatıldığında alarm başlatma bölümüne bakın. Android'de arka plan işleme hakkında bilgi için bkz . developer.android.com üzerinde arka plan işleme kılavuzu.

Yayın alıcıları hakkında daha fazla bilgi için bkz . Xamarin.Android'de Yayın Alıcıları.

Android'de gelen bildirimleri işleme

Sınıfın MainActivity gelen bildirimleri algılaması ve örneğe bildirmesi AndroidNotificationManager gerekir. Activity sınıfındaki MainActivity özniteliği değerini LaunchMode.SingleTopbelirtmelidirLaunchMode:

[Activity(
        //...
        LaunchMode = LaunchMode.SingleTop]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        // ...
    }

Mod, SingleTop uygulama ön plandayken birden Activity çok örneğinin başlatılmasını engeller. Bu LaunchMode , daha karmaşık bildirim senaryolarında birden çok etkinlik başlatan uygulamalar için uygun olmayabilir. Numaralandırma değerleri hakkında LaunchMode daha fazla bilgi için bkz . Android Activity LaunchMode.

MainActivity sınıfında, gelen bildirimleri alacak şekilde değiştirilir:

protected override void OnCreate(Bundle savedInstanceState)
{
    // ...

    global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
    LoadApplication(new App());
    CreateNotificationFromIntent(Intent);
}

protected override void OnNewIntent(Intent intent)
{
    CreateNotificationFromIntent(intent);
}

void CreateNotificationFromIntent(Intent intent)
{
    if (intent?.Extras != null)
    {
        string title = intent.GetStringExtra(AndroidNotificationManager.TitleKey);
        string message = intent.GetStringExtra(AndroidNotificationManager.MessageKey);
        DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
    }
}

yöntemi, CreateNotificationFromIntent bağımsız değişkenden intent bildirim verilerini ayıklar AndroidNotificationManager ve yöntemini kullanarak ReceiveNotification öğesine sağlar. CreateNotificationFromIntent yöntemi hem yönteminden hem de OnCreate yönteminden çağrılırOnNewIntent:

  • Uygulama bildirim verileriyle başlatıldığında, Intent veriler yöntemine OnCreate geçirilir.
  • Uygulama zaten ön plandaysa, Intent veriler yöntemine OnNewIntent geçirilir.

Android, bildirimler için birçok gelişmiş seçenek sunar. Daha fazla bilgi için bkz . Xamarin.Android'de bildirimler.

iOS arabirim uygulamasını oluşturma

Xamarin.Forms Uygulamanın iOS'ta bildirim gönderip alması için uygulamanın uygulamasını INotificationManagersağlaması gerekir.

iOSNotificationManager sınıfını oluşturma

iOSNotificationManager sınıfı arabirimini INotificationManager uygular:

using System;
using Foundation;
using UserNotifications;
using Xamarin.Forms;

[assembly: Dependency(typeof(LocalNotifications.iOS.iOSNotificationManager))]
namespace LocalNotifications.iOS
{
    public class iOSNotificationManager : INotificationManager
    {
        int messageId = 0;
        bool hasNotificationsPermission;
        public event EventHandler NotificationReceived;

        public void Initialize()
        {
            // request the permission to use local notifications
            UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
            {
                hasNotificationsPermission = approved;
            });
        }

        public void SendNotification(string title, string message, DateTime? notifyTime = null)
        {
            // EARLY OUT: app doesn't have permissions
            if (!hasNotificationsPermission)
            {
                return;
            }

            messageId++;

            var content = new UNMutableNotificationContent()
            {
                Title = title,
                Subtitle = "",
                Body = message,
                Badge = 1
            };            

            UNNotificationTrigger trigger;
            if (notifyTime != null)
            {
                // Create a calendar-based trigger.
                trigger = UNCalendarNotificationTrigger.CreateTrigger(GetNSDateComponents(notifyTime.Value), false);
            }
            else
            {
                // Create a time-based trigger, interval is in seconds and must be greater than 0.
                trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.25, false);
            }                      

            var request = UNNotificationRequest.FromIdentifier(messageId.ToString(), content, trigger);
            UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
            {
                if (err != null)
                {
                    throw new Exception($"Failed to schedule notification: {err}");
                }
            });
        }

        public void ReceiveNotification(string title, string message)
        {
            var args = new NotificationEventArgs()
            {
                Title = title,
                Message = message
            };
            NotificationReceived?.Invoke(null, args);
        }

        NSDateComponents GetNSDateComponents(DateTime dateTime)
        {
            return new NSDateComponents
            {
                Month = dateTime.Month,
                Day = dateTime.Day,
                Year = dateTime.Year,
                Hour = dateTime.Hour,
                Minute = dateTime.Minute,
                Second = dateTime.Second
            };
        }
    }
}

Ad assembly alanının üzerindeki özniteliği, arabirim uygulamasını ile DependencyServicekaydederINotificationManager.

iOS'ta, bildirim zamanlamayı denemeden önce bildirimleri kullanmak için izin istemeniz gerekir. yöntemi, Initialize yerel bildirimleri kullanmak için yetkilendirme isteğinde bulunur. yöntemi, SendNotification bildirim oluşturmak ve göndermek için gereken mantığı tanımlar. yöntemi ReceiveNotification , bir ileti alındığında iOS tarafından çağrılır ve olay işleyicisini çağırır.

Not

SendNotification yöntemi, bir nesne kullanarak veya tam olarak DateTime bir UNTimeIntervalNotificationTrigger nesne kullanarak hemen yerel bir UNCalendarNotificationTrigger bildirim oluşturur.

iOS'ta gelen bildirimleri işleme

iOS'ta, gelen iletileri işlemek için alt sınıflara UNUserNotificationCenterDelegate sahip bir temsilci oluşturmanız gerekir. Örnek uygulama bir iOSNotificationReceiver sınıf tanımlar:

public class iOSNotificationReceiver : UNUserNotificationCenterDelegate
{
    public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
    {
        ProcessNotification(notification);
        completionHandler(UNNotificationPresentationOptions.Alert);
    }

    void ProcessNotification(UNNotification notification)
    {
        string title = notification.Request.Content.Title;
        string message = notification.Request.Content.Body;

        DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
    }    
}

Bu sınıf, sınıfının bir örneğini iOSNotificationManager almak için öğesini DependencyService kullanır ve yöntemine ReceiveNotification gelen bildirim verileri sağlar.

SınıfınAppDelegate, uygulama başlatma sırasında temsilci olarak UNUserNotificationCenter bir iOSNotificationReceiver nesne belirtmesi gerekir. Bu, yönteminde FinishedLaunching gerçekleşir:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();

    UNUserNotificationCenter.Current.Delegate = new iOSNotificationReceiver();

    LoadApplication(new App());
    return base.FinishedLaunching(app, options);
}

iOS, bildirimler için birçok gelişmiş seçenek sunar. Daha fazla bilgi için bkz . Xamarin.iOS'ta Bildirimler.

Uygulamayı test etme

Platform projeleri arabirimin kayıtlı bir uygulamasını içerdiğinde INotificationManager , uygulama her iki platformda da test edilebilir. Uygulamayı çalıştırın ve bildirim oluşturmak için Bildirim Oluştur düğmelerinden birini tıklatın.

Android'de bildirimler bildirim alanında görünür. Bildirime dokunulduğunda uygulama bildirimi alır ve bir ileti görüntüler:

Android'de yerel bildirimler

iOS'ta, gelen bildirimler kullanıcı girişi gerektirmeden uygulama tarafından otomatik olarak alınır. Uygulama bildirimi alır ve bir ileti görüntüler:

iOS'ta yerel bildirimler