Bagikan melalui


Tutorial: Mengirim pemberitahuan push ke aplikasi .NET MAUI menggunakan Azure Notification Hubs melalui layanan backend

Jelajahi sampel. Jelajahi sampel

Pemberitahuan push mengirimkan informasi dari sistem backend ke aplikasi klien. Apple, Google, dan platform lainnya masing-masing memiliki Push Notification Service (PNS) mereka sendiri. Azure Notification Hubs memungkinkan Anda memusatkan pemberitahuan di seluruh platform sehingga aplikasi backend Anda dapat berkomunikasi dengan satu hub, yang menangani pendistribusian pemberitahuan ke setiap PNS.

Azure Notification Hubs mengharuskan aplikasi untuk mendaftar dengan hub dan secara opsional menentukan templat dan/atau berlangganan tag:

  • Melakukan pemasangan perangkat mengaitkan handle PNS ke pengidentifikasi di Azure Notification Hub. Untuk informasi selengkapnya tentang pendaftaran, lihat Manajemen pendaftaran.
  • Templat memungkinkan perangkat menentukan templat pesan berparameter. Pesan masuk dapat disesuaikan per perangkat. Untuk informasi selengkapnya, lihat Templat hub pemberitahuan.
  • Tag dapat digunakan untuk berlangganan kategori pesan seperti berita, olahraga, dan cuaca. Untuk informasi selengkapnya, lihat Perutean dan ekspresi tag.

Dalam tutorial ini Anda akan menggunakan Azure Notification Hubs untuk mengirim pemberitahuan push ke aplikasi .NET Multi-platform App UI (.NET MAUI) yang menargetkan Android dan iOS. Backend ASP.NET Core Web API digunakan untuk menangani pendaftaran perangkat untuk klien, dan untuk memulai pemberitahuan push. Operasi ini ditangani menggunakan paket NuGet Microsoft.Azure.NotificationHubs . Untuk informasi selengkapnya tentang pendekatan keseluruhan, lihat Manajemen pendaftaran dari backend.

Di tutorial ini, Anda akan:

  • Menyiapkan layanan pemberitahuan push dan Azure Notification Hub.
  • Buat aplikasi backend ASP.NET Core WebAPI.
  • Buat aplikasi .NET MAUI.
  • Konfigurasikan aplikasi Android untuk pemberitahuan push.
  • Konfigurasikan aplikasi iOS untuk pemberitahuan push.
  • Menguji aplikasi.
  • Memecahkan segala masalah penyiapan dan konfigurasi.

Prasyarat

Untuk menyelesaikan tutorial ini, Anda memerlukan:

  • Akun Azure dengan langganan aktif.
  • PC atau Mac yang menjalankan versi terbaru Visual Studio/Visual Studio Code dengan beban kerja pengembangan UI Aplikasi Multi-platform .NET dan beban kerja pengembangan ASP.NET dan web yang diinstal.

Untuk Android, Anda harus memiliki:

  • Pengembang membuka kunci perangkat fisik, atau emulator, yang menjalankan API 26+ dengan Google Play Services terinstal.

Untuk iOS, Anda harus memiliki:

  • Akun pengembang Apple aktif.
  • Mac yang menjalankan Xcode, bersama dengan sertifikat pengembang valid yang diinstal ke rantai kunci Anda.

Kemudian, di iOS Anda harus memiliki:

  • Simulator iOS 16+ yang berjalan di macOS 13+ di komputer Mac dengan prosesor Apple silicon atau T2.

    ATAU

  • Perangkat iOS fisik yang terdaftar ke akun pengembang Anda (menjalankan iOS 13.0+).

  • Perangkat fisik Anda terdaftar di akun pengembang Apple Anda, dan terkait dengan sertifikat Anda.

Penting

Simulator iOS mendukung pemberitahuan jarak jauh di iOS 16+ saat berjalan di macOS 13+ di komputer Mac dengan prosesor Apple silicon atau T2. Jika Anda tidak memenuhi persyaratan perangkat keras ini, Anda memerlukan akun pengembang Apple aktif dan perangkat fisik.

Untuk mengikuti tutorial ini, Anda harus memiliki keakraban dengan:

Meskipun tutorial ini menargetkan Visual Studio, Anda dapat mengikutinya menggunakan Visual Studio Code di PC atau Mac. Namun, akan ada beberapa perbedaan yang perlu direkonsiliasi. Misalnya, deskripsi antarmuka pengguna dan alur kerja, nama templat, dan konfigurasi lingkungan.

Menyiapkan layanan pemberitahuan push dan Azure Notification Hub

Di bagian ini, Anda akan menyiapkan Firebase Cloud Messaging dan Apple Push Notification Services (APNS). Anda kemudian akan membuat dan mengonfigurasi Azure Notification Hub untuk bekerja dengan layanan ini.

Membuat proyek Firebase

Untuk membuat proyek Firebase:

  1. Di browser web, masuk ke firebase console.

  2. Di konsol Firebase, pilih tombol Tambahkan proyek dan buat proyek Firebase baru, masukkan PushDemo sebagai Nama proyek.

    Catatan

    Sebuah nama yang unik akan dibuat untuk Anda. Secara default ini terdiri dari varian huruf kecil dari nama yang Anda berikan ditambah angka yang dihasilkan yang dipisahkan oleh tanda hubung. Anda dapat mengubah ini jika diinginkan, asalkan pengeditan Anda masih unik secara global.

  3. Setelah proyek Anda dibuat, pilih logo Android untuk menambahkan Firebase ke aplikasi Android:

    Cuplikan layar menambahkan Firebase ke aplikasi Android di konsol Firebase Cloud Messaging.

  4. Di halaman Tambahkan Firebase ke aplikasi Android Anda, masukkan nama untuk paket Anda, secara opsional nama panggilan aplikasi, dan pilih tombol Daftarkan aplikasi :

    Cuplikan layar mendaftarkan aplikasi Android Anda dengan Firebase.

  5. Di halaman Tambahkan Firebase ke aplikasi Android Anda, pilih tombol Unduh google-services.json dan simpan file ke folder lokal sebelum memilih tombol Berikutnya :

    Cuplikan layar mengunduh file JSON layanan google.

  6. Di halaman Tambahkan Firebase ke aplikasi Android Anda, pilih tombol Berikutnya .

  7. Di halaman Tambahkan Firebase ke aplikasi Android Anda, pilih tombol Lanjutkan ke konsol .

  8. Di konsol Firebase, pilih ikon Gambaran Umum Proyek lalu pilih Pengaturan proyek:

    Cuplikan layar memilih pengaturan proyek di konsol Firebase Cloud Messaging.

  9. Di pengaturan Proyek, pilih tab Pesan Cloud. Anda akan melihat bahwa Firebase Cloud Messaging API (V1) diaktifkan:

    Cuplikan layar mengonfirmasi bahwa Firebase Cloud Messaging V1 diaktifkan.

  10. Di pengaturan Proyek, pilih tab Akun layanan lalu pilih tombol Buat kunci privat baru.

  11. Dalam dialog Buat kunci privat baru, pilih tombol Buat kunci:

    Cuplikan layar pembuatan kunci privat baru di konsol Firebase Cloud Messaging.

    File JSON akan diunduh, yang akan berisi nilai yang akan Anda masukkan ke Azure Notification Hub Anda.

Daftarkan aplikasi iOS Anda untuk pemberitahuan push

Untuk mengirim pemberitahuan push ke app iOS, Anda harus mendaftarkan aplikasi dengan Apple dan mendaftar untuk pemberitahuan push. Ini dapat dicapai dengan melakukan langkah-langkah dalam dokumentasi Azure Notification Hub berikut:

Jika Anda ingin menerima pemberitahuan push di perangkat fisik, Anda juga harus membuat profil provisi.

Penting

Untuk menerima pemberitahuan latar belakang di iOS, Anda harus menambahkan mode latar belakang pemberitahuan jarak jauh ke aplikasi Anda. Untuk informasi selengkapnya, lihat Mengaktifkan kemampuan pemberitahuan jarak jauh pada developer.apple.com.

Membuat Azure Notification Hub

Untuk membuat hub pemberitahuan di portal Azure:

  1. Di browser web, masuk ke portal Azure.
  2. Di portal Azure, klik tombol Buat sumber daya lalu cari dan pilih Notification Hub sebelum memilih tombol Buat.
  3. Di halaman Notification Hub , lakukan langkah-langkah berikut:
    1. Di bidang Langganan, pilih nama langganan Azure yang ingin Anda gunakan, lalu pilih grup sumber daya yang sudah ada, atau buat yang baru.

    2. Di bidang Detail Namespace, masukkan nama unik untuk namespace baru.

    3. Di bidang Detail Hub Pemberitahuan, ketik nama untuk hub pemberitahuan. Ini diperlukan karena namespace berisi satu atau beberapa hub pemberitahuan.

    4. Di menu drop-down Lokasi, pilih nilai yang menentukan lokasi tempat Anda ingin membuat hub pemberitahuan.

    5. Tinjau opsi Zona Ketersediaan. Jika Anda memilih wilayah yang memiliki zona ketersediaan, kotak centang dipilih secara default.

      Catatan

      Zona ketersediaan adalah fitur berbayar, sehingga biaya tambahan ditambahkan ke tingkat Anda.

    6. Pilih opsi Pemulihan bencana: tidak ada, wilayah pemulihan yang dipasangkan, atau wilayah pemulihan yang fleksibel. Jika Anda memilih Wilayah pemulihan berpasangan, wilayah failover akan ditampilkan. Jika Anda memilih Wilayah pemulihan fleksibel, gunakan menu drop-down untuk memilih dari daftar wilayah pemulihan.

    7. Pilih tombol Buat. Hub pemberitahuan akan dibuat.

  4. Di portal Azure, telusuri ke hub pemberitahuan yang baru dibuat lalu ke bilah Kelola > Kebijakan Akses.
  5. Di bilah Kebijakan Akses, catat string koneksi untuk kebijakan DefaultFullSharedAccessSignature tersebut. Anda akan memerlukan ini nanti saat membangun layanan backend yang berkomunikasi dengan hub pemberitahuan Anda.

Untuk informasi selengkapnya tentang membuat hub pemberitahuan, lihat Membuat hub pemberitahuan Azure di portal Azure.

Mengonfigurasi Firebase Cloud Messaging pada hub pemberitahuan

Untuk mengonfigurasi hub pemberitahuan Anda untuk berkomunikasi dengan Firebase Cloud Messaging:

  1. Di portal Azure, telusuri ke hub pemberitahuan Anda dan pilih bilah Pengaturan > Google (FCM v1).

  2. Di bilah Google (FCM v1), masukkan nilai untuk Kunci Privat, Email Klien, dan ID Proyek. Nilai-nilai ini dapat ditemukan dalam file JSON kunci privat yang Anda unduh dari Firebase Cloud Messaging:

    Bidang Microsoft Azure Kunci JSON Contoh nilai JSON
    Kunci privat private_key Nilai ini harus dimulai dengan -----BEGIN PRIVATE KEY-----\n dan diakhiri dengan -----END PRIVATE KEY-----\n.
    Email Klien client_email firebase-adminsdk-55sfg@pushdemo-d6ab2.iam.gserviceaccount.com
    ID Proyek project_id pushdemo-d6ab2
  3. Di bilah Google (FCM v1), pilih tombol Simpan .

Mengonfigurasi Apple Push Notification Service di pusat notifikasi

Di portal Azure, telusuri ke hub pemberitahuan Anda dan pilih bilah Pengaturan > Apple (APNS). Kemudian ikuti langkah-langkah yang sesuai berdasarkan pendekatan yang Anda pilih sebelumnya saat membuat sertifikat untuk hub pemberitahuan.

Penting

Saat mengatur Mode Aplikasi, hanya pilih Produksi jika Anda ingin mengirim pemberitahuan push kepada pengguna yang telah membeli aplikasi Anda dari toko.

Opsi 1 - Gunakan sertifikat push .p12

  1. Di bilah Apple (APNS), pilih mode autentikasi sertifikat.
  2. Pada bilah Apple (APNS), pilih ikon file di samping bidang Unggah Sertifikat. Kemudian pilih file .p12 yang Anda ekspor sebelumnya dan unggah.
  3. Di bilah Apple (APNS), masukkan kata sandi sertifikat ke bidang Kata Sandi jika diperlukan.
  4. Di bilah Apple (APNS), pilih mode aplikasi Sandbox .
  5. Di bilah Apple (APNS), pilih tombol Simpan.

Opsi 2 - Gunakan autentikasi berbasis token

  1. Di tab Apple (APNS), pilih mode autentikasi Token.
  2. Di bilah Apple (APNS), masukkan nilai yang sebelumnya Anda peroleh untuk bidang Key Id, Bundle Id, Team Id, dan Token.
  3. Di halaman Apple (APNS), pilih mode aplikasi Sandbox.
  4. Di bilah Apple (APNS), pilih tombol Simpan.

Membuat aplikasi backend ASP.NET Core Web API

Di bagian ini Anda akan membuat backend ASP.NET Core Web API untuk menangani penginstalan perangkat dan mengirim pemberitahuan ke aplikasi .NET MAUI.

Membuat proyek API web

Untuk membuat proyek API web:

  1. Di Visual Studio, buat proyek ASP.NET Core Web API :

    Cuplikan layar pembuatan proyek ASP.NET Core Web API baru di Visual Studio.

  2. Dalam dialog Konfigurasikan proyek baru Anda, beri nama proyek PushNotificationsAPI.

  3. Dalam dialog Informasi tambahan pastikan bahwa kotak centang Konfigurasi untuk HTTPS dan Gunakan pengontrol diaktifkan:

    Cuplikan layar mengonfigurasi proyek ASP.NET Core Web API di Visual Studio.

  4. Setelah proyek dibuat, tekan F5 untuk menjalankan proyek.

    Aplikasi saat ini dikonfigurasi untuk menggunakan WeatherForecastController sebagai launchUrl, yang diatur dalam file Properties\launchSettings.json . Aplikasi ini akan diluncurkan di browser web, dan akan menampilkan beberapa data JSON.

    Penting

    Saat Anda menjalankan proyek ASP.NET Core yang menggunakan HTTPS, Visual Studio akan mendeteksi apakah sertifikat pengembangan ASP.NET Core HTTPS diinstal ke penyimpanan sertifikat pengguna lokal Anda, dan akan menawarkan untuk menginstalnya dan mempercayainya jika hilang.

  5. Tutup browser web.

  6. Di Penjelajah Solusi, perluas folder Pengontrol dan hapus WeatherForecastController.cs.

  7. Di Penjelajah Solusi, di akar proyek, hapus WeatherForecast.cs.

  8. Buka jendela perintah, dan navigasi ke direktori yang berisi file proyek. Kemudian, jalankan perintah berikut:

    dotnet user-secrets init
    dotnet user-secrets set "NotificationHub:Name" <value>
    dotnet user-secrets set "NotificationHub:ConnectionString" "<value>"
    

    Gantilah nilai placeholder dengan nama Azure Notification Hub Anda dan nilai string koneksi Anda sendiri. Ini dapat ditemukan di lokasi berikut di Azure Notification Hub Anda:

    Nilai konfigurasi Lokasi
    NotificationHub:Name Lihat Nama di ringkasan Esensial di bagian atas halaman Gambaran Umum .
    NotificationHub:ConnectionString Lihat DefaultFullSharedAccessSignature* di halaman Kebijakan Akses.

    Ini menyiapkan nilai konfigurasi lokal menggunakan alat Secret Manager. Ini memisahkan rahasia Azure Notification Hub Anda dari solusi Visual Studio, untuk memastikan bahwa rahasia tersebut tidak berakhir di kontrol sumber.

    Tip

    Untuk skenario produksi, pertimbangkan layanan seperti Azure KeyVault untuk menyimpan string koneksi dengan aman.

Mengautentikasi klien dengan kunci API

Untuk mengautentikasi klien dengan kunci API:

  1. Buka jendela perintah, dan navigasi ke direktori yang berisi file proyek. Kemudian, jalankan perintah berikut:

    dotnet user-secrets set "Authentication:ApiKey" <value>
    

    Ganti nilai tempat penampung dengan kunci API Anda, yang dapat berupa nilai apa pun.

  2. Di Visual Studio, tambahkan folder baru bernama Autentikasi ke proyek Anda, lalu tambahkan kelas baru bernama ApiKeyAuthOptions ke folder Autentikasi dan ganti kodenya dengan kode berikut:

    using Microsoft.AspNetCore.Authentication;
    
    namespace PushNotificationsAPI.Authentication;
    
    public class ApiKeyAuthOptions : AuthenticationSchemeOptions
    {
        public const string DefaultScheme = "ApiKey";
        public string Scheme => DefaultScheme;
        public string ApiKey { get; set; }
    }
    
  3. Di Visual Studio, tambahkan kelas baru bernama ApiKeyAuthHandler ke folder Autentikasi dan ganti kodenya dengan kode berikut:

    using Microsoft.AspNetCore.Authentication;
    using Microsoft.Extensions.Options;
    using System.Security.Claims;
    using System.Text.Encodings.Web;
    
    namespace PushNotificationsAPI.Authentication;
    
    public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions>
    {
        const string ApiKeyIdentifier = "apikey";
    
        public ApiKeyAuthHandler(
            IOptionsMonitor<ApiKeyAuthOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder)
            : base(options, logger, encoder)
        {
        }
    
        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            string key = string.Empty;
    
            if (Request.Headers[ApiKeyIdentifier].Any())
            {
                key = Request.Headers[ApiKeyIdentifier].FirstOrDefault();
            }
            else if (Request.Query.ContainsKey(ApiKeyIdentifier))
            {
                if (Request.Query.TryGetValue(ApiKeyIdentifier, out var queryKey))
                    key = queryKey;
            }
    
            if (string.IsNullOrWhiteSpace(key))
                return Task.FromResult(AuthenticateResult.Fail("No api key provided"));
    
            if (!string.Equals(key, Options.ApiKey, StringComparison.Ordinal))
                return Task.FromResult(AuthenticateResult.Fail("Invalid api key."));
    
            var identities = new List<ClaimsIdentity>
            {
                new ClaimsIdentity("ApiKeyIdentity")
            };
    
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identities), Options.Scheme);
    
            return Task.FromResult(AuthenticateResult.Success(ticket));
        }
    }
    

    Handler autentikasi adalah jenis yang mengimplementasikan perilaku skema, yang dalam hal ini adalah skema kunci API kustom.

  4. Di Visual Studio, tambahkan kelas baru bernama AuthenticationBuilderExtensions ke folder Autentikasi dan ganti kodenya dengan kode berikut:

    using Microsoft.AspNetCore.Authentication;
    
    namespace PushNotificationsAPI.Authentication;
    
    public static class AuthenticationBuilderExtensions
    {
      public static AuthenticationBuilder AddApiKeyAuth(
          this AuthenticationBuilder builder,
          Action<ApiKeyAuthOptions> configureOptions)
        {
            return builder
                .AddScheme<ApiKeyAuthOptions, ApiKeyAuthHandler>(
                ApiKeyAuthOptions.DefaultScheme,
                configureOptions);
        }
    }
    

    Metode ekstensi ini akan digunakan untuk menyederhanakan kode konfigurasi middleware di Program.cs.

  5. Di Visual Studio, buka Program.cs dan perbarui kode untuk mengonfigurasi autentikasi kunci API di bawah panggilan ke builder.Services.AddControllers metode :

    using PushNotificationsAPI.Authentication;
    
    builder.Services.AddControllers();
    
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
        options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
    }).AddApiKeyAuth(builder.Configuration.GetSection("Authentication").Bind);
    
  6. Di Program.cs, perbarui kode di bawah komentar // Configure the HTTP request pipeline untuk memanggil metode ekstensi UseRouting, UseAuthentication, dan MapControllers.

    // Configure the HTTP request pipeline.
    
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    
    app.Run();
    

    Metode UseAuthentication ekstensi mendaftarkan middleware yang menggunakan skema autentikasi yang terdaftar sebelumnya. UseAuthentication harus dipanggil sebelum middleware apa pun yang bergantung pada pengguna yang diautentikasi.

    Catatan

    Meskipun kunci API tidak seaman token, itu akan cukup untuk tutorial ini, dan mudah dikonfigurasi melalui ASP.NET Middleware.

Menambahkan dan mengonfigurasi layanan

Untuk menambahkan dan mengonfigurasi layanan di aplikasi backend API web Anda:

  1. Di Visual Studio, tambahkan paket NuGet Microsoft.Azure.NotificationHubs ke proyek Anda. Paket NuGet ini digunakan untuk mengakses hub pemberitahuan Anda, yang dienkapsulasi dalam layanan.

  2. Di Visual Studio, tambahkan folder baru bernama Model ke proyek Anda, lalu tambahkan kelas baru bernama PushTemplates ke folder Model dan ganti kodenya dengan kode berikut:

    namespace PushNotificationsAPI.Models;
    
    public class PushTemplates
    {
        public class Generic
        {
            public const string Android = "{ \"message\" : { \"notification\" : { \"title\" : \"PushDemo\", \"body\" : \"$(alertMessage)\"}, \"data\" : { \"action\" : \"$(alertAction)\" } } }";
            public const string iOS = "{ \"aps\" : {\"alert\" : \"$(alertMessage)\"}, \"action\" : \"$(alertAction)\" }";
        }
    
        public class Silent
        {
            public const string Android = "{ \"message\" : { \"data\" : {\"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\"} } }";
            public const string iOS = "{ \"aps\" : {\"content-available\" : 1, \"apns-priority\": 5, \"sound\" : \"\", \"badge\" : 0}, \"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\" }";
        }
    }
    

    Kelas PushTemplates berisi payload pemberitahuan yang ditokenisasi untuk pemberitahuan push generik dan senyap. Payload ini didefinisikan di luar penginstalan untuk memungkinkan eksperimen tanpa harus memperbarui penginstalan yang ada melalui layanan. Menangani perubahan pada penginstalan dengan cara ini di luar cakupan untuk artikel ini. Dalam skenario produk, pertimbangkan untuk menggunakan templat kustom.

  3. Di Visual Studio, tambahkan kelas baru bernama DeviceInstallation ke folder Model dan ganti kodenya dengan kode berikut:

    using System.ComponentModel.DataAnnotations;
    
    namespace PushNotificationsAPI.Models;
    
    public class DeviceInstallation
    {
        [Required]
        public string InstallationId { get; set; }
    
        [Required]
        public string Platform { get; set; }
    
        [Required]
        public string PushChannel { get; set; }
    
        public IList<string> Tags { get; set; } = Array.Empty<string>();
    }
    
  4. Di Visual Studio, tambahkan kelas baru bernama NotificationRequest ke folder Model dan ganti kodenya dengan kode berikut:

    namespace PushNotificationsAPI.Models;
    
    public class NotificationRequest
    {
        public string Text { get; set; }
        public string Action { get; set; }
        public string[] Tags { get; set; } = Array.Empty<string>();
        public bool Silent { get; set; }
    }
    
  5. Di Visual Studio, tambahkan kelas baru bernama NotificationHubOptions ke folder Model dan ganti kodenya dengan kode berikut:

    using System.ComponentModel.DataAnnotations;
    
    namespace PushNotificationsAPI.Models;
    
    public class NotificationHubOptions
    {
        [Required]
        public string Name { get; set; }
    
        [Required]
        public string ConnectionString { get; set; }
    }
    
  6. Di Visual Studio, tambahkan folder baru bernama Layanan ke proyek Anda, lalu tambahkan antarmuka baru bernama INotificationService ke folder Layanan dan ganti kodenya dengan kode berikut:

    using PushNotificationsAPI.Models;
    
    namespace PushNotificationsAPI.Services;
    
    public interface INotificationService
    {
        Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token);
        Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token);
        Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token);
    }
    
  7. Di Visual Studio, tambahkan kelas baru bernama NotificationHubService ke folder Layanan dan ganti kodenya dengan kode berikut:

    using Microsoft.Extensions.Options;
    using Microsoft.Azure.NotificationHubs;
    using PushNotificationsAPI.Models;
    
    namespace PushNotificationsAPI.Services;
    
    public class NotificationHubService : INotificationService
    {
        readonly NotificationHubClient _hub;
        readonly Dictionary<string, NotificationPlatform> _installationPlatform;
        readonly ILogger<NotificationHubService> _logger;
    
        public NotificationHubService(IOptions<NotificationHubOptions> options, ILogger<NotificationHubService> logger)
        {
            _logger = logger;
            _hub = NotificationHubClient.CreateClientFromConnectionString(options.Value.ConnectionString, options.Value.Name);
    
            _installationPlatform = new Dictionary<string, NotificationPlatform>
            {
                { nameof(NotificationPlatform.Apns).ToLower(), NotificationPlatform.Apns },
                { nameof(NotificationPlatform.FcmV1).ToLower(), NotificationPlatform.FcmV1 }
            };
        }
    
        public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token)
        {
            if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) ||
                string.IsNullOrWhiteSpace(deviceInstallation?.Platform) ||
                string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel))
                return false;
    
            var installation = new Installation()
            {
                InstallationId = deviceInstallation.InstallationId,
                PushChannel = deviceInstallation.PushChannel,
                Tags = deviceInstallation.Tags
            };
    
            if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform))
                installation.Platform = platform;
            else
                return false;
    
            try
            {
                await _hub.CreateOrUpdateInstallationAsync(installation, token);
            }
            catch
            {
                return false;
            }
    
            return true;
        }
    
        public async Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token)
        {
            if (string.IsNullOrWhiteSpace(installationId))
                return false;
    
            try
            {
                await _hub.DeleteInstallationAsync(installationId, token);
            }
            catch
            {
                return false;
            }
    
            return true;
        }
    
        public async Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token)
        {
            if ((notificationRequest.Silent &&
                string.IsNullOrWhiteSpace(notificationRequest?.Action)) ||
                (!notificationRequest.Silent &&
                (string.IsNullOrWhiteSpace(notificationRequest?.Text)) ||
                string.IsNullOrWhiteSpace(notificationRequest?.Action)))
                return false;
    
            var androidPushTemplate = notificationRequest.Silent ?
                PushTemplates.Silent.Android :
                PushTemplates.Generic.Android;
    
            var iOSPushTemplate = notificationRequest.Silent ?
                PushTemplates.Silent.iOS :
                PushTemplates.Generic.iOS;
    
            var androidPayload = PrepareNotificationPayload(
                androidPushTemplate,
                notificationRequest.Text,
                notificationRequest.Action);
    
            var iOSPayload = PrepareNotificationPayload(
                iOSPushTemplate,
                notificationRequest.Text,
                notificationRequest.Action);
    
            try
            {
                if (notificationRequest.Tags.Length == 0)
                {
                    // This will broadcast to all users registered in the notification hub
                    await SendPlatformNotificationsAsync(androidPayload, iOSPayload, token);
                }
                else if (notificationRequest.Tags.Length <= 20)
                {
                    await SendPlatformNotificationsAsync(androidPayload, iOSPayload, notificationRequest.Tags, token);
                }
                else
                {
                    var notificationTasks = notificationRequest.Tags
                        .Select((value, index) => (value, index))
                        .GroupBy(g => g.index / 20, i => i.value)
                        .Select(tags => SendPlatformNotificationsAsync(androidPayload, iOSPayload, tags, token));
    
                    await Task.WhenAll(notificationTasks);
                }
    
                return true;
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Unexpected error sending notification");
                return false;
            }
        }
    
        string PrepareNotificationPayload(string template, string text, string action) => template
            .Replace("$(alertMessage)", text, StringComparison.InvariantCulture)
            .Replace("$(alertAction)", action, StringComparison.InvariantCulture);
    
        Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, CancellationToken token)
        {
            var sendTasks = new Task[]
            {
                _hub.SendFcmV1NativeNotificationAsync(androidPayload, token),
                _hub.SendAppleNativeNotificationAsync(iOSPayload, token)
            };
    
            return Task.WhenAll(sendTasks);
        }
    
        Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, IEnumerable<string> tags, CancellationToken token)
        {
            var sendTasks = new Task[]
            {
                _hub.SendFcmV1NativeNotificationAsync(androidPayload, tags, token),
                _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token)
            };
    
            return Task.WhenAll(sendTasks);
        }
    }
    

    Ekspresi tag yang disediakan untuk metode SendTemplateNotificationsAsync dibatasi hingga 20 tag jika hanya berisi OR. Jika tidak, mereka dibatasi hingga 6 tag. Untuk informasi selengkapnya, lihat Perutean dan Ekspresi Tag.

  8. Di Visual Studio, buka Program.cs dan perbarui kode untuk menambahkan NotificationHubService sebagai implementasi singleton INotificationService di bawah panggilan ke metode builder.Services.AddAuthentication.

    using PushNotificationsAPI.Authentication;
    using PushNotificationsAPI.Services;
    using PushNotificationsAPI.Models;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
        options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
    }).AddApiKeyAuth(builder.Configuration.GetSection("Authentication").Bind);
    
    builder.Services.AddSingleton<INotificationService, NotificationHubService>();
    builder.Services.AddOptions<NotificationHubOptions>()
        .Configure(builder.Configuration.GetSection("NotificationHub").Bind)
        .ValidateDataAnnotations();
    
    var app = builder.Build();
    

Membuat REST API pemberitahuan

Untuk membuat REST API pemberitahuan:

  1. Di Visual Studio, tambahkan Pengontrol baru bernama NotificationsController ke folder Pengontrol.

    Tip

    Pilih templat Pengontrol API dengan tindakan baca/tulis.

  2. Dalam file NotificationsController.cs, tambahkan pernyataan berikut using di bagian atas file:

    using System.ComponentModel.DataAnnotations;
    using System.Net;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using PushNotificationsAPI.Models;
    using PushNotificationsAPI.Services;
    
  3. Dalam file NotificationsController.cs, tambahkan Authorize atribut ke NotificationsController kelas :

    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class NotificationsController : ControllerBase
    
  4. Dalam file NotificationsController.cs, perbarui NotificationsContoller konstruktor untuk menerima instans INotificationService terdaftar sebagai argumen, dan tetapkan ke anggota readonly:

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  5. Dalam file NotificationsContoller.cs, ganti semua metode dengan kode berikut:

    [HttpPut]
    [Route("installations")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<IActionResult> UpdateInstallation(
        [Required] DeviceInstallation deviceInstallation)
    {
        var success = await _notificationService
            .CreateOrUpdateInstallationAsync(deviceInstallation, HttpContext.RequestAborted);
    
        if (!success)
            return new UnprocessableEntityResult();
    
        return new OkResult();
    }
    
    [HttpDelete()]
    [Route("installations/{installationId}")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<ActionResult> DeleteInstallation(
        [Required][FromRoute] string installationId)
    {
        // Probably want to ensure deletion even if the connection is broken
        var success = await _notificationService
            .DeleteInstallationByIdAsync(installationId, CancellationToken.None);
    
        if (!success)
            return new UnprocessableEntityResult();
    
        return new OkResult();
    }
    
    [HttpPost]
    [Route("requests")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<IActionResult> RequestPush(
        [Required] NotificationRequest notificationRequest)
    {
        if ((notificationRequest.Silent &&
            string.IsNullOrWhiteSpace(notificationRequest?.Action)) ||
            (!notificationRequest.Silent &&
            string.IsNullOrWhiteSpace(notificationRequest?.Text)))
            return new BadRequestResult();
    
        var success = await _notificationService
            .RequestNotificationAsync(notificationRequest, HttpContext.RequestAborted);
    
        if (!success)
            return new UnprocessableEntityResult();
    
        return new OkResult();
    }
    
  6. Dalam file Properti/launchSettings.json, ubah launchUrl properti untuk setiap profil dari weatherforecast menjadi api/notifications.

Membuat aplikasi API

Sekarang Anda akan membuat aplikasi API di Azure App Service untuk menghosting layanan backend Anda. Ini dapat dicapai langsung dari Visual Studio atau Visual Studio Code, dengan Azure CLI, Azure PowerShell, Azure Developer CLI, dan melalui Portal Microsoft Azure. Untuk informasi selengkapnya, lihat Menerbitkan aplikasi web Anda.

Untuk membuat aplikasi API di portal Azure:

  1. Di browser web, masuk ke portal Azure.

  2. Di portal Azure, klik tombol Buat sumber daya lalu cari dan pilih Aplikasi API sebelum memilih tombol Buat.

  3. Di halaman Buat Aplikasi API, perbarui bidang berikut sebelum memilih tombol Buat :

    Bidang Perbuatan
    Langganan Pilih langganan target yang sama dengan tempat Anda membuat hub pemberitahuan.
    Grup Sumber Daya Pilih grup sumber daya yang sama dengan tempat Anda membuat hub pemberitahuan.
    Nama Masukkan nama yang unik secara global.
    Tumpukan Runtime Pastikan bahwa versi terbaru .NET dipilih.
  4. Setelah Aplikasi API disediakan, navigasikan ke sumber daya.

  5. Pada halaman Gambaran Umum , catat nilai domain default. URL ini adalah titik akhir backend Anda yang akan digunakan dari aplikasi .NET MAUI Anda. URL akan menggunakan nama aplikasi API yang Anda tentukan, dengan format https://<app_name>.azurewebsites.net.

  6. Di portal Azure, telusuri ke bilah variabel Lingkungan Pengaturan > lalu pastikan bahwa tab Pengaturan aplikasi dipilih. Kemudian gunakan tombol Tambahkan untuk menambahkan pengaturan berikut:

    Nama Nilai
    Autentikasi:ApiKey <nilai_kunci_api>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Penting

    Pengaturan Authentication:ApiKey aplikasi telah ditambahkan untuk kesederhanaan. Untuk skenario produksi, pertimbangkan layanan seperti Azure KeyVault untuk menyimpan string koneksi dengan aman.

    Setelah semua pengaturan ini dimasukkan, pilih tombol Terapkan lalu tombol Konfirmasi .

Menerbitkan layanan backend

Untuk menerbitkan layanan backend Anda ke Azure App Service:

  1. Di Visual Studio, klik kanan proyek Anda dan pilih Terbitkan.
  2. Di dalam wizard Publish, pilih Azure lalu tombol Berikutnya.
  3. Di wizard Publikasikan, pilih Azure App Service (Windows) dan kemudian tombol Berikutnya.
  4. Di Panduan Terbitkan, ikuti proses autentikasi untuk menyambungkan Visual Studio ke langganan Azure Anda dan menerbitkan aplikasi.

Visual Studio membuat, mengemas, dan menerbitkan aplikasi ke Azure, lalu meluncurkan aplikasi di browser default Anda. Untuk informasi selengkapnya, lihat Menerbitkan aplikasi web ASP.NET.

Tip

Anda dapat mengunduh profil publikasi untuk aplikasi Anda dari bilah Gambaran Umum aplikasi API Anda di portal Azure lalu menggunakan profil di Visual Studio untuk menerbitkan aplikasi Anda.

Memvalidasi API yang diterbitkan

Untuk memeriksa apakah aplikasi API telah diterbitkan dengan benar, Anda harus menggunakan alat REST pilihan Anda untuk mengirim POST permintaan ke alamat berikut:

https://<app_name>.azurewebsites.net/api/notifications/requests

Catatan

Alamat dasarnya adalah https://<app_name>.azurewebsites.net.

Pastikan Anda mengonfigurasi header permintaan untuk menyertakan kunci apikey dan nilainya, atur isi ke mentah, dan gunakan konten JSON tempat penampung berikut:

{}

Anda harus menerima 400 Bad Request tanggapan dari layanan.

Catatan

Belum dimungkinkan untuk menguji API menggunakan data permintaan yang valid karena ini akan memerlukan informasi khusus platform dari aplikasi .NET MAUI.

Untuk informasi selengkapnya tentang memanggil REST API, lihat Menggunakan file .http di Visual Studio dan Menguji API web dengan Http Repl. Di Visual Studio Code, Klien REST dapat digunakan untuk menguji REST API.

Membuat aplikasi .NET MAUI

Di bagian ini, Anda akan membuat aplikasi .NET Multi-platform App UI (.NET MAUI) yang memungkinkan Anda mendaftar untuk menerima pemberitahuan push dari hub pemberitahuan melalui layanan backend, dan membatalkan pendaftaran.

Untuk membuat aplikasi .NET MAUI Anda:

  1. Di Visual Studio, buat aplikasi MAUI .NET baru bernama PushNotificationsDemo, menggunakan templat proyek Aplikasi .NET MAUI.

  2. Di Visual Studio, tambahkan folder baru bernama Model ke proyek .NET MAUI, lalu tambahkan kelas baru bernama DeviceInstallation ke folder Model dan ganti kodenya dengan kode berikut:

    using System.Text.Json.Serialization;
    
    namespace PushNotificationsDemo.Models;
    
    public class DeviceInstallation
    {
        [JsonPropertyName("installationId")]
        public string InstallationId { get; set; }
    
        [JsonPropertyName("platform")]
        public string Platform { get; set; }
    
        [JsonPropertyName("pushChannel")]
        public string PushChannel { get; set; }
    
        [JsonPropertyName("tags")]
        public List<string> Tags { get; set; } = new List<string>();
    }
    
  3. Di Visual Studio, tambahkan enumerasi bernama PushDemoAction ke folder Model dan ganti kodenya dengan kode berikut:

    namespace PushNotificationsDemo.Models;
    
    public enum PushDemoAction
    {
        ActionA,
        ActionB
    }
    
  4. Di Visual Studio, tambahkan folder baru bernama Services ke proyek .NET MAUI, lalu tambahkan antarmuka baru bernama IDeviceInstallationService ke folder Layanan dan ganti kodenya dengan kode berikut:

    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.Services;
    
    public interface IDeviceInstallationService
    {
        string Token { get; set; }
        bool NotificationsSupported { get; }
        string GetDeviceId();
        DeviceInstallation GetDeviceInstallation(params string[] tags);
    }
    

    Antarmuka ini akan diimplementasikan pada setiap platform nanti, untuk memberikan informasi yang DeviceInstallation diperlukan oleh layanan backend.

  5. Di Visual Studio, tambahkan antarmuka bernama INotificationRegistrationService ke folder Layanan dan ganti kodenya dengan kode berikut:

    namespace PushNotificationsDemo.Services;
    
    public interface INotificationRegistrationService
    {
        Task DeregisterDeviceAsync();
        Task RegisterDeviceAsync(params string[] tags);
        Task RefreshRegistrationAsync();
    }
    

    Antarmuka ini akan menangani interaksi antara klien dan layanan backend.

  6. Di Visual Studio, tambahkan antarmuka bernama INotificationActionService ke folder Layanan dan ganti kodenya dengan kode berikut:

    namespace PushNotificationsDemo.Services;
    
    public interface INotificationActionService
    {
        void TriggerAction(string action);
    }
    

    Antarmuka ini akan digunakan sebagai mekanisme sederhana untuk mempusatkan penanganan tindakan pemberitahuan.

  7. Di Visual Studio, tambahkan antarmuka bernama IPushDemoNotificationActionService ke folder Layanan dan ganti kodenya dengan kode berikut:

    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.Services;
    
    public interface IPushDemoNotificationActionService : INotificationActionService
    {
        event EventHandler<PushDemoAction> ActionTriggered;
    }
    

    IPushDemoNotificationActionService Jenis ini khusus untuk aplikasi ini, dan menggunakan enumerasi PushDemoAction untuk mengidentifikasi tindakan yang dipicu dengan pendekatan bertipe kuat.

  8. Di Visual Studio, tambahkan kelas bernama NotificationRegistrationService ke folder Layanan dan ganti kodenya dengan kode berikut:

    using System.Text;
    using System.Text.Json;
    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.Services;
    
    public class NotificationRegistrationService : INotificationRegistrationService
    {
        const string RequestUrl = "api/notifications/installations";
        const string CachedDeviceTokenKey = "cached_device_token";
        const string CachedTagsKey = "cached_tags";
    
        string _baseApiUrl;
        HttpClient _client;
        IDeviceInstallationService _deviceInstallationService;
    
        IDeviceInstallationService DeviceInstallationService =>
            _deviceInstallationService ?? (_deviceInstallationService = Application.Current.Windows[0].Page.Handler.MauiContext.Services.GetService<IDeviceInstallationService>());
    
        public NotificationRegistrationService(string baseApiUri, string apiKey)
        {
            _client = new HttpClient();
            _client.DefaultRequestHeaders.Add("Accept", "application/json");
            _client.DefaultRequestHeaders.Add("apikey", apiKey);
    
            _baseApiUrl = baseApiUri;
        }
    
        public async Task DeregisterDeviceAsync()
        {
            var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey)
                .ConfigureAwait(false);
    
            if (cachedToken == null)
                return;
    
            var deviceId = DeviceInstallationService?.GetDeviceId();
    
            if (string.IsNullOrWhiteSpace(deviceId))
                throw new Exception("Unable to resolve an ID for the device.");
    
            await SendAsync(HttpMethod.Delete, $"{RequestUrl}/{deviceId}")
                .ConfigureAwait(false);
    
            SecureStorage.Remove(CachedDeviceTokenKey);
            SecureStorage.Remove(CachedTagsKey);
        }
    
        public async Task RegisterDeviceAsync(params string[] tags)
        {
            var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags);
    
            await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation)
                .ConfigureAwait(false);
    
            await SecureStorage.SetAsync(CachedDeviceTokenKey, deviceInstallation.PushChannel)
                .ConfigureAwait(false);
    
            await SecureStorage.SetAsync(CachedTagsKey, JsonSerializer.Serialize(tags));
        }
    
        public async Task RefreshRegistrationAsync()
        {
            var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey)
                .ConfigureAwait(false);
    
            var serializedTags = await SecureStorage.GetAsync(CachedTagsKey)
                .ConfigureAwait(false);
    
            if (string.IsNullOrWhiteSpace(cachedToken) ||
                string.IsNullOrWhiteSpace(serializedTags) ||
                string.IsNullOrWhiteSpace(_deviceInstallationService.Token) ||
                cachedToken == DeviceInstallationService.Token)
                return;
    
            var tags = JsonSerializer.Deserialize<string[]>(serializedTags);
    
            await RegisterDeviceAsync(tags);
        }
    
        async Task SendAsync<T>(HttpMethod requestType, string requestUri, T obj)
        {
            string serializedContent = null;
    
            await Task.Run(() => serializedContent = JsonSerializer.Serialize(obj))
                .ConfigureAwait(false);
    
            await SendAsync(requestType, requestUri, serializedContent);
        }
    
        async Task SendAsync(HttpMethod requestType, string requestUri, string jsonRequest = null)
        {
            var request = new HttpRequestMessage(requestType, new Uri($"{_baseApiUrl}{requestUri}"));
    
            if (jsonRequest != null)
                request.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
    
            var response = await _client.SendAsync(request).ConfigureAwait(false);
    
            response.EnsureSuccessStatusCode();
        }
    }
    
  9. Di Visual Studio, tambahkan kelas bernama PushDemoNotificationActionService ke folder Layanan dan ganti kodenya dengan kode berikut:

    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.Services;
    
    public class PushDemoNotificationActionService : IPushDemoNotificationActionService
    {
        readonly Dictionary<string, PushDemoAction> _actionMappings = new Dictionary<string, PushDemoAction>
        {
            { "action_a", PushDemoAction.ActionA },
            { "action_b", PushDemoAction.ActionB }
        };
    
        public event EventHandler<PushDemoAction> ActionTriggered = delegate { };
    
        public void TriggerAction(string action)
        {
            if (!_actionMappings.TryGetValue(action, out var pushDemoAction))
                return;
    
            List<Exception> exceptions = new List<Exception>();
    
            foreach (var handler in ActionTriggered?.GetInvocationList())
            {
                try
                {
                    handler.DynamicInvoke(this, pushDemoAction);
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                }
            }
    
            if (exceptions.Any())
                throw new AggregateException(exceptions);
        }
    }
    
  10. Di Visual Studio, tambahkan kelas bernama Config ke akar proyek dan ganti kodenya dengan kode berikut:

    namespace PushNotificationsDemo;
    
    public static partial class Config
    {
        public static string ApiKey = "API_KEY";
        public static string BackendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT";
    }
    

    Kelas Config ini digunakan sebagai cara sederhana untuk menjaga rahasia Anda dari kontrol sumber. Anda dapat mengganti nilai-nilai ini sebagai bagian dari pembangunan otomatis atau mengambil alih mereka menggunakan kelas parsial lokal.

    Penting

    Saat menentukan alamat dasar di aplikasi .NET MAUI, pastikan alamat tersebut berakhir dengan /.

  11. Di Visual Studio, tambahkan kelas bernama Config.local_secrets ke akar proyek. Kemudian ganti kode dalam file Config.local_secrets.cs dengan kode berikut:

    namespace PushNotificationsDemo;
    
    public static partial class Config
    {
        static Config()
        {
            ApiKey = "<your_api_key>";
            BackendServiceEndpoint = "<your_api_app_url>";
        }
    }
    

    Ganti nilai tempat penampung dengan nilai yang Anda pilih ketika membuat layanan backend. BackendServiceEndpoint URL harus menggunakan format https://<api_app_name>.azurewebsites.net/.

    Tip

    Ingatlah untuk menambahkan *.local_secrets.* ke dalam file .gitignore Anda untuk menghindari memasukkan file ini ke dalam kontrol versi.

Buat antarmuka pengguna

Untuk membuat UI aplikasi:

  1. Di Visual Studio, buka MainPage.xaml dan ganti dan turunannya VerticalStackLayout dengan XAML berikut:

    <VerticalStackLayout Margin="20"
                         Spacing="6">
        <Button x:Name="registerButton"
                Text="Register"
                Clicked="OnRegisterButtonClicked" />
        <Button x:Name="deregisterButton"
                Text="Deregister"
                Clicked="OnDeregisterButtonClicked" />
    </VerticalStackLayout>
    
  2. Di Visual Studio, buka MainPage.xaml.cs dan tambahkan using pernyataan untuk PushNotificationsDemo.Services namespace:

    using PushNotificationsDemo.Services;
    
  3. Di MainPage.xaml.cs, tambahkan readonly bidang penopang untuk menyimpan referensi ke INotificationRegistrationService implementasi.

    readonly INotificationRegistrationService _notificationRegistrationService;
    
  4. MainPage Di konstruktor, selesaikan INotificationRegistrationService implementasi dan tetapkan ke _notificationRegistrationService bidang backing:

    public MainPage(INotificationRegistrationService service)
    {
        InitializeComponent();
    
        _notificationRegistrationService = service;
    }
    
  5. Implementasikan OnRegisterButtonClicked dan OnDeregisterButtonClicked penangan acara di dalam kelas MainPage, dengan memanggil metode register dan deregister yang sesuai pada objek INotificationRegistrationService.

    void OnRegisterButtonClicked(object sender, EventArgs e)
    {
        _notificationRegistrationService.RegisterDeviceAsync()
            .ContinueWith((task) =>
            {
                ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device registered");
            });
    }
    
    void OnDeregisterButtonClicked(object sender, EventArgs e)
    {
        _notificationRegistrationService.DeregisterDeviceAsync()
            .ContinueWith((task) =>
            {
                ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device deregistered");
            });
    }
    
    void ShowAlert(string message)
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            DisplayAlert("Push notifications demo", message, "OK")
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        });
    }
    
    void OnRegisterButtonClicked(object sender, EventArgs e)
    {
        _notificationRegistrationService.RegisterDeviceAsync()
            .ContinueWith((task) =>
            {
                ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device registered");
            });
    }
    
    void OnDeregisterButtonClicked(object sender, EventArgs e)
    {
        _notificationRegistrationService.DeregisterDeviceAsync()
            .ContinueWith((task) =>
            {
                ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device deregistered");
            });
    }
    
    void ShowAlert(string message)
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            DisplayAlertAsync("Push notifications demo", message, "OK")
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        });
    }
    

    Penting

    Di aplikasi, pendaftaran dan de-pendaftaran dilakukan sebagai respons terhadap input pengguna, untuk memungkinkan fungsionalitas ini dieksplorasi dan diuji dengan lebih mudah. Dalam aplikasi produksi, Anda biasanya akan melakukan tindakan pendaftaran dan pencabutan pendaftaran selama titik yang sesuai dalam siklus hidup aplikasi, tanpa memerlukan input pengguna eksplisit.

  6. Di Visual Studio, buka App.xaml.cs dan tambahkan pernyataan berikut using :

    using PushNotificationsDemo.Models;
    using PushNotificationsDemo.Services;
    
  7. Di App.xaml.cs, tambahkan readonly bidang backing untuk menyimpan referensi ke IPushDemoNotificationActionService implementasi:

    readonly IPushDemoNotificationActionService _actionService;
    
  1. Di dalam App konstruktor, tentukan implementasi IPushDemoNotificationActionService dan tetapkan ke bidang backing _actionService, serta berlangganan ke event IPushDemoNotificationActionService.ActionTriggered.

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    
        MainPage = new AppShell();
    }
    
  1. Di dalam konstruktor App, selesaikan implementasi IPushDemoNotificationActionService dan tetapkan ke backing field _actionService, lalu berlangganan ke acara IPushDemoNotificationActionService.ActionTriggered:

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    }
    
  1. Di kelas App, implementasikan pengendali acara untuk acara IPushDemoNotificationActionService.ActionTriggered.

    void NotificationActionTriggered(object sender, PushDemoAction e)
    {
        ShowActionAlert(e);
    }
    
    void ShowActionAlert(PushDemoAction action)
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            Windows[0].Page?.DisplayAlert("Push notifications demo", $"{action} action received.", "OK")
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        });
    }
    
    void NotificationActionTriggered(object sender, PushDemoAction e)
    {
        ShowActionAlert(e);
    }
    
    void ShowActionAlert(PushDemoAction action)
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            Windows[0].Page?.DisplayAlertAsync("Push notifications demo", $"{action} action received.", "OK")
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        });
    }
    

    Penanganan acara untuk ActionTriggered acara menunjukkan penerimaan dan penyebaran tindakan pemberitahuan push. Ini biasanya akan ditangani secara diam-diam, misalnya menavigasi ke tampilan tertentu atau me-refresh beberapa data daripada menampilkan pemberitahuan.

Mengonfigurasi aplikasi Android

Untuk mengonfigurasi aplikasi .NET MAUI Anda di Android untuk menerima dan memproses pemberitahuan push:

  1. Di Visual Studio, tambahkan paket Xamarin.Firebase.Messaging NuGet ke proyek aplikasi .NET MAUI Anda.

  2. Di Visual Studio, tambahkan file google-services.json Anda ke folder Platforms/Android dari proyek aplikasi .NET MAUI Anda. Setelah file ditambahkan ke proyek Anda, file tersebut seharusnya ditambahkan dengan tindakan build :GoogleServicesJson

    <ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
      <GoogleServicesJson Include="Platforms\Android\google-services.json" />
    </ItemGroup>
    

    Kiat

    Ingatlah untuk menambahkan google-services.json ke dalam file .gitignore Anda untuk menghindari meng-commit file ini ke kontrol sumber.

  3. Di Visual Studio, edit file proyek (*.csproj) dan atur SupportedOSPlatformVersion untuk Android ke 26.0:

    <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">26.0</SupportedOSPlatformVersion>
    

    Google membuat perubahan pada saluran pemberitahuan Android di API 26. Untuk informasi selengkapnya, lihat Saluran pemberitahuan di developer.android.com.

  4. Di folder Platforms/Android proyek, tambahkan kelas baru bernama DeviceInstallationService dan ganti kodenya dengan kode berikut:

    using Android.Gms.Common;
    using PushNotificationsDemo.Models;
    using PushNotificationsDemo.Services;
    using static Android.Provider.Settings;
    
    namespace PushNotificationsDemo.Platforms.Android;
    
    public class DeviceInstallationService : IDeviceInstallationService
    {
        public string Token { get; set; }
    
        public bool NotificationsSupported
            => GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Platform.AppContext) == ConnectionResult.Success;
    
        public string GetDeviceId()
            => Secure.GetString(Platform.AppContext.ContentResolver, Secure.AndroidId);
    
        public DeviceInstallation GetDeviceInstallation(params string[] tags)
        {
            if (!NotificationsSupported)
                throw new Exception(GetPlayServicesError());
    
            if (string.IsNullOrWhiteSpace(Token))
                throw new Exception("Unable to resolve token for FCMv1.");
    
            var installation = new DeviceInstallation
            {
                InstallationId = GetDeviceId(),
                Platform = "fcmv1",
                PushChannel = Token
            };
    
            installation.Tags.AddRange(tags);
    
            return installation;
        }
    
        string GetPlayServicesError()
        {
            int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Platform.AppContext);
    
            if (resultCode != ConnectionResult.Success)
                return GoogleApiAvailability.Instance.IsUserResolvableError(resultCode) ?
                           GoogleApiAvailability.Instance.GetErrorString(resultCode) :
                           "This device isn't supported.";
    
            return "An error occurred preventing the use of push notifications.";
        }
    }
    

    Kelas ini menyediakan ID unik, menggunakan nilai Secure.AndroidId, dan payload pendaftaran hub pemberitahuan.

  5. Di folder Platforms/Android proyek, tambahkan kelas baru bernama PushNotificationFirebaseMessagingService dan ganti kodenya dengan kode berikut:

    using Android.App;
    using Firebase.Messaging;
    using PushNotificationsDemo.Services;
    
    namespace PushNotificationsDemo.Platforms.Android;
    
    [Service(Exported = false)]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class PushNotificationFirebaseMessagingService : FirebaseMessagingService
    {
        IPushDemoNotificationActionService _notificationActionService;
        INotificationRegistrationService _notificationRegistrationService;
        IDeviceInstallationService _deviceInstallationService;
        int _messageId;
    
        IPushDemoNotificationActionService NotificationActionService =>
            _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
        INotificationRegistrationService NotificationRegistrationService =>
            _notificationRegistrationService ?? (_notificationRegistrationService = IPlatformApplication.Current.Services.GetService<INotificationRegistrationService>());
    
        IDeviceInstallationService DeviceInstallationService =>
            _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
    
        public override void OnNewToken(string token)
        {
            DeviceInstallationService.Token = token;
    
            NotificationRegistrationService.RefreshRegistrationAsync()
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        }
    
        public override void OnMessageReceived(RemoteMessage message)
        {
            base.OnMessageReceived(message);
    
            if (message.Data.TryGetValue("action", out var messageAction))
                NotificationActionService.TriggerAction(messageAction);
        }
    }
    

    Kelas ini memiliki IntentFilter atribut yang menyertakan com.google.firebase.MESSAGING_EVENT filter. Filter ini memungkinkan Android meneruskan pesan masuk ke kelas ini untuk diproses.

    Untuk informasi tentang format pesan Firebase Cloud Messaging, lihat Tentang pesan FCM di developer.android.com.

  6. Di Visual Studio, buka file MainActivity.cs di folder Platforms/Android dan tambahkan pernyataan berikut using :

    using Android.App;
    using Android.Content;
    using Android.Content.PM;
    using Android.OS;
    using PushNotificationsDemo.Services;
    using Firebase.Messaging;
    
  7. MainActivity Di kelas , atur LaunchMode ke SingleTop sehingga MainActivity tidak akan dibuat lagi saat dibuka:

    [Activity(
        Theme = "@style/Maui.SplashTheme",
        MainLauncher = true,
        LaunchMode = LaunchMode.SingleTop,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
    
  8. Di kelas MainActivity, tambahkan field pendukung untuk menyimpan referensi ke implementasi IPushDemoNotificationActionService dan IDeviceInstallationService.

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
  9. Di kelas MainActivity, tambahkan properti privat NotificationActionService dan DeviceInstallationService yang mengambil konkret implementasinya dari kontainer injeksi dependensi aplikasi.

    IPushDemoNotificationActionService NotificationActionService =>
        _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
    IDeviceInstallationService DeviceInstallationService =>
        _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
    
  10. Di dalam kelas MainActivity, implementasikan antarmuka Android.Gms.Tasks.IOnSuccessListener untuk mengambil dan menyimpan token Firebase.

    public class MainActivity : MauiAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener
    {
        public void OnSuccess(Java.Lang.Object result)
        {
            DeviceInstallationService.Token = result.ToString();
        }
    }
    
  11. Di kelas MainActivity, tambahkan metode ProcessNotificationActions yang akan memeriksa apakah Intent yang diberikan memiliki nilai tambahan bernama action, dan kemudian, secara kondisional, memicu action menggunakan implementasi IPushDemoNotificationActionService.

    void ProcessNotificationsAction(Intent intent)
    {
        try
        {
            if (intent?.HasExtra("action") == true)
            {
                var action = intent.GetStringExtra("action");
    
                if (!string.IsNullOrEmpty(action))
                    NotificationActionService.TriggerAction(action);
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }
    }
    
  12. Ambil alih metode OnNewIntent untuk memanggil metode ProcessNotificationActions di kelas MainActivity.

    protected override void OnNewIntent(Intent? intent)
    {
        base.OnNewIntent(intent);
        ProcessNotificationsAction(intent);
    }
    

    Karena LaunchMode untuk Activity diatur ke SingleTop, sebuah Intent akan dikirim ke instans Activity yang ada melalui penimpaan OnNewIntent, bukan metode OnCreate. Oleh karena itu, Anda harus menangani niat masuk di OnNewIntent dan OnCreate.

  13. Di dalam kelas MainActivity, gantikan metode OnCreate untuk memanggil metode ProcessNotificationActions dan mengambil token dari Firebase, dengan menambahkan MainActivity sebagai IOnSuccessListener.

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
    
        if (DeviceInstallationService.NotificationsSupported)
            FirebaseMessaging.Instance.GetToken().AddOnSuccessListener(this);
    
        ProcessNotificationsAction(Intent);
    }
    

    Catatan

    Aplikasi harus didaftarkan ulang setiap kali Anda menjalankannya dan menghentikannya dari sesi debug untuk terus menerima pemberitahuan push.

  14. Di Visual Studio, tambahkan POST_NOTIFICATIONS izin ke file AndroidManifest.xml di folder Platforms/Android :

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    

    Untuk informasi selengkapnya tentang izin ini, lihat Izin Runtime Notifikasi di developer.android.com.

  15. Di Visual Studio, buka MainPage.xaml.cs dan tambahkan kode berikut ke MainPage kelas :

    #if ANDROID
            protected override async void OnAppearing()
            {
                base.OnAppearing();
    
                PermissionStatus status = await Permissions.RequestAsync<Permissions.PostNotifications>();
            }
    #endif
    

    Kode ini berjalan di Android saat MainPage muncul, dan meminta pengguna untuk memberikan POST_NOTIFICATIONS izin. Untuk informasi selengkapnya tentang izin .NET MAUI, lihat Izin.

Mengonfigurasi aplikasi iOS

Simulator iOS mendukung pemberitahuan jarak jauh di iOS 16+ saat berjalan di macOS 13+ di komputer Mac dengan prosesor Apple silicon atau T2. Setiap simulator menghasilkan token pendaftaran yang unik untuk kombinasi simulator tersebut dan perangkat keras Mac yang dijalankannya.

Penting

Simulator ini mendukung lingkungan kotak pasir Apple Push Notification Service.

Instruksi berikut mengasumsikan Anda menggunakan perangkat keras yang mendukung penerimaan pemberitahuan jarak jauh di simulator iOS. Jika tidak demikian, Anda harus menjalankan aplikasi iOS di perangkat fisik, yang akan mengharuskan Anda membuat profil provisi untuk aplikasi yang menyertakan kemampuan Pemberitahuan Push. Anda kemudian harus memastikan bahwa aplikasi Anda dibuat menggunakan sertifikat dan profil provisi Anda. Untuk informasi selengkapnya tentang cara melakukannya, lihat Menyiapkan aplikasi iOS Anda untuk bekerja dengan Azure Notification Hubs, lalu ikuti instruksi di bawah ini.

Untuk mengonfigurasi aplikasi .NET MAUI Anda di iOS untuk menerima dan memproses pemberitahuan push:

  1. Di Visual Studio, edit file proyek (*.csproj) dan atur SupportedOSPlatformVersion untuk iOS ke 13.0:

    <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">13.0</SupportedOSPlatformVersion>
    

    Apple membuat perubahan pada layanan push mereka di iOS 13. Untuk informasi selengkapnya, lihat Pembaruan Azure Notification Hubs untuk iOS 13.

  2. Di Visual Studio, tambahkan file Entitlements.plist ke folder Platforms/iOS proyek dan tambahkan XML berikut ke file:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>aps-environment</key>
      <string>development</string>
    </dict>
    </plist>
    

    Ini menetapkan hak lingkungan APS dan menentukan penggunaan lingkungan layanan Pemberitahuan Push Apple untuk pengembangan. Dalam aplikasi produksi, nilai pemberian izin ini harus diatur ke production. Untuk informasi selengkapnya tentang pemberian izin ini, lihat Pemberian Izin Lingkungan APS di developer.apple.com.

    Untuk informasi selengkapnya tentang menambahkan file hak istimewa, lihat hak istimewa iOS.

  3. Di Visual Studio, tambahkan kelas baru bernama DeviceInstallationService ke folder Platforms/iOS proyek dan tambahkan kode berikut ke file:

    using PushNotificationsDemo.Services;
    using PushNotificationsDemo.Models;
    using UIKit;
    
    namespace PushNotificationsDemo.Platforms.iOS;
    
    public class DeviceInstallationService : IDeviceInstallationService
    {
        const int SupportedVersionMajor = 13;
        const int SupportedVersionMinor = 0;
    
        public string Token { get; set; }
    
        public bool NotificationsSupported =>
            UIDevice.CurrentDevice.CheckSystemVersion(SupportedVersionMajor, SupportedVersionMinor);
    
        public string GetDeviceId() =>
            UIDevice.CurrentDevice.IdentifierForVendor.ToString();
    
        public DeviceInstallation GetDeviceInstallation(params string[] tags)
        {
            if (!NotificationsSupported)
                throw new Exception(GetNotificationsSupportError());
    
            if (string.IsNullOrWhiteSpace(Token))
                throw new Exception("Unable to resolve token for APNS");
    
            var installation = new DeviceInstallation
            {
                InstallationId = GetDeviceId(),
                Platform = "apns",
                PushChannel = Token
            };
    
            installation.Tags.AddRange(tags);
    
            return installation;
        }
    
        string GetNotificationsSupportError()
        {
            if (!NotificationsSupported)
                return $"This app only supports notifications on iOS {SupportedVersionMajor}.{SupportedVersionMinor} and above. You are running {UIDevice.CurrentDevice.SystemVersion}.";
    
            if (Token == null)
                return $"This app can support notifications but you must enable this in your settings.";
    
            return "An error occurred preventing the use of push notifications";
        }
    }
    

    Kelas ini menyediakan ID unik, menggunakan nilai UIDevice.IdentifierForVendor, dan payload pendaftaran untuk hub pemberitahuan.

  4. Di Visual Studio, tambahkan kelas baru bernama NSDataExtensions ke folder Platforms/iOS proyek dan tambahkan kode berikut ke file:

    using Foundation;
    using System.Text;
    
    namespace PushNotificationsDemo.Platforms.iOS;
    
    internal static class NSDataExtensions
    {
        internal static string ToHexString(this NSData data)
        {
            var bytes = data.ToArray();
    
            if (bytes == null)
                return null;
    
            StringBuilder sb = new StringBuilder(bytes.Length * 2);
    
            foreach (byte b in bytes)
                sb.AppendFormat("{0:x2}", b);
    
            return sb.ToString().ToUpperInvariant();
        }
    }
    

    Metode ekstensi ToHexString akan digunakan dalam kode yang akan Anda tambahkan untuk memproses token perangkat yang diambil.

  5. Di Visual Studio, buka file AppDelegate.cs di folder Platforms/iOS dan tambahkan pernyataan berikut using :

    using System.Diagnostics;
    using Foundation;
    using PushNotificationsDemo.Platforms.iOS;
    using PushNotificationsDemo.Services;
    using UIKit;
    using UserNotifications;
    
  6. Di kelas AppDelegate, tambahkan sebuah bidang dukungan untuk menyimpan referensi ke implementasi IPushDemoNotificationActionService, INotificationRegistrationService, dan IDeviceInstallationService.

    IPushDemoNotificationActionService _notificationActionService;
    INotificationRegistrationService _notificationRegistrationService;
    IDeviceInstallationService _deviceInstallationService;
    
  7. Di kelas AppDelegate, tambahkan properti privat NotificationActionService, NotificationRegistrationService, dan DeviceInstallationService yang mengambil implementasi konkret dari kontainer injeksi dependensi aplikasi.

    IPushDemoNotificationActionService NotificationActionService =>
        _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
    INotificationRegistrationService NotificationRegistrationService =>
        _notificationRegistrationService ?? (_notificationRegistrationService = IPlatformApplication.Current.Services.GetService<INotificationRegistrationService>());
    
    IDeviceInstallationService DeviceInstallationService =>
        _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
    
  8. Di kelas AppDelegate, tambahkan metode CompleteRegistrationAsync setelah itu atur nilai properti IDeviceInstallationService.Token.

    Task CompleteRegistrationAsync(NSData deviceToken)
    {
        DeviceInstallationService.Token = deviceToken.ToHexString();
        return NotificationRegistrationService.RefreshRegistrationAsync();
    }
    

    Metode ini juga me-refresh pendaftaran dan menyimpan token perangkat jika telah diperbarui sejak terakhir disimpan.

  9. Di kelas AppDelegate, tambahkan metode ProcessNotificationActions untuk memproses data pemberitahuan NSDictionary dan memanggil NotificationActionService.TriggerAction jika diperlukan.

    void ProcessNotificationActions(NSDictionary userInfo)
    {
        if (userInfo == null)
            return;
    
        try
        {
            // If your app isn't in the foreground, the notification goes to Notification Center.
            // If your app is in the foreground, the notification goes directly to your app and you
            // need to process the notification payload yourself.
            var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString;
    
            if (!string.IsNullOrWhiteSpace(actionValue?.Description))
                NotificationActionService.TriggerAction(actionValue.Description);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
    
  10. Di kelas AppDelegate, tambahkan metode RegisteredForRemoteNotifications dengan meneruskan argumen deviceToken ke metode CompleteRegistrationAsync:

    [Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
    public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        CompleteRegistrationAsync(deviceToken)
            .ContinueWith((task) =>
            {
                if (task.IsFaulted)
                    throw task.Exception;
            });
    }
    

    Metode ini akan dipanggil ketika aplikasi terdaftar untuk menerima pemberitahuan jarak jauh, dan digunakan untuk meminta token perangkat unik, yang secara efektif merupakan alamat aplikasi Anda di perangkat.

  11. Di kelas AppDelegate, tambahkan metode ReceivedRemoteNotification dengan meneruskan argumen userInfo ke metode ProcessNotificationActions.

    [Export("application:didReceiveRemoteNotification:")]
    public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
    {
        ProcessNotificationActions(userInfo);
    }
    

    Metode ini akan dipanggil ketika aplikasi telah menerima pemberitahuan jarak jauh, dan digunakan untuk memproses pemberitahuan.

  12. Di kelas AppDelegate, tambahkan metode FailedToRegisterForRemoteNotifications untuk mencatat kesalahan apa pun.

    [Export("application:didFailToRegisterForRemoteNotificationsWithError:")]
    public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
    {
        Debug.WriteLine(error.Description);
    }
    

    Metode ini akan dipanggil ketika aplikasi gagal mendaftar untuk menerima pemberitahuan jarak jauh. Pendaftaran mungkin gagal jika perangkat tidak tersambung ke jaringan, jika server APNS tidak dapat dijangkau, atau jika aplikasi salah dikonfigurasi.

    Catatan

    Untuk skenario produksi, Anda mungkin ingin menerapkan pencatatan dan penanganan kesalahan yang tepat dalam metode .FailedToRegisterForRemoteNotifications

  13. Di kelas AppDelegate, tambahkan metode FinishedLaunching untuk meminta persetujuan secara bersyarat agar dapat menggunakan notifikasi dan mendaftar untuk notifikasi jarak jauh.

    [Export("application:didFinishLaunchingWithOptions:")]
    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        if (DeviceInstallationService.NotificationsSupported)
        {
            UNUserNotificationCenter.Current.RequestAuthorization(
                UNAuthorizationOptions.Alert |
                UNAuthorizationOptions.Badge |
                UNAuthorizationOptions.Sound,
                (approvalGranted, error) =>
                {
                    if (approvalGranted && error == null)
                    {
                        MainThread.BeginInvokeOnMainThread(() =>
                        {
                            UIApplication.SharedApplication.RegisterForRemoteNotifications();
                        });
                    }
                });
        }
    
        using (var userInfo = launchOptions?.ObjectForKey(UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary)
        {
            ProcessNotificationActions(userInfo);
        }
    
        return base.FinishedLaunching(application, launchOptions);
    }
    

    Untuk informasi tentang meminta izin untuk menggunakan pemberitahuan, lihat Meminta izin untuk menggunakan pemberitahuan di developer.apple.com.

Untuk informasi tentang pemberitahuan di iOS, lihat Pemberitahuan Pengguna di developer.apple.com.

Mendaftarkan tipe dengan kontainer injeksi dependensi aplikasi

  1. Di Visual Studio, buka MauiProgram.cs dan tambahkan using pernyataan untuk PushNotificationsDemo.Services namespace:

    using PushNotificationsDemo.Services;
    
  2. Di kelas MauiProgram, tambahkan kode untuk metode ekstensi RegisterServices yang mendaftarkan DeviceInstallationService pada setiap platform, serta layanan PushDemoNotificationActionService dan NotificationRegistrationService lintas platform, dan yang mengembalikan objek MauiAppBuilder.

    public static MauiAppBuilder RegisterServices(this MauiAppBuilder builder)
    {
    #if IOS
        builder.Services.AddSingleton<IDeviceInstallationService, PushNotificationsDemo.Platforms.iOS.DeviceInstallationService>();
    #elif ANDROID
        builder.Services.AddSingleton<IDeviceInstallationService, PushNotificationsDemo.Platforms.Android.DeviceInstallationService>();
    #endif
    
        builder.Services.AddSingleton<IPushDemoNotificationActionService, PushDemoNotificationActionService>();
        builder.Services.AddSingleton<INotificationRegistrationService>(new NotificationRegistrationService(Config.BackendServiceEndpoint, Config.ApiKey));
    
        return builder;
    }
    
  3. Tambahkan kode di kelas MauiProgram untuk metode ekstensi RegisterViews yang mendaftarkan tipe MainPage sebagai singleton dan yang mengembalikan objek MauiAppBuilder:

    public static MauiAppBuilder RegisterViews(this MauiAppBuilder builder)
    {
        builder.Services.AddSingleton<MainPage>();
        return builder;
    }
    

    Jenis MainPage terdaftar karena memerlukan INotificationRegistrationService dependensi, dan jenis apa pun yang memerlukan dependensi harus terdaftar dengan kontainer injeksi dependensi.

  4. Di kelas MauiProgram, ubah metode CreateMauiApp sehingga memanggil metode ekstensi RegisterServices dan RegisterViews.

    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .RegisterServices()
            .RegisterViews();
    
    #if DEBUG
          builder.Logging.AddDebug();
    #endif
          return builder.Build();
    }
    

Untuk informasi selengkapnya tentang dependency injection di .NET MAUI, lihat Dependency injection.

Menguji aplikasi

Anda dapat menguji aplikasi dengan mengirim pemberitahuan push ke aplikasi menggunakan layanan backend, atau melalui portal Azure.

Simulator iOS mendukung pemberitahuan jarak jauh di iOS 16+ saat berjalan di macOS 13+ di komputer Mac dengan prosesor Apple silicon atau T2. Jika tidak memenuhi persyaratan perangkat keras ini, Anda harus menguji aplikasi iOS di perangkat fisik. Di Android, Anda dapat menguji aplikasi di perangkat fisik yang tidak terkunci oleh pengembang, atau emulator.

Android dan iOS menampilkan pemberitahuan push untuk aplikasi ketika berjalan di latar belakang. Jika aplikasi berjalan di latar depan saat pemberitahuan diterima, kode aplikasi menentukan perilaku. Misalnya, Anda dapat memperbarui antarmuka aplikasi untuk mencerminkan informasi baru yang terkandung dalam pemberitahuan.

Uji menggunakan layanan backend

Untuk mengirim pemberitahuan push pengujian ke aplikasi Anda melalui layanan backend yang diterbitkan ke Azure App Service:

  1. Di Visual Studio, jalankan aplikasi PushNotificationsDemo di Android atau iOS dan pilih tombol Daftar .

    Catatan

    Jika Anda menguji di Android, pastikan Anda tidak berjalan menggunakan konfigurasi debug. Atau, jika aplikasi sebelumnya telah disebarkan, pastikan aplikasi ditutup paksa lalu mulai lagi dari peluncur.

  2. Di alat REST pilihan Anda, kirim POST permintaan ke alamat berikut:

    https://<app_name>.azurewebsites.net/api/notifications/requests
    

    Pastikan Anda mengonfigurasi header permintaan untuk menyertakan kunci apikey dan nilainya, atur isi ke mentah, dan gunakan konten JSON berikut:

    {
        "text": "Message from REST tooling!",
        "action": "action_a"
    }
    

    Permintaan keseluruhan harus mirip dengan contoh berikut:

    POST /api/notifications/requests HTTP/1.1
    Host: https://<app_name>.azurewebsites.net
    apikey: <your_api_key>
    Content-Type: application/json
    
    {
        "text": "Message from REST tooling!",
        "action": "action_a"
    }
    
  3. Dalam alat REST pilihan Anda, validasi bahwa Anda menerima respons 200 OK .

  4. Di aplikasi di Android atau iOS, peringatan akan muncul yang menampilkan tindakan ActionA yang diterima.

Untuk informasi selengkapnya tentang memanggil REST API, lihat Menggunakan file .http di Visual Studio dan Menguji API web dengan Http Repl. Di Visual Studio Code, Klien REST dapat digunakan untuk menguji REST API.

Uji menggunakan portal Azure

Azure Notification Hubs memungkinkan Anda memeriksa apakah aplikasi Anda dapat menerima pemberitahuan push.

Untuk mengirim pemberitahuan push pengujian ke aplikasi Anda melalui portal Azure:

  1. Di Visual Studio, jalankan aplikasi PushNotificationsDemo di Android atau iOS dan pilih tombol Daftar .

    Catatan

    Jika Anda menguji di Android, pastikan Anda tidak berjalan menggunakan konfigurasi debug. Atau, jika aplikasi sebelumnya telah disebarkan, pastikan aplikasi ditutup paksa lalu mulai lagi dari peluncur.

  2. Di portal Azure, telusuri ke hub pemberitahuan Anda dan pilih tombol Uji Kirim pada bilah Gambaran Umum.

  3. Di bilah Uji Kirim, pilih Platform yang diperlukan dan ubah payload.

    Untuk Apple, gunakan payload berikut:

    {
      "aps": {
        "alert": "Message from Notification Hub!"
      },
      "action": "action_a"
    }
    

    Untuk Android, gunakan payload berikut:

    {
      "message": {
        "notification": {
          "title": "PushDemo",
          "body": "Message from Notification Hub!"
        },
        "data": {
          "action": "action_a"
        }
      }
    }
    

    portal Azure harus menunjukkan bahwa pemberitahuan telah berhasil dikirim.

    Untuk informasi tentang format pesan Firebase Cloud Messaging, lihat Tentang pesan FCM di developer.android.com.

  4. Di aplikasi di Android atau iOS, peringatan akan muncul yang menampilkan tindakan ActionA yang diterima.

Pemecahan Masalah

Bagian berikut membahas masalah umum yang dihadapi saat mencoba menggunakan pemberitahuan push di aplikasi klien.

Tidak ada tanggapan dari layanan backend

Saat menguji secara lokal, pastikan bahwa layanan backend berjalan dan menggunakan port yang benar.

Jika Anda menguji aplikasi Azure API, periksa apakah layanan sudah berjalan, telah disebarkan, dan dimulai tanpa kesalahan.

Pastikan Anda telah menentukan alamat dasar dengan benar di alat REST Anda, atau di konfigurasi aplikasi .NET MAUI Anda. Alamat dasar harus https://<api_name>.azurewebsites.net atau https://localhost:7020 saat menguji secara lokal.

Menerima kode status 401 dari layanan backend

Validasi bahwa Anda mengatur apikey header permintaan dengan benar dan nilai ini cocok dengan yang Anda konfigurasi untuk layanan backend.

Jika Anda menerima kesalahan ini saat menguji secara lokal, pastikan bahwa nilai kunci yang Anda tentukan di aplikasi .NET MAUI Cocok Authentication:ApiKey dengan nilai rahasia pengguna yang digunakan oleh layanan backend.

Jika Anda menguji dengan aplikasi Azure API, pastikan bahwa nilai kunci yang ditentukan dalam aplikasi .NET MAUI Anda cocok Authentication:ApiKey dengan nilai pengaturan aplikasi yang ditentukan dalam portal Azure. Jika Anda membuat atau mengubah pengaturan aplikasi ini setelah menyebarkan layanan backend, Maka Anda harus memulai ulang layanan agar nilai diterapkan.

Menerima kode status 404 dari layanan backend

Validasi bahwa titik akhir dan metode permintaan HTTP sudah benar:

  • MELETAKKAN- https://<api_name>.azurewebsites.net/api/notifications/installations
  • MENGHAPUS- https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • UJI DIRI AWAL - https://<api_name>.azurewebsites.net/api/notifications/requests

Atau saat menguji secara lokal:

  • MELETAKKAN- https://localhost:7020/api/notifications/installations
  • MENGHAPUS- https://localhost:7020/api/notifications/installations/<installation_id>
  • POS - https://localhost:7020/api/notifications/requests

Penting

Saat menentukan alamat dasar di aplikasi .NET MAUI, pastikan alamat tersebut berakhir dengan /. Alamat dasar harus https://<api_name>.azurewebsites.net atau https://localhost:7020/ saat menguji secara lokal.

Tidak menerima pemberitahuan di Android setelah memulai atau menghentikan sesi debug

Pastikan Anda mendaftar setiap kali memulai sesi debug. Debugger akan menyebabkan token Firebase baru dibuat, oleh karena itu, penginstalan hub notifikasi harus diperbarui.

Tidak dapat mendaftar dan pesan kesalahan dari notification hub ditampilkan

Verifikasi bahwa perangkat uji memiliki konektifitas jaringan. Kemudian tentukan kode status respons HTTP dengan mengatur titik henti untuk memeriksa StatusCode properti di HttpResponse.

Tinjau saran pemecahan masalah sebelumnya, jika berlaku, berdasarkan kode status.

Atur titik henti pada baris yang mengembalikan kode status tertentu untuk API masing-masing. Kemudian, coba panggil layanan backend saat melakukan debugging secara lokal.

Validasi layanan backend berfungsi seperti yang diharapkan oleh alat REST pilihan Anda, dan gunakan payload yang dibuat oleh aplikasi .NET MAUI untuk platform pilihan Anda.

Tinjau bagian konfigurasi khusus platform untuk memastikan bahwa tidak ada langkah yang terlewatkan. Periksa apakah nilai yang sesuai sedang digunakan untuk variabel InstallationId dan Token untuk platform yang Anda pilih.

Tidak dapat menyelesaikan ID untuk pesan kesalahan perangkat tersebut.

Tinjau bagian konfigurasi khusus platform untuk memastikan bahwa tidak ada langkah yang terlewatkan.