Bagikan melalui


Tutorial: Mengirim pemberitahuan push ke aplikasi Flutter menggunakan Azure Notification Hubs melalui layanan backend

Unduh Sampel Mengunduh sampel

Dalam tutorial ini, Anda menggunakan Azure Notification Hubs untuk mendorong pemberitahuan ke aplikasi Flutter yang menargetkan Android dan iOS.

Backend ASP.NET Core Web API digunakan untuk menangani pendaftaran perangkat untuk klien menggunakan pendekatan Penginstalan terbaru dan terbaik. Layanan ini juga akan mengirim pemberitahuan push secara lintas platform.

Operasi ini ditangani menggunakan Notification Hubs SDK untuk operasi backend. Detail lebih lanjut tentang pendekatan keseluruhan disediakan dalam dokumentasi Mendaftar dari backend aplikasi Anda .

Tutorial ini membawa Anda melalui langkah-langkah berikut:

Prasyarat

Untuk mengikutinya, Anda memerlukan:

Untuk Android, Anda harus memiliki:

  • Developer membuka kunci perangkat fisik atau emulator (menjalankan API 26 ke atas dengan Google Play Services terinstal).

Untuk iOS, Anda harus memiliki:

Catatan

Simulator iOS tidak mendukung pemberitahuan jarak jauh sehingga perangkat fisik diperlukan saat menjelajahi sampel ini di iOS. Namun, Anda tidak perlu menjalankan aplikasi di Android dan iOS untuk menyelesaikan tutorial ini.

Anda dapat mengikuti langkah-langkah dalam contoh prinsip pertama ini tanpa pengalaman sebelumnya. Namun, Anda akan mendapat manfaat dari keakraban dengan aspek-aspek berikut.

Langkah-langkah yang disediakan khusus untuk macOS. Dimungkinkan untuk mengikuti Windows dengan melewatkan aspek iOS .

Menyiapkan Push Notification Services dan Azure Notification Hub

Di bagian ini, Anda menyiapkan Firebase Cloud Messaging (FCM) dan Apple Push Notification Services (APNS). Anda kemudian membuat dan mengonfigurasi hub pemberitahuan untuk bekerja dengan layanan tersebut.

Membuat proyek Firebase dan mengaktifkan Firebase Cloud Messaging untuk Android

  1. Masuk ke konsol Firebase. Buat proyek Firebase baru yang memasukkan PushDemo sebagai Nama proyek.

    Catatan

    Nama 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 Anda ingin asalkan masih unik secara global.

  2. Setelah membuat proyek, pilih Tambahkan Firebase ke aplikasi Android Anda.

    Menambahkan Firebase ke aplikasi Android Anda

  3. Pada halaman Tambahkan Firebase ke aplikasi Android Anda , ikuti langkah-langkah berikut.

    1. Untuk nama paket Android, masukkan nama untuk paket Anda. Misalnya: com.<organization_identifier>.<package_name>.

      Tentukan nama paket

    2. Pilih Daftarkan aplikasi.

    3. Pilih Unduh google-services.json. Kemudian simpan file ke folder lokal untuk digunakan nanti dan pilih Berikutnya.

      Unduh google-services.json

    4. Pilih Berikutnya.

    5. Pilih Lanjutkan ke konsol

      Catatan

      Jika tombol Lanjutkan ke konsol tidak diaktifkan, karena pemeriksaan penginstalan verifikasi , pilih Lewati langkah ini.

  4. Di konsol Firebase, pilih roda gigi untuk proyek Anda. Lalu pilih Pengaturan Proyek.

    Pilih Pengaturan Proyek

    Catatan

    Jika Anda belum mengunduh file google-services.json , Anda dapat mengunduhnya di halaman ini.

  5. Beralih ke tab Pesan Cloud di bagian atas. Salin dan simpan kunci Server untuk digunakan nanti. Anda menggunakan nilai ini untuk mengonfigurasi hub pemberitahuan Anda.

    Salin kunci server

Mendaftarkan aplikasi iOS Anda untuk pemberitahuan push

Untuk mengirim pemberitahuan push ke app iOS, daftarkan aplikasi Anda dengan Apple, dan daftarkan juga pemberitahuan push.

  1. Jika Anda belum mendaftarkan aplikasi, telusuri ke Portal Provisi iOS di Pusat Pengembang Apple. Masuk ke portal dengan ID Apple Anda, navigasikan ke Sertifikat, Pengidentifikasi & Profil, lalu pilih Pengidentifikasi. Klik + untuk mendaftarkan aplikasi baru.

    Halaman ID Aplikasi Portal Provisi iOS

  2. Pada layar Daftarkan Pengidentifikasi Baru , pilih tombol radio ID Aplikasi . Lalu pilih Lanjutkan.

    Portal Provisi iOS mendaftarkan halaman ID baru

  3. Perbarui tiga nilai berikut untuk aplikasi baru Anda, lalu pilih Lanjutkan:

    • Deskripsi: Ketik nama deskriptif untuk aplikasi Anda.

    • ID Bundel: Masukkan ID Bundel formulir com.organization_identifier<>.<>product_name seperti yang disebutkan dalam Panduan Distribusi Aplikasi. Dalam cuplikan layar berikut, mobcat nilai digunakan sebagai pengidentifikasi organisasi dan nilai PushDemo digunakan sebagai nama produk.

      Halaman ID aplikasi register Portal Provisi iOS

    • Pemberitahuan Push: Periksa opsi Pemberitahuan Push di bagian Kemampuan .

      Formulir untuk mendaftarkan ID Aplikasi baru

      Tindakan ini menghasilkan ID Aplikasi dan permintaan yang Anda konfirmasi informasinya. Pilih Lanjutkan, lalu pilih Daftar untuk mengonfirmasi ID Aplikasi baru.

      Mengonfirmasi ID Aplikasi baru

      Setelah memilih Daftar, Anda akan melihat ID Aplikasi baru sebagai item baris di halaman Sertifikat, Pengidentifikasi, & Profil .

  4. Di halaman Sertifikat, Pengidentifikasi & Profil , di bawah Pengidentifikasi, temukan item baris ID Aplikasi yang Anda buat. Kemudian, pilih barisnya untuk menampilkan layar Edit Konfigurasi ID Aplikasi Anda .

Membuat sertifikat untuk Notification Hubs

Sertifikat diperlukan untuk mengaktifkan hub pemberitahuan agar berfungsi dengan Apple Push Notification Services (APNS) dan dapat disediakan dengan salah satu dari dua cara:

  1. Membuat sertifikat push p12 yang dapat diunggah langsung ke Notification Hub (pendekatan asli)

  2. Membuat sertifikat p8 yang dapat digunakan untuk autentikasi berbasis token (pendekatan yang lebih baru dan direkomendasikan)

Pendekatan yang lebih baru memiliki sejumlah manfaat seperti yang di dokumentasikan dalam autentikasi berbasis Token (HTTP/2) untuk APNS. Lebih sedikit langkah yang diperlukan tetapi juga diamanatkan untuk skenario tertentu. Namun, langkah-langkah telah disediakan untuk kedua pendekatan karena keduanya akan berfungsi untuk tujuan tutorial ini.

OPSI 1: Membuat sertifikat push p12 yang dapat diunggah langsung ke Notification Hub
  1. Di Mac Anda, jalankan alat Akses Rantai Kunci. Ini dapat dibuka dari folder Utilitas atau folder Lainnya di Launchpad.

  2. Pilih Akses Rantai Kunci, perluas Asisten Sertifikat, lalu pilih Minta Sertifikat dari Otoritas Sertifikat.

    Menggunakan Akses Rantai Kunci untuk meminta sertifikat baru

    Catatan

    Secara default, Akses Rantai Kunci memilih item pertama dalam daftar. Ini bisa menjadi masalah jika Anda berada dalam kategori Sertifikat dan Otoritas Sertifikasi Hubungan Pengembang Di Seluruh Dunia Apple bukan item pertama dalam daftar. Pastikan Anda memiliki item non-kunci, atau kunci Otoritas Sertifikasi Hubungan Pengembang Di Seluruh Dunia Apple dipilih, sebelum membuat CSR (Permintaan Penandatanganan Sertifikat).

  3. Pilih Alamat Email Pengguna Anda, masukkan nilai Nama Umum Anda, pastikan Anda menentukan Disimpan ke disk, lalu pilih Lanjutkan. Biarkan ALAMAT Email CA kosong karena tidak diperlukan.

    Informasi sertifikat yang diharapkan

  4. Masukkan nama untuk file Permintaan Penandatanganan Sertifikat (CSR) di Simpan Sebagai, pilih lokasi di Tempat, lalu pilih Simpan.

    Pilih nama file untuk sertifikat

    Tindakan ini menyimpan file CSR di lokasi yang dipilih. Lokasi defaultnya adalah Desktop. Ingat lokasi yang dipilih untuk file.

  5. Kembali ke halaman Sertifikat, Pengidentifikasi, & Profil di Portal Provisi iOS, gulir ke bawah ke opsi Pemberitahuan Push yang dicentang, lalu pilih Konfigurasi untuk membuat sertifikat.

    Edit halaman ID Aplikasi

  6. Jendela Sertifikat TLS/SSL layanan Pemberitahuan Push Apple muncul. Pilih tombol Buat Sertifikat di bawah bagian Sertifikat TLS/SSL Pengembangan .

    Tombol Buat sertifikat untuk ID Aplikasi

    Layar Buat Sertifikat baru ditampilkan.

    Catatan

    Tutorial ini menggunakan sertifikat pengembangan. Proses yang sama digunakan saat mendaftarkan sertifikat produksi. Pastikan Anda menggunakan jenis sertifikat yang sama saat mengirim pemberitahuan.

  7. Pilih Pilih File, telusuri ke lokasi tempat Anda menyimpan file CSR, lalu klik dua kali nama sertifikat untuk memuatnya. Lalu pilih Lanjutkan.

  8. Setelah portal membuat sertifikat, pilih tombol Unduh . Simpan sertifikat, dan ingat lokasi penyimpanannya.

    Halaman unduhan sertifikat yang dihasilkan

    Sertifikat diunduh dan disimpan ke komputer Anda di folder Unduhan Anda.

    Menemukan file sertifikat di folder Unduhan

    Catatan

    Secara default, sertifikat pengembangan yang diunduh diberi nama aps_development.cer.

  9. Klik dua kali aps_development.cer sertifikat push yang diunduh. Tindakan ini menginstal sertifikat baru di Rantai Kunci, seperti yang ditunjukkan pada gambar berikut:

    Daftar sertifikat akses rantai kunci memperlihatkan sertifikat baru

    Catatan

    Meskipun nama dalam sertifikat Anda mungkin berbeda, namanya akan diawali dengan Apple Development iOS Push Services dan memiliki pengidentifikasi bundel yang sesuai yang terkait dengannya.

  10. Di Akses Rantai Kunci, Klik Kontrol + pada sertifikat push baru yang Anda buat di kategori Sertifikat. Pilih Ekspor, beri nama file, pilih format p12 , lalu pilih Simpan.

    Mengekspor sertifikat sebagai format p12

    Anda dapat memilih untuk melindungi sertifikat dengan kata sandi, tetapi kata sandi bersifat opsional. Klik OK jika Anda ingin melewati pembuatan kata sandi. Catat nama file dan lokasi sertifikat p12 yang diekspor. Mereka digunakan untuk mengaktifkan autentikasi dengan APN.

    Catatan

    Nama dan lokasi file p12 Anda mungkin berbeda dari apa yang digambarkan dalam tutorial ini.

OPSI 2: Membuat sertifikat p8 yang dapat digunakan untuk autentikasi berbasis token
  1. Catat detail berikut:

    • Awalan ID Aplikasi (ID Tim)
    • ID Bundel
  2. Kembali ke Sertifikat, Pengidentifikasi & Profil, klik Kunci.

    Catatan

    Jika Anda sudah memiliki kunci yang dikonfigurasi untuk APNS, Anda dapat menggunakan kembali sertifikat p8 yang Anda unduh tepat setelah dibuat. Jika demikian, Anda dapat mengabaikan langkah 3 hingga 5.

  3. Klik tombol + (atau tombol Buat kunci ) untuk membuat kunci baru.

  4. Berikan nilai Nama Kunci yang sesuai, lalu centang opsi Layanan Pemberitahuan Push Apple (APNS), lalu klik Lanjutkan, diikuti dengan Daftar di layar berikutnya.

  5. Klik Unduh lalu pindahkan file p8 (diawali dengan AuthKey_) ke direktori lokal yang aman, lalu klik Selesai.

    Catatan

    Pastikan untuk menyimpan file p8 Anda di tempat yang aman (dan simpan cadangan). Setelah mengunduh kunci Anda, kunci tidak dapat diunduh ulang karena salinan server dihapus.

  6. Pada Kunci, klik kunci yang Anda buat (atau kunci yang ada jika Anda telah memilih untuk menggunakannya sebagai gantinya).

  7. Catat nilai ID Kunci .

  8. Buka sertifikat p8 Anda dalam aplikasi pilihan Anda yang sesuai seperti Visual Studio Code. Catat nilai kunci (antara -----BEGIN PRIVATE KEY----- dan -----END PRIVATE KEY-----).

    kunci privat -----BEGIN-----
    <key_value>
    -----END PRIVATE KEY-----

    Catatan

    Ini adalah nilai token yang akan digunakan nanti untuk mengonfigurasi Notification Hub.

Di akhir langkah-langkah ini, Anda harus memiliki informasi berikut untuk digunakan nanti di Mengonfigurasi hub pemberitahuan Anda dengan informasi APNS:

  • ID Tim (lihat langkah 1)
  • ID Bundel (lihat langkah 1)
  • ID Kunci (lihat langkah 7)
  • Nilai token (nilai kunci p8 yang diperoleh pada langkah 8)

Membuat profil provisi untuk aplikasi

  1. Kembali ke Portal Provisi iOS, pilih Sertifikat, Pengidentifikasi & Profil, pilih Profil dari menu kiri, lalu pilih + untuk membuat profil baru. Layar Daftarkan Profil Provisi Baru muncul.

  2. Pilih Pengembangan Aplikasi iOS di bagian Pengembangan sebagai jenis profil provisi, lalu pilih Lanjutkan.

    Daftar profil provisi

  3. Selanjutnya, pilih ID aplikasi yang Anda buat dari daftar drop-down ID Aplikasi , dan pilih Lanjutkan.

    Pilih ID Aplikasi

  4. Di jendela Pilih sertifikat , pilih sertifikat pengembangan yang Anda gunakan untuk penandatanganan kode, dan pilih Lanjutkan.

    Catatan

    Sertifikat ini bukan sertifikat push yang Anda buat di langkah sebelumnya. Ini adalah sertifikat pengembangan Anda. Jika tidak ada, Anda harus membuatnya karena ini adalah prasyarat untuk tutorial ini. Sertifikat pengembang dapat dibuat di Portal Pengembang Apple, melalui Xcode atau di Visual Studio.

  5. Kembali ke halaman Sertifikat, Pengidentifikasi & Profil , pilih Profil dari menu sebelah kiri, lalu pilih + untuk membuat profil baru. Layar Daftarkan Profil Provisi Baru muncul.

  6. Di jendela Pilih sertifikat , pilih sertifikat pengembangan yang Anda buat. Lalu pilih Lanjutkan.

  7. Selanjutnya, pilih perangkat yang akan digunakan untuk pengujian, dan pilih Lanjutkan.

  8. Terakhir, pilih nama untuk profil di Nama Profil Provisi, dan pilih Buat.

    Pilih nama profil provisi

  9. Saat profil provisi baru dibuat, pilih Unduh. Ingat lokasi penyimpanannya.

  10. Telusuri ke lokasi profil provisi, lalu klik dua kali untuk menginstalnya di komputer pengembangan Anda.

Membuat Notification Hub

Di bagian ini, Anda membuat hub pemberitahuan dan mengonfigurasi autentikasi dengan APNS. Anda dapat menggunakan sertifikat push p12 atau autentikasi berbasis token. Jika Anda ingin menggunakan hub pemberitahuan yang telah Anda buat, Anda dapat melompat ke langkah 5.

  1. Masuk ke Azure.

  2. Klik Buat sumber daya, lalu cari dan pilih Notification Hub, lalu klik Buat.

  3. Perbarui bidang berikut, lalu klik Buat:

    DETAIL DASAR

    Berlangganan: Pilih Langganan target dari daftar drop-down
    Grup Sumber Daya: Buat Grup Sumber Daya baru (atau pilih yang sudah ada)

    DETAIL NAMESPACE

    Namespace Notification Hub: Masukkan nama unik global untuk namespace Notification Hub

    Catatan

    Pastikan opsi Buat baru dipilih untuk bidang ini.

    DETAIL HUB PEMBERITAHUAN

    Notification Hub: Masukkan nama untuk Notification Hub
    Lokasi: Pilih lokasi yang sesuai dari daftar drop-down
    Tingkat Harga: Pertahankan opsi Gratis default

    Catatan

    Kecuali Anda telah mencapai jumlah maksimum hub pada tingkat gratis.

  4. Setelah Notification Hub disediakan, navigasikan ke sumber daya tersebut.

  5. Navigasikan ke Notification Hub baru Anda.

  6. Pilih Kebijakan Akses dari daftar (di bawah KELOLA) .

  7. Catat nilai Nama Kebijakan bersama dengan nilai String Koneksi terkait.

Mengonfigurasi Notification Hub Anda dengan informasi APNS

Di bawah Layanan Pemberitahuan, pilih Apple lalu ikuti langkah-langkah yang sesuai berdasarkan pendekatan yang Anda pilih sebelumnya di bagian Membuat Sertifikat untuk Notification Hubs .

Catatan

Gunakan Mode Produksi untuk Aplikasi hanya jika Anda ingin mengirim pemberitahuan push kepada pengguna yang membeli aplikasi Anda dari toko.

OPSI 1: Menggunakan sertifikat pendorongan .p12

  1. Pilih Sertifikat.

  2. Pilih ikon file.

  3. Pilih file .p12 yang Anda ekspor sebelumnya, lalu pilih Buka.

  4. Jika perlu, tentukan kata sandi yang benar.

  5. Pilih Mode kotak pasir .

  6. Pilih Simpan.

OPSI 2: Menggunakan autentikasi berbasis token

  1. Pilih Token.

  2. Masukkan nilai berikut yang Anda peroleh sebelumnya:

    • ID Kunci
    • ID Bundel
    • ID Tim
    • Token
  3. Pilih Sandbox.

  4. Pilih Simpan.

Mengonfigurasi hub pemberitahuan Anda dengan informasi FCM

  1. Pilih Google (GCM/FCM) di bagian Pengaturan di menu sebelah kiri.
  2. Masukkan kunci server yang Anda catat dari Google Firebase Console.
  3. Pilih Simpan pada toolbar.

Membuat aplikasi backend ASP.NET Core Web API

Di bagian ini, Anda membuat backend ASP.NET Core Web API untuk menangani pendaftaran perangkat dan pengiriman pemberitahuan ke aplikasi seluler Flutter.

Membuat proyek web

  1. Di Visual Studio, pilih File>Solusi Baru.

  2. Pilih .NET Core>App>ASP.NET Core>API>Berikutnya.

  3. Dalam dialog Konfigurasikan ASP.NET Core Web API baru Anda , pilih Kerangka Kerja Target.NET Core 3.1.

  4. Masukkan PushDemoApi untuk Nama Proyek lalu pilih Buat.

  5. Mulai penelusuran kesalahan (Command + Enter) untuk menguji aplikasi templat.

    Catatan

    Aplikasi templat dikonfigurasi untuk menggunakan WeatherForecastController sebagai launchUrl. Ini diatur dalam launchSettings.json Properti>.

    Jika Anda diminta dengan pesan sertifikat pengembangan yang ditemukan tidak valid :

    1. Klik Ya untuk menyetujui menjalankan alat 'dotnet dev-certs https' untuk memperbaikinya. Alat 'dotnet dev-certs https' kemudian meminta Anda untuk memasukkan kata sandi untuk sertifikat dan kata sandi untuk Rantai Kunci Anda.

    2. Klik Ya saat diminta untuk Menginstal dan mempercayai sertifikat baru, lalu masukkan kata sandi untuk Rantai Kunci Anda.

  6. Perluas folder Pengontrol , lalu hapus WeatherForecastController.cs.

  7. Hapus WeatherForecast.cs.

  8. Siapkan nilai konfigurasi lokal menggunakan alat Secret Manager. Memisahkan rahasia dari solusi memastikan bahwa rahasia tersebut tidak berakhir dalam kontrol sumber. Buka Terminal lalu buka direktori file proyek dan jalankan perintah berikut:

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

    Ganti nilai tempat penampung dengan nama hub pemberitahuan Anda sendiri dan nilai string koneksi. Anda mencatatnya di bagian buat hub pemberitahuan . Jika tidak, Anda dapat mencarinya di Azure.

    NotificationHub:Name:
    Lihat Nama di ringkasan Esensial di bagian atas Gambaran Umum.

    NotificationHub:ConnectionString:
    Lihat DefaultFullSharedAccessSignature dalam Kebijakan Akses

    Catatan

    Untuk skenario produksi, Anda dapat melihat opsi seperti Azure KeyVault untuk menyimpan string koneksi dengan aman. Untuk kesederhanaan, rahasia akan ditambahkan ke pengaturan aplikasi Azure App Service.

Mengautentikasi klien menggunakan Kunci API (Opsional)

Kunci API tidak seaman token, tetapi cukup untuk tujuan tutorial ini. Kunci API dapat dikonfigurasi dengan mudah melalui ASP.NET Middleware.

  1. Tambahkan kunci API ke nilai konfigurasi lokal.

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

    Catatan

    Anda harus mengganti nilai tempat penampung dengan nilai Anda sendiri dan mencatatnya.

  2. Kontrol + Klik proyek PushDemoApi , pilih Folder Baru dari menu Tambahkan , lalu klik Tambahkan menggunakan Autentikasi sebagai Nama Folder.

  3. Kontrol + Klik folder Autentikasi , lalu pilih File Baru... dari menu Tambahkan .

  4. PilihKelas KosongUmum>, masukkan ApiKeyAuthOptions.cs untuk Nama, lalu klik Baru menambahkan implementasi berikut.

    using Microsoft.AspNetCore.Authentication;
    
    namespace PushDemoApi.Authentication
    {
        public class ApiKeyAuthOptions : AuthenticationSchemeOptions
        {
            public const string DefaultScheme = "ApiKey";
            public string Scheme => DefaultScheme;
            public string ApiKey { get; set; }
        }
    }
    
  5. Tambahkan Kelas Kosong lain ke folder Autentikasi yang disebut ApiKeyAuthHandler.cs, lalu tambahkan implementasi berikut.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Text.Encodings.Web;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    namespace PushDemoApi.Authentication
    {
        public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions>
        {
            const string ApiKeyIdentifier = "apikey";
    
            public ApiKeyAuthHandler(
                IOptionsMonitor<ApiKeyAuthOptions> options,
                ILoggerFactory logger,
                UrlEncoder encoder,
                ISystemClock clock)
                : base(options, logger, encoder, clock) {}
    
            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));
            }
        }
    }
    

    Catatan

    Handler Autentikasi adalah jenis yang mengimplementasikan perilaku skema, dalam hal ini skema Kunci API kustom.

  6. Tambahkan Kelas Kosong lain ke folder Autentikasi yang disebut ApiKeyAuthenticationBuilderExtensions.cs, lalu tambahkan implementasi berikut.

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

    Catatan

    Metode ekstensi ini menyederhanakan kode konfigurasi middleware dalam Startup.cs membuatnya lebih mudah dibaca dan umumnya lebih mudah diikuti.

  7. Di Startup.cs, perbarui metode ConfigureServices untuk mengonfigurasi autentikasi Kunci API di bawah panggilan ke layanan. Metode AddControllers .

    using PushDemoApi.Authentication;
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
            options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
        }).AddApiKeyAuth(Configuration.GetSection("Authentication").Bind);
    }
    
  8. Masih dalam Startup.cs, perbarui metode Konfigurasi untuk memanggil metode ekstensi UseAuthentication dan UseAuthorization pada IApplicationBuilder aplikasi. Pastikan metode tersebut dipanggil setelah UseRouting dan sebelum aplikasi. Gunakan Titik Akhir.

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseHttpsRedirection();
    
        app.UseRouting();
    
        app.UseAuthentication();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
    

    Catatan

    Memanggil UseAuthentication mendaftarkan middleware yang menggunakan skema autentikasi yang terdaftar sebelumnya (dari ConfigureServices). Ini harus dipanggil sebelum middleware apa pun yang bergantung pada pengguna yang diautentikasi.

Menambahkan dependensi dan mengonfigurasi layanan

ASP.NET Core mendukung pola desain perangkat lunak injeksi dependensi (DI ), yang merupakan teknik untuk mencapai Inversion of Control (IoC) antara kelas dan dependensinya.

Penggunaan hub pemberitahuan dan Notification Hubs SDK untuk operasi backend dienkapsulasi dalam layanan. Layanan ini terdaftar dan tersedia melalui abstraksi yang sesuai.

  1. Kontrol + Klik folder Dependensi , lalu pilih Kelola Paket NuGet....

  2. Cari Microsoft.Azure.NotificationHubs dan pastikan diperiksa.

  3. Klik Tambahkan Paket, lalu klik Terima saat diminta untuk menerima persyaratan lisensi.

  4. Kontrol + Klik proyek PushDemoApi , pilih Folder Baru dari menu Tambahkan , lalu klik Tambahkan menggunakan Model sebagai Nama Folder.

  5. Kontrol + Klik folder Model , lalu pilih File Baru... dari menu Tambahkan .

  6. PilihKelas KosongUmum>, masukkan PushTemplates.cs untuk Nama, lalu klik Baru menambahkan implementasi berikut.

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

    Catatan

    Kelas ini berisi payload pemberitahuan yang ditokenisasi untuk pemberitahuan generik dan senyap yang diperlukan oleh skenario ini. Payload 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 tutorial ini. Untuk produksi, pertimbangkan templat kustom.

  7. Tambahkan Kelas Kosong lain ke folder Model yang disebut DeviceInstallation.cs, lalu tambahkan implementasi berikut.

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.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>();
        }
    }
    
  8. Tambahkan Kelas Kosong lain ke folder Model yang disebut NotificationRequest.cs, lalu tambahkan implementasi berikut.

    using System;
    
    namespace PushDemoApi.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; }
        }
    }
    
  9. Tambahkan Kelas Kosong lain ke folder Model yang disebut NotificationHubOptions.cs, lalu tambahkan implementasi berikut.

    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class NotificationHubOptions
        {
            [Required]
            public string Name { get; set; }
    
            [Required]
            public string ConnectionString { get; set; }
        }
    }
    
  10. Tambahkan folder baru ke proyek PushDemoApi yang disebut Layanan.

  11. Tambahkan Antarmuka Kosong ke folder Layanan yang disebut INotificationService.cs, lalu tambahkan implementasi berikut.

    using System.Threading;
    using System.Threading.Tasks;
    using PushDemoApi.Models;
    
    namespace PushDemoApi.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);
        }
    }
    
  12. Tambahkan Kelas Kosong ke folder Layanan yang disebut NotificationHubsService.cs, lalu tambahkan kode berikut untuk mengimplementasikan antarmuka INotificationService :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using PushDemoApi.Models;
    
    namespace PushDemoApi.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.Fcm).ToLower(), NotificationPlatform.Fcm }
                };
            }
    
            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.SendFcmNativeNotificationAsync(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.SendFcmNativeNotificationAsync(androidPayload, tags, token),
                    _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token)
                };
    
                return Task.WhenAll(sendTasks);
            }
        }
    }
    

    Catatan

    Ekspresi tag yang disediakan untuk SendTemplateNotificationAsync dibatasi hingga 20 tag. Ini dibatasi hingga 6 untuk sebagian besar operator tetapi ekspresi hanya berisi OU (||) dalam hal ini. Jika ada lebih dari 20 tag dalam permintaan, tag tersebut harus dibagi menjadi beberapa permintaan. Lihat dokumentasi Perutean dan Ekspresi Tag untuk detail selengkapnya.

  13. Di Startup.cs, perbarui metode ConfigureServices untuk menambahkan NotificationHubsService sebagai implementasi database tunggal INotificationService.

    
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    
        services.AddSingleton<INotificationService, NotificationHubService>();
    
        services.AddOptions<NotificationHubOptions>()
            .Configure(Configuration.GetSection("NotificationHub").Bind)
            .ValidateDataAnnotations();
    }
    

Membuat API pemberitahuan

  1. Kontrol + Klik folder Pengontrol , lalu pilih File Baru... dari menu Tambahkan .

  2. Pilih ASP.NET>Core Web API Controller Class, masukkan NotificationsController untuk Nama, lalu klik Baru.

    Catatan

    Jika Anda mengikuti Visual Studio 2019, pilih Pengontrol API dengan templat tindakan baca/tulis .

  3. Tambahkan namespace berikut ke bagian atas file.

    using System.ComponentModel.DataAnnotations;
    using System.Net;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
  4. Perbarui pengontrol templat sehingga berasal dari ControllerBase dan didekorasi dengan atribut ApiController .

    [ApiController]
    [Route("api/[controller]")]
    public class NotificationsController : ControllerBase
    {
        // Templated methods here
    }
    

    Catatan

    Kelas dasar Pengontrol menyediakan dukungan untuk tampilan tetapi ini tidak diperlukan dalam hal ini sehingga ControllerBase dapat digunakan sebagai gantinya. Jika Mengikuti Visual Studio 2019, Anda dapat melewati langkah ini.

  5. Jika Anda memilih untuk menyelesaikan klien Autentikasi menggunakan bagian Kunci API , Anda juga harus menghias NotificationsController dengan atribut Otorisasi .

    [Authorize]
    
  6. Perbarui konstruktor untuk menerima instans terdaftar INotificationService sebagai argumen dan tetapkan ke anggota readonly.

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  7. Di launchSettings.json (dalam folder Properti ), ubah launchUrl dari weatherforecast ke api/pemberitahuan agar sesuai dengan URL yang ditentukan dalam atribut RegistrationsControllerRoute .

  8. Mulai penelusuran kesalahan (Command + Enter) untuk memvalidasi aplikasi bekerja dengan NotificationsController baru dan mengembalikan status Tidak Sah 401 .

    Catatan

    Visual Studio mungkin tidak secara otomatis meluncurkan aplikasi di browser. Anda akan menggunakan Postman untuk menguji API mulai saat ini.

  9. Pada tab Postman baru, atur permintaan ke GET. Masukkan alamat di bawah ini mengganti applicationUrl> tempat penampung< dengan applicationUrl https yang ditemukan di Properti>launchSettings.json.

    <applicationUrl>/api/notifications
    

    Catatan

    applicationUrl harus 'https://localhost:5001' untuk profil default. Jika Anda menggunakan IIS (default di Visual Studio 2019 di Windows), Anda harus menggunakan applicationUrl yang ditentukan dalam item iisSettings sebagai gantinya. Anda akan menerima respons 404 jika alamat salah.

  10. Jika Anda memilih untuk menyelesaikan klien Autentikasi menggunakan bagian Kunci API , pastikan untuk mengonfigurasi header permintaan untuk menyertakan nilai apikey Anda.

    Kunci Nilai
    apikey <your_api_key>
  11. Klik tombol Kirim .

    Catatan

    Anda akan menerima status 200 OK dengan beberapa konten JSON .

    Jika Anda menerima peringatan verifikasi sertifikat SSL , Anda dapat mengalihkan pengaturan postman verifikasi sertifikat SSL permintaan di Pengaturan.

  12. Ganti metode kelas templat di NotificationsController.cs 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)
    {
        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();
    }
    

Membuat aplikasi API

Anda sekarang membuat Aplikasi API di Azure App Service untuk menghosting layanan backend.

  1. Masuk ke portal Azure.

  2. Klik Buat sumber daya, lalu cari dan pilih Aplikasi API, lalu klik Buat.

  3. Perbarui bidang berikut, lalu klik Buat.

    Nama aplikasi:
    Masukkan nama unik global untuk Aplikasi API

    Berlangganan:
    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.

    Rencana/Lokasi App Service:
    Membuat Paket App Service baru

    Catatan

    Ubah dari opsi default menjadi paket yang menyertakan dukungan SSL . Jika tidak, Anda harus mengambil langkah-langkah yang sesuai saat bekerja dengan aplikasi seluler untuk mencegah permintaan http diblokir.

    Application Insights:
    Pertahankan opsi yang disarankan (sumber daya baru akan dibuat menggunakan nama tersebut) atau pilih sumber daya yang ada.

  4. Setelah Aplikasi API disediakan, navigasikan ke sumber daya tersebut.

  5. Catat properti URL di ringkasan Esensial di bagian atas Gambaran Umum. URL ini adalah titik akhir backend Anda yang akan digunakan nanti dalam tutorial ini.

    Catatan

    URL menggunakan nama aplikasi API yang Anda tentukan sebelumnya, dengan format https://<app_name>.azurewebsites.net.

  6. Pilih Konfigurasi dari daftar (di bawah Pengaturan).

  7. Untuk setiap pengaturan di bawah ini, klik Pengaturan aplikasi baru untuk memasukkan Nama dan Nilai, lalu klik OK.

    Nama Nilai
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Catatan

    Ini adalah pengaturan yang sama dengan yang Anda tentukan sebelumnya di pengaturan pengguna. Anda harus dapat menyalin ini. Pengaturan Authentication:ApiKey diperlukan hanya jika Anda memilih untuk menyelesaikan klien Autentikasi menggunakan bagian Kunci API . Untuk skenario produksi, Anda dapat melihat opsi seperti Azure KeyVault. Ini telah ditambahkan sebagai pengaturan aplikasi untuk kesederhanaan dalam kasus ini.

  8. Setelah semua pengaturan aplikasi ditambahkan, klik Simpan, lalu Lanjutkan.

Menerbitkan layanan backend

Selanjutnya, Anda menyebarkan aplikasi ke Aplikasi API untuk membuatnya dapat diakses dari semua perangkat.

Catatan

Langkah-langkah berikut khusus untuk Visual Studio untuk Mac. Jika Anda mengikuti Visual Studio 2019 di Windows, alur penerbitan akan berbeda. Lihat Menerbitkan ke Azure App Service di Windows.

  1. Ubah konfigurasi Anda dari Debug ke Rilis jika Anda belum melakukannya.

  2. Kontrol + Klik proyek PushDemoApi , lalu pilih Terbitkan ke Azure... dari menu Terbitkan .

  3. Ikuti alur autentikasi jika diminta untuk melakukannya. Gunakan akun yang Anda gunakan di bagian buat Aplikasi API sebelumnya.

  4. Pilih Aplikasi API Azure App Service yang Anda buat sebelumnya dari daftar sebagai target publikasi Anda, lalu klik Terbitkan.

Setelah Anda menyelesaikan wizard, wizard menerbitkan aplikasi ke Azure lalu membuka aplikasi. Catat URL jika Anda belum melakukannya. URL ini adalah titik akhir backend Anda yang digunakan nanti dalam tutorial ini.

Memvalidasi API yang diterbitkan

  1. Di Postman buka tab baru, atur permintaan ke PUT dan masukkan alamat di bawah ini. Ganti tempat penampung dengan alamat dasar yang Anda catat di bagian sebelumnya terbitkan layanan backend .

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

    Catatan

    Alamat dasar harus dalam format https://<app_name>.azurewebsites.net/

  2. Jika Anda memilih untuk menyelesaikan bagian Autentikasi klien menggunakan Kunci API , pastikan untuk mengonfigurasi header permintaan untuk menyertakan nilai apikey Anda.

    Kunci Nilai
    apikey <your_api_key>
  3. Pilih opsi mentah untuk Isi, lalu pilih JSON dari daftar opsi format, lalu sertakan beberapa konten JSON tempat penampung:

    {}
    
  4. Klik Kirim.

    Catatan

    Anda harus menerima status UnprocessableEntity 422 dari layanan.

  5. Lakukan langkah 1-4 lagi tetapi kali ini menentukan titik akhir permintaan untuk memvalidasi Anda menerima respons 400 Permintaan Buruk .

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

Catatan

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

Membuat aplikasi Flutter lintas platform

Di bagian ini, Anda membangun aplikasi seluler Flutter yang menerapkan pemberitahuan push secara lintas platform.

Ini memungkinkan Anda untuk mendaftar dan membatalkan pendaftaran dari hub pemberitahuan melalui layanan backend yang Anda buat.

Pemberitahuan ditampilkan saat tindakan ditentukan dan aplikasi berada di latar depan. Jika tidak, pemberitahuan muncul di pusat pemberitahuan.

Catatan

Anda biasanya akan melakukan tindakan pendaftaran (dan deregistrasi) selama titik yang sesuai dalam siklus hidup aplikasi (atau sebagai bagian dari pengalaman eksekusi pertama Anda mungkin) tanpa input pendaftaran/deregister pengguna eksplisit. Namun, contoh ini akan memerlukan input pengguna eksplisit untuk memungkinkan fungsionalitas ini dieksplorasi dan diuji dengan lebih mudah.

Membuat solusi Flutter

  1. Buka instans baru Visual Studio Code.

  2. Buka Palet Perintah (Perintah + Shift + P).

  3. Pilih perintah Flutter: New Project lalu tekan Enter.

  4. Masukkan push_demo untuk Nama Proyek lalu pilih Lokasi proyek.

  5. Saat diminta untuk melakukannya, pilih Dapatkan Paket.

  6. Kontrol + Klik folder kotlin (di bawah app>src>main), lalu pilih Ungkap di Finder. Kemudian, ganti nama folder anak (di bawah folder kotlin ) menjadi com, <your_organization>, dan pushdemo masing-masing.

    Catatan

    Saat menggunakan templat Visual Studio Code folder ini default ke com, misalnya, <project_name>. Dengan asumsi mobcat digunakan untuk organisasi, struktur folder harus secara indikatif muncul sebagai:

    • kotlin
      • Com
        • mobcat
          • pushdemo
  7. Kembali ke Visual Studio Code, perbarui nilai applicationId diaplikasi>android>build.gradle ke com.<your_organization>.pushdemo.

    Catatan

    Anda harus menggunakan nama organisasi Anda sendiri untuk <tempat penampung your_organization> . Misalnya, menggunakan mobcat sebagai organisasi akan menghasilkan nilai nama paketcom.mobcat.pushdemo.

  8. Perbarui atribut paket dalam file AndroidManifest.xml, di bawahdebugsrc>, src>utama, danprofilsrc> masing-masing. Pastikan nilai cocok dengan applicationId yang Anda gunakan di langkah sebelumnya.

    <manifest
        xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.<your_organization>.pushdemo>">
        ...
    </manifest>
    
  9. android:label Perbarui atribut dalam file AndroidManifest.xml di bawah src>main ke PushDemo. Kemudian, tambahkan android:allowBackup atribut , langsung di bawah android:label, atur nilainya ke false.

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="PushDemo"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher">
        ...
    </application>
    
  10. Buka file build.gradle tingkat aplikasi (aplikasi>android>build.gradle), lalu perbarui compileSdkVersion (dari bagian android) untuk menggunakan API 29. Kemudian, perbarui nilai minSdkVersion dan targetSdkVersion (dari bagian defaultConfig ), menjadi masing-masing 26 dan 29 .

    Catatan

    Hanya perangkat yang menjalankan API level 26 ke atas yang didukung untuk tujuan tutorial ini namun Anda dapat memperluasnya untuk mendukung perangkat yang menjalankan versi yang lebih lama.

  11. Kontrol + Klik folder ios , lalu pilih Buka di Xcode.

  12. Di Xcode, klik Runner ( xcodeproj di bagian atas, bukan folder). Kemudian, pilih target Runner dan pilih tab Umum . Dengan konfigurasi Semua build dipilih, perbarui Pengidentifikasi Bundel ke com.<your_organization>.PushDemo.

    Catatan

    Anda harus menggunakan nama organisasi Anda sendiri untuk <tempat penampung your_organization> . Misalnya, menggunakan mobcat sebagai organisasi akan menghasilkan nilai Pengidentifikasi Bundelcom.mobcat.PushDemo.

  13. Klik Info.plist lalu perbarui nilai Nama bundel ke PushDemo

  14. Tutup Xcode dan kembali ke Visual Studio Code.

  15. Kembali ke Visual Studio Code, buka pubspec.yaml, tambahkan paket http dan flutter_secure_storageDart sebagai dependensi. Kemudian, simpan file dan klik Dapatkan Paket saat diminta untuk melakukannya.

    dependencies:
      flutter:
        sdk: flutter
    
      http: ^0.12.1
      flutter_secure_storage: ^3.3.3
    
  16. Di Terminal, ubah direktori ke folder ios (untuk proyek Flutter Anda). Kemudian, jalankan perintah instal pod untuk menginstal pod baru (diperlukan oleh paket flutter_secure_storage ).

  17. Kontrol + Klik folder lib , lalu pilih File Baru dari menu menggunakan main_page.dart sebagai nama file. Kemudian, tambahkan kode berikut.

    import 'package:flutter/material.dart';
    
    class MainPage extends StatefulWidget {
      @override
      _MainPageState createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[],
            )
          )
        );
      }
    }
    
  18. Di main.dart, ganti kode templat dengan yang berikut ini.

    import 'package:flutter/material.dart';
    import 'package:push_demo/main_page.dart';
    
    final navigatorKey = GlobalKey<NavigatorState>();
    
    void main() => runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey));
    
  19. Di Terminal, buat dan jalankan aplikasi di setiap platform target untuk menguji aplikasi templat yang berjalan di perangkat Anda. Pastikan perangkat yang didukung tersambung.

    flutter run
    

Menerapkan komponen lintas platform

  1. Kontrol + Klik folder lib , lalu pilih Folder Baru dari menu menggunakan model sebagai Nama Folder.

  2. Kontrol + Klik folder model , lalu pilih File Baru dari menu menggunakan device_installation.dart sebagai nama file. Kemudian, tambahkan kode berikut.

    class DeviceInstallation {
        final String deviceId;
        final String platform;
        final String token;
        final List<String> tags;
    
        DeviceInstallation(this.deviceId, this.platform, this.token, this.tags);
    
        DeviceInstallation.fromJson(Map<String, dynamic> json)
          : deviceId = json['installationId'],
            platform = json['platform'],
            token = json['pushChannel'],
            tags = json['tags'];
    
        Map<String, dynamic> toJson() =>
        {
          'installationId': deviceId,
          'platform': platform,
          'pushChannel': token,
          'tags': tags,
        };
    }
    
  3. Tambahkan file baru ke folder model yang disebut push_demo_action.dart yang menentukan enumerasi tindakan yang didukung dalam contoh ini.

    enum PushDemoAction {
      actionA,
      actionB,
    }
    
  4. Tambahkan folder baru ke proyek yang disebut layanan lalu tambahkan file baru ke folder yang disebut device_installation_service.dart dengan implementasi berikut.

    import 'package:flutter/services.dart';
    
    class DeviceInstallationService {
      static const deviceInstallation = const MethodChannel('com.<your_organization>.pushdemo/deviceinstallation');
      static const String getDeviceIdChannelMethod = "getDeviceId";
      static const String getDeviceTokenChannelMethod = "getDeviceToken";
      static const String getDevicePlatformChannelMethod = "getDevicePlatform";
    
      Future<String> getDeviceId() {
        return deviceInstallation.invokeMethod(getDeviceIdChannelMethod);
      }
    
      Future<String> getDeviceToken() {
        return deviceInstallation.invokeMethod(getDeviceTokenChannelMethod);
      }
    
      Future<String> getDevicePlatform() {
        return deviceInstallation.invokeMethod(getDevicePlatformChannelMethod);
      }
    }
    

    Catatan

    Anda harus menggunakan nama organisasi Anda sendiri untuk <tempat penampung your_organization> . Misalnya, menggunakan mobcat sebagai organisasi akan menghasilkan nama MethodChannelcom.mobcat.pushdemo/deviceinstallation.

    Kelas ini merangkum bekerja dengan platform asli yang mendasarinya untuk memperoleh detail penginstalan perangkat yang diperlukan. MethodChannel memfasilitasi komunikasi asinkron dua arah dengan platform asli yang mendasar. Mitra khusus platform untuk saluran ini akan dibuat pada langkah-langkah selanjutnya.

  5. Tambahkan file lain ke folder yang disebut notification_action_service.dart dengan implementasi berikut.

    import 'package:flutter/services.dart';
    import 'dart:async';
    import 'package:push_demo/models/push_demo_action.dart';
    
    class NotificationActionService {
      static const notificationAction =
          const MethodChannel('com.<your_organization>.pushdemo/notificationaction');
      static const String triggerActionChannelMethod = "triggerAction";
      static const String getLaunchActionChannelMethod = "getLaunchAction";
    
      final actionMappings = {
        'action_a' : PushDemoAction.actionA,
        'action_b' : PushDemoAction.actionB
      };
    
      final actionTriggeredController = StreamController.broadcast();
    
      NotificationActionService() {
        notificationAction
            .setMethodCallHandler(handleNotificationActionCall);
      }
    
      Stream get actionTriggered => actionTriggeredController.stream;
    
      Future<void> triggerAction({action: String}) async {
    
        if (!actionMappings.containsKey(action)) {
          return;
        }
    
        actionTriggeredController.add(actionMappings[action]);
      }
    
      Future<void> checkLaunchAction() async {
        final launchAction = await notificationAction.invokeMethod(getLaunchActionChannelMethod) as String;
    
        if (launchAction != null) {
          triggerAction(action: launchAction);
        }
      }
    
      Future<void> handleNotificationActionCall(MethodCall call) async {
        switch (call.method) {
          case triggerActionChannelMethod:
            return triggerAction(action: call.arguments as String);
          default:
            throw MissingPluginException();
            break;
        }
      }
    }
    

    Catatan

    Ini digunakan sebagai mekanisme sederhana untuk mempusatkan penanganan tindakan pemberitahuan sehingga dapat ditangani dengan cara lintas platform menggunakan enumerasi yang ditik dengan kuat. Layanan ini memungkinkan platform asli yang mendasar untuk memicu tindakan, ketika satu ditentukan dalam payload pemberitahuan. Ini juga memungkinkan kode umum untuk secara retrospektif memeriksa apakah tindakan ditentukan selama peluncuran aplikasi setelah Flutter siap untuk memprosesnya. Misalnya, saat aplikasi diluncurkan dengan mengetuk pemberitahuan dari pusat pemberitahuan.

  6. Tambahkan file baru ke folder layanan yang disebut notification_registration_service.dart dengan implementasi berikut.

    import 'dart:convert';
    import 'package:flutter/services.dart';
    import 'package:http/http.dart' as http;
    import 'package:push_demo/services/device_installation_service.dart';
    import 'package:push_demo/models/device_installation.dart';
    import 'package:flutter_secure_storage/flutter_secure_storage.dart';
    
    class NotificationRegistrationService {
      static const notificationRegistration =
          const MethodChannel('com.<your_organization>.pushdemo/notificationregistration');
    
      static const String refreshRegistrationChannelMethod = "refreshRegistration";
      static const String installationsEndpoint = "api/notifications/installations";
      static const String cachedDeviceTokenKey = "cached_device_token";
      static const String cachedTagsKey = "cached_tags";
    
      final deviceInstallationService = DeviceInstallationService();
      final secureStorage = FlutterSecureStorage();
    
      String baseApiUrl;
      String apikey;
    
      NotificationRegistrationService(this.baseApiUrl, this.apikey) {
        notificationRegistration
            .setMethodCallHandler(handleNotificationRegistrationCall);
      }
    
      String get installationsUrl => "$baseApiUrl$installationsEndpoint";
    
      Future<void> deregisterDevice() async {
        final cachedToken = await secureStorage.read(key: cachedDeviceTokenKey);
        final serializedTags = await secureStorage.read(key: cachedTagsKey);
    
        if (cachedToken == null || serializedTags == null) {
          return;
        }
    
        var deviceId = await deviceInstallationService.getDeviceId();
    
        if (deviceId.isEmpty) {
          throw "Unable to resolve an ID for the device.";
        }
    
        var response = await http
            .delete("$installationsUrl/$deviceId", headers: {"apikey": apikey});
    
        if (response.statusCode != 200) {
          throw "Deregister request failed: ${response.reasonPhrase}";
        }
    
        await secureStorage.delete(key: cachedDeviceTokenKey);
        await secureStorage.delete(key: cachedTagsKey);
      }
    
      Future<void> registerDevice(List<String> tags) async {
        try {
          final deviceId = await deviceInstallationService.getDeviceId();
          final platform = await deviceInstallationService.getDevicePlatform();
          final token = await deviceInstallationService.getDeviceToken();
    
          final deviceInstallation =
              DeviceInstallation(deviceId, platform, token, tags);
    
          final response = await http.put(installationsUrl,
              body: jsonEncode(deviceInstallation),
              headers: {"apikey": apikey, "Content-Type": "application/json"});
    
          if (response.statusCode != 200) {
            throw "Register request failed: ${response.reasonPhrase}";
          }
    
          final serializedTags = jsonEncode(tags);
    
          await secureStorage.write(key: cachedDeviceTokenKey, value: token);
          await secureStorage.write(key: cachedTagsKey, value: serializedTags);
        } on PlatformException catch (e) {
          throw e.message;
        } catch (e) {
          throw "Unable to register device: $e";
        }
      }
    
      Future<void> refreshRegistration() async {
        final currentToken = await deviceInstallationService.getDeviceToken();
        final cachedToken = await secureStorage.read(key: cachedDeviceTokenKey);
        final serializedTags = await secureStorage.read(key: cachedTagsKey);
    
        if (currentToken == null ||
            cachedToken == null ||
            serializedTags == null ||
            currentToken == cachedToken) {
          return;
        }
    
        final tags = jsonDecode(serializedTags);
    
        return registerDevice(tags);
      }
    
      Future<void> handleNotificationRegistrationCall(MethodCall call) async {
        switch (call.method) {
          case refreshRegistrationChannelMethod:
            return refreshRegistration();
          default:
            throw MissingPluginException();
            break;
        }
      }
    }
    

    Catatan

    Kelas ini merangkum penggunaan DeviceInstallationService dan permintaan ke layanan backend untuk melakukan tindakan pendaftaran, deregister, dan refresh pendaftaran yang diperlukan. Argumen apiKey hanya diperlukan jika Anda memilih untuk menyelesaikan klien Autentikasi menggunakan bagian Kunci API .

  7. Tambahkan file baru ke folder lib yang disebut config.dart dengan implementasi berikut.

    class Config {
      static String apiKey = "API_KEY";
      static String backendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT";
    }
    

    Catatan

    Ini digunakan sebagai cara sederhana untuk menentukan rahasia aplikasi. Ganti nilai tempat penampung dengan nilai Anda sendiri. Anda seharusnya mencatat ini ketika Anda membangun layanan backend. URL Aplikasi API harus https://<api_app_name>.azurewebsites.net/. Anggota apiKey hanya diperlukan jika Anda memilih untuk menyelesaikan klien Autentikasi menggunakan bagian Kunci API .

    Pastikan untuk menambahkan ini ke file gitignore Anda untuk menghindari penerapan rahasia ini ke kontrol sumber.

Menerapkan UI lintas platform

  1. Di main_page.dart, ganti fungsi build dengan yang berikut.

    @override
    Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 40.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              FlatButton(
                child: Text("Register"),
                onPressed: registerButtonClicked,
              ),
              FlatButton(
                child: Text("Deregister"),
                onPressed: deregisterButtonClicked,
              ),
            ],
          ),
        ),
      );
    }
    
  2. Tambahkan impor yang disyaratkan ke bagian atas file main_page.dart .

    import 'package:push_demo/services/notification_registration_service.dart';
    import 'config.dart';
    
  3. Tambahkan bidang ke kelas _MainPageState untuk menyimpan referensi ke NotificationRegistrationService.

    final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
    
  4. Di kelas _MainPageState , terapkan penanganan aktivitas untuk tombol Daftar dan Batalkan pendaftaranpada peristiwa yang ditekan . Panggil metode Register/Deregister yang sesuai lalu tampilkan pemberitahuan untuk menunjukkan hasilnya.

    void registerButtonClicked() async {
        try {
          await notificationRegistrationService.registerDevice(List<String>());
          await showAlert(message: "Device registered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      void deregisterButtonClicked() async {
        try {
          await notificationRegistrationService.deregisterDevice();
          await showAlert(message: "Device deregistered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      Future<void> showAlert({ message: String }) async {
        return showDialog<void>(
          context: context,
          barrierDismissible: false,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('PushDemo'),
              content: SingleChildScrollView(
                child: ListBody(
                  children: <Widget>[
                    Text(message),
                  ],
                ),
              ),
              actions: <Widget>[
                FlatButton(
                  child: Text('OK'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
      }
    
  5. Sekarang di main.dart, pastikan impor berikut ada di bagian atas file.

    import 'package:flutter/material.dart';
    import 'package:push_demo/models/push_demo_action.dart';
    import 'package:push_demo/services/notification_action_service.dart';
    import 'package:push_demo/main_page.dart';
    
  6. Deklarasikan variabel untuk menyimpan referensi ke instans NotificationActionService dan menginisialisasinya.

    final notificationActionService = NotificationActionService();
    
  7. Tambahkan fungsi untuk menangani tampilan pemberitahuan saat tindakan dipicu.

    void notificationActionTriggered(PushDemoAction action) {
      showActionAlert(message: "${action.toString().split(".")[1]} action received");
    }
    
    Future<void> showActionAlert({ message: String }) async {
      return showDialog<void>(
        context: navigatorKey.currentState.overlay.context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('PushDemo'),
            content: SingleChildScrollView(
              child: ListBody(
                children: <Widget>[
                  Text(message),
                ],
              ),
            ),
            actions: <Widget>[
              FlatButton(
                child: Text('OK'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }
    
  8. Perbarui fungsi utama untuk mengamati streaming NotificationActionServiceactionTriggered dan periksa tindakan apa pun yang diambil selama peluncuran aplikasi.

    void main() async {
      runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey,));
      notificationActionService.actionTriggered.listen((event) { notificationActionTriggered(event as PushDemoAction); });
      await notificationActionService.checkLaunchAction();
    }
    

    Catatan

    Ini hanya untuk menunjukkan tanda terima dan penyebaran tindakan pemberitahuan push. Biasanya, ini akan ditangani secara diam-diam misalnya menavigasi ke tampilan tertentu atau me-refresh beberapa data daripada menampilkan pemberitahuan dalam kasus ini.

Mengonfigurasi proyek Android asli untuk pemberitahuan push

Menambahkan file JSON Google Services

  1. Kontrol + Klik folder android , lalu pilih Buka di Android Studio. Kemudian, beralihlah ke tampilan Proyek (jika belum).

  2. Temukan file google-services.json yang Anda unduh sebelumnya saat menyiapkan proyek PushDemo di Firebase Console. Kemudian, seret ke direktori akar modul aplikasi (aplikasiandroid android>>).

Mengonfigurasi pengaturan dan izin build

  1. Alihkan tampilan Project ke Android.

  2. Buka AndroidManifest.xml, lalu tambahkan izin INTERNET dan READ_PHONE_STATE setelah elemen aplikasi sebelum tag penutup .

    <manifest>
        <application>...</application>
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    </manifest>
    

Menambahkan Firebase SDK

  1. Di Android Studio, buka file build.gradle tingkat proyek (Gradle Scripts>build.gradle (Project: android)). dan pastikan Anda memiliki classpath 'com.google.gms:google-services' di simpul buildscript>dependensi .

    buildscript {
    
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
      }
    
      dependencies {
        // ...
    
        // Add the following line:
        classpath 'com.google.gms:google-services:4.3.3'  // Google Services plugin
      }
    }
    
    allprojects {
      // ...
    
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
        // ...
      }
    }
    

    Catatan

    Pastikan Anda mereferensikan versi terbaru sesuai instruksi yang disediakan di Firebase Console saat Membuat Proyek Android.

  2. Dalam file build.gradle tingkat aplikasi (Gradle Scripts>build.gradle (Module: app)), terapkan plugin Google Services Gradle. Terapkan plugin tepat di atas simpul android .

    // ...
    
    // Add the following line:
    apply plugin: 'com.google.gms.google-services'  // Google Services plugin
    
    android {
      // ...
    }
    
  3. Dalam file yang sama, di simpul dependensi , tambahkan dependensi untuk pustaka Android Cloud Messaging .

    dependencies {
        // ...
        implementation 'com.google.firebase:firebase-messaging:20.2.0'
    }
    

    Catatan

    Pastikan Anda mereferensikan versi terbaru sesuai dokumentasi klien Cloud Messaging Android.

  4. Simpan perubahan, lalu klik tombol Sinkronkan Sekarang (dari prompt toolbar) atau Sinkronkan Project dengan File Gradle.

Menangani pemberitahuan push untuk Android

  1. Di Android Studio, Klik Pada + folder paket com.your_organization.pushdemo<> (app>src>main>kotlin), pilih Paket dari menu Baru. Masukkan layanan sebagai nama, lalu tekan Return.

  2. Kontrol + Klik folder layanan , pilih File/Kelas Kotlin dari menu Baru . Masukkan DeviceInstallationService sebagai nama, lalu tekan Return.

  3. Terapkan DeviceInstallationService menggunakan kode berikut.

    package com.<your_organization>.pushdemo.services
    
    import android.annotation.SuppressLint
    import android.content.Context
    import android.provider.Settings.Secure
    import com.google.android.gms.common.ConnectionResult
    import com.google.android.gms.common.GoogleApiAvailability
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodCall
    import io.flutter.plugin.common.MethodChannel
    
    @SuppressLint("HardwareIds")
    class DeviceInstallationService {
    
        companion object {
            const val DEVICE_INSTALLATION_CHANNEL = "com.<your_organization>.pushdemo/deviceinstallation"
            const val GET_DEVICE_ID = "getDeviceId"
            const val GET_DEVICE_TOKEN = "getDeviceToken"
            const val GET_DEVICE_PLATFORM = "getDevicePlatform"
        }
    
        private var context: Context
        private var deviceInstallationChannel : MethodChannel
    
        val playServicesAvailable
            get() = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS
    
        constructor(context: Context, flutterEngine: FlutterEngine) {
            this.context = context
            deviceInstallationChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, DEVICE_INSTALLATION_CHANNEL)
            deviceInstallationChannel.setMethodCallHandler { call, result -> handleDeviceInstallationCall(call, result) }
        }
    
        fun getDeviceId() : String
            = Secure.getString(context.applicationContext.contentResolver, Secure.ANDROID_ID)
    
        fun getDeviceToken() : String {
            if(!playServicesAvailable) {
                throw Exception(getPlayServicesError())
            }
    
            // TODO: Revisit once we have created the PushNotificationsFirebaseMessagingService
            val token = "Placeholder_Get_Value_From_FirebaseMessagingService_Implementation"
    
            if (token.isNullOrBlank()) {
                throw Exception("Unable to resolve token for FCM.")
            }
    
            return token
        }
    
        fun getDevicePlatform() : String = "fcm"
    
        private fun handleDeviceInstallationCall(call: MethodCall, result: MethodChannel.Result) {
            when (call.method) {
                GET_DEVICE_ID -> {
                    result.success(getDeviceId())
                }
                GET_DEVICE_TOKEN -> {
                    getDeviceToken(result)
                }
                GET_DEVICE_PLATFORM -> {
                    result.success(getDevicePlatform())
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    
        private fun getDeviceToken(result: MethodChannel.Result) {
            try {
                val token = getDeviceToken()
                result.success(token)
            }
            catch (e: Exception) {
                result.error("ERROR", e.message, e)
            }
        }
    
        private fun getPlayServicesError(): String {
            val resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
    
            if (resultCode != ConnectionResult.SUCCESS) {
                return if (GoogleApiAvailability.getInstance().isUserResolvableError(resultCode)){
                    GoogleApiAvailability.getInstance().getErrorString(resultCode)
                } else {
                    "This device is not supported"
                }
            }
    
            return "An error occurred preventing the use of push notifications"
        }
    }
    

    Catatan

    Kelas ini mengimplementasikan mitra khusus platform untuk com.<your_organization>.pushdemo/deviceinstallation saluran. Ini didefinisikan dalam bagian Flutter dari aplikasi dalam DeviceInstallationService.dart. Dalam hal ini, panggilan dilakukan dari kode umum ke host asli. Pastikan untuk mengganti <your_organization> dengan organisasi Anda sendiri di mana pun ini digunakan.

    Kelas ini menyediakan ID unik (menggunakan Secure.AndroidId) sebagai bagian dari payload pendaftaran hub pemberitahuan.

  4. Tambahkan File/Kelas Kotlin lain ke folder layanan yang disebut NotificationRegistrationService, lalu tambahkan kode berikut.

    package com.<your_organization>.pushdemo.services
    
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodChannel
    
    class NotificationRegistrationService {
    
        companion object {
            const val NOTIFICATION_REGISTRATION_CHANNEL = "com.<your_organization>.pushdemo/notificationregistration"
            const val REFRESH_REGISTRATION = "refreshRegistration"
        }
    
        private var notificationRegistrationChannel : MethodChannel
    
        constructor(flutterEngine: FlutterEngine) {
            notificationRegistrationChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, NotificationRegistrationService.NOTIFICATION_REGISTRATION_CHANNEL)
        }
    
        fun refreshRegistration() {
            notificationRegistrationChannel.invokeMethod(REFRESH_REGISTRATION, null)
        }
    }
    

    Catatan

    Kelas ini mengimplementasikan mitra khusus platform untuk com.<your_organization>.pushdemo/notificationregistration saluran. Ini didefinisikan dalam bagian Flutter aplikasi dalam NotificationRegistrationService.dart. Dalam hal ini, panggilan dilakukan dari host asli ke kode umum. Sekali lagi, berhati-hatilah untuk mengganti <your_organization> dengan organisasi Anda sendiri di mana pun ini digunakan.

  5. Tambahkan File/Kelas Kotlin lain ke folder layanan yang disebut NotificationActionService, lalu tambahkan kode berikut.

    package com.<your_organization>.pushdemo.services
    
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodCall
    import io.flutter.plugin.common.MethodChannel
    
    class NotificationActionService {
        companion object {
            const val NOTIFICATION_ACTION_CHANNEL = "com.<your_organization>.pushdemo/notificationaction"
            const val TRIGGER_ACTION = "triggerAction"
            const val GET_LAUNCH_ACTION = "getLaunchAction"
        }
    
        private var notificationActionChannel : MethodChannel
        var launchAction : String? = null
    
        constructor(flutterEngine: FlutterEngine) {
            notificationActionChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, NotificationActionService.NOTIFICATION_ACTION_CHANNEL)
            notificationActionChannel.setMethodCallHandler { call, result -> handleNotificationActionCall(call, result) }
        }
    
        fun triggerAction(action: String) {
            notificationActionChannel.invokeMethod(NotificationActionService.TRIGGER_ACTION, action)
        }
    
        private fun handleNotificationActionCall(call: MethodCall, result: MethodChannel.Result) {
            when (call.method) {
                NotificationActionService.GET_LAUNCH_ACTION -> {
                    result.success(launchAction)
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    }
    

    Catatan

    Kelas ini mengimplementasikan mitra khusus platform untuk com.<your_organization>.pushdemo/notificationaction saluran. Itu didefinisikan dalam bagian Flutter aplikasi dalam NotificationActionService.dart. Panggilan dapat dilakukan di kedua arah dalam kasus ini. Pastikan untuk mengganti <your_organization> dengan organisasi Anda sendiri di mana pun ini digunakan.

  6. Tambahkan File/Kelas Kotlin baru ke paket com.your_organization.pushdemo<> yang disebut PushNotificationsFirebaseMessagingService, lalu terapkan menggunakan kode berikut.

    package com.<your_organization>.pushdemo
    
    import android.os.Handler
    import android.os.Looper
    import com.google.firebase.messaging.FirebaseMessagingService
    import com.google.firebase.messaging.RemoteMessage
    import com.<your_organization>.pushdemo.services.NotificationActionService
    import com.<your_organization>.pushdemo.services.NotificationRegistrationService
    
    class PushNotificationsFirebaseMessagingService : FirebaseMessagingService() {
    
        companion object {
            var token : String? = null
            var notificationRegistrationService : NotificationRegistrationService? = null
            var notificationActionService : NotificationActionService? = null
        }
    
        override fun onNewToken(token: String) {
            PushNotificationsFirebaseMessagingService.token = token
            notificationRegistrationService?.refreshRegistration()
        }
    
        override fun onMessageReceived(message: RemoteMessage) {
            message.data.let {
                Handler(Looper.getMainLooper()).post {
                    notificationActionService?.triggerAction(it.getOrDefault("action", null))
                }
            }
        }
    }
    

    Catatan

    Kelas ini bertanggung jawab untuk menangani pemberitahuan saat aplikasi berjalan di latar depan. Ini akan secara kondisional memanggil triggerAction pada NotificationActionService jika tindakan disertakan dalam payload pemberitahuan yang diterima di onMessageReceived. Ini juga akan memanggil refreshRegistration pada NotificationRegistrationService ketika token Firebase diregenerasi dengan menimpa fungsi onNewToken .

    Sekali lagi, berhati-hatilah untuk mengganti <your_organization> dengan organisasi Anda sendiri di mana pun digunakan.

  7. Di AndroidManifest.xml (app>src>main), tambahkan PushNotificationsFirebaseMessagingService ke bagian bawah elemen aplikasi dengan com.google.firebase.MESSAGING_EVENT filter niat.

    <manifest>
        <application>
            <!-- EXISTING MANIFEST CONTENT -->
             <service
                android:name="com.<your_organization>.pushdemo.PushNotificationsFirebaseMessagingService"
                android:exported="false">
                <intent-filter>
                    <action android:name="com.google.firebase.MESSAGING_EVENT" />
                </intent-filter>
            </service>
        </application>
    </manifest>
    
  8. Kembali ke DeviceInstallationService, pastikan impor berikut ada di bagian atas file.

    package com.<your_organization>.pushdemo
    import com.<your_organization>.pushdemo.services.PushNotificationsFirebaseMessagingService
    

    Catatan

    Ganti <your_organization> dengan nilai organisasi Anda sendiri.

  9. Perbarui teks tempat penampung Placeholder_Get_Value_From_FirebaseMessagingService_Implementation untuk mendapatkan nilai token dari PushNotificationFirebaseMessagingService.

    fun getDeviceToken() : String {
        if(!playServicesAvailable) {
            throw Exception(getPlayServicesError())
        }
    
        // Get token from the PushNotificationsFirebaseMessagingService.token field.
        val token = PushNotificationsFirebaseMessagingService.token
    
        if (token.isNullOrBlank()) {
            throw Exception("Unable to resolve token for FCM.")
        }
    
        return token
    }
    
  10. Di MainActivity, pastikan impor berikut ada di bagian atas file.

    package com.<your_organization>.pushdemo
    
    import android.content.Intent
    import android.os.Bundle
    import com.google.android.gms.tasks.OnCompleteListener
    import com.google.firebase.iid.FirebaseInstanceId
    import com.<your_organization>.pushdemo.services.DeviceInstallationService
    import com.<your_organization>.pushdemo.services.NotificationActionService
    import com.<your_organization>.pushdemo.services.NotificationRegistrationService
    import io.flutter.embedding.android.FlutterActivity
    

    Catatan

    Ganti <your_organization> dengan nilai organisasi Anda sendiri.

  11. Tambahkan variabel untuk menyimpan referensi ke DeviceInstallationService.

    private lateinit var deviceInstallationService: DeviceInstallationService
    
  12. Tambahkan fungsi yang disebut processNotificationActions untuk memeriksa apakah Niat memiliki nilai tambahan bernama tindakan. Secara kondisional memicu tindakan tersebut atau menyimpannya untuk digunakan nanti jika tindakan sedang diproses selama peluncuran aplikasi.

     private fun processNotificationActions(intent: Intent, launchAction: Boolean = false) {
        if (intent.hasExtra("action")) {
            var action = intent.getStringExtra("action");
    
            if (action.isNotEmpty()) {
                if (launchAction) {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.launchAction = action
                }
                else {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.triggerAction(action)
                }
            }
        }
    }
    
  13. Ambil alih fungsi onNewIntent untuk memanggil processNotificationActions.

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        processNotificationActions(intent)
    }
    

    Catatan

    Karena LaunchMode untuk MainActivity diatur ke SingleTop, Niat akan dikirim ke instans Aktivitas yang ada melalui fungsi onNewIntent daripada fungsi onCreate sehingga Anda harus menangani Niat masuk dalam fungsi onCreate dan onNewIntent .

  14. Ambil alih fungsi onCreate , atur deviceInstallationService ke instans baru DeviceInstallationService.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        flutterEngine?.let {
            deviceInstallationService = DeviceInstallationService(context, it)
        }
    }
    
  15. Atur properti notificationActionService dan notificationRegistrationService di PushNotificationFirebaseMessagingServices.

    flutterEngine?.let {
      deviceInstallationService = DeviceInstallationService(context, it)
      PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it)
      PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it)
    }
    
  16. Dalam fungsi yang sama, panggil FirebaseInstanceId.getInstance().instanceId secara kondisional. Terapkan OnCompleteListener untuk mengatur nilai token yang dihasilkan pada PushNotificationFirebaseMessagingService sebelum memanggil refreshRegistration.

    if(deviceInstallationService?.playServicesAvailable) {
        FirebaseInstanceId.getInstance().instanceId
            .addOnCompleteListener(OnCompleteListener { task ->
                if (!task.isSuccessful)
                    return@OnCompleteListener
    
                PushNotificationsFirebaseMessagingService.token = task.result?.token
                PushNotificationsFirebaseMessagingService.notificationRegistrationService?.refreshRegistration()
            })
    }
    
  17. Masih dalam onCreate, panggil processNotificationActions di akhir fungsi. Gunakan true untuk argumen launchAction untuk menunjukkan tindakan ini sedang diproses selama peluncuran aplikasi.

    processNotificationActions(this.intent, true)
    

Catatan

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

Mengonfigurasi proyek iOS asli untuk pemberitahuan push

Mengonfigurasi target runner dan Info.plist

  1. Di Visual Studio Code, Kontrol + Klik folder ios, lalu pilih Buka di Xcode.

  2. Di Xcode, klik Runner ( xcodeproj di bagian atas, bukan folder) lalu pilih target Runner , lalu Signing & Capabilities. Dengan konfigurasi Semua build dipilih, pilih akun Pengembang Anda untuk Tim. Pastikan opsi "Kelola penandatanganan secara otomatis" dicentang dan Sertifikat Penandatanganan dan Profil Provisi Anda dipilih secara otomatis.

    Catatan

    Jika Anda tidak melihat nilai Profil Provisi baru, coba refresh profil untuk Identitas Penandatanganan dengan memilihAkunPreferensi>Xcode>, lalu pilih tombol Unduh Profil Manual untuk mengunduh profil.

  3. Klik + Kemampuan, lalu cari Pemberitahuan Push. Klik Dua Kalipada Pemberitahuan Push untuk menambahkan kemampuan ini.

  4. Buka Info.plist dan atur Versi sistem minimum ke 13.0.

    Catatan

    Hanya perangkat yang menjalankan iOS 13.0 ke atas yang didukung untuk tujuan tutorial ini namun Anda dapat memperluasnya untuk mendukung perangkat yang menjalankan versi yang lebih lama.

  5. Buka Runner.entitlements dan pastikan pengaturan Lingkungan APS diatur ke pengembangan.

Menangani pemberitahuan push untuk iOS

  1. Kontrol + Klik folder Runner (dalam proyek Runner), lalu pilih Grup Baru menggunakan Layanan sebagai nama.

  2. Kontrol + Klik folder Layanan , lalu pilih File Baru.... Lalu, pilih File Swift dan klik Berikutnya. Tentukan DeviceInstallationService untuk nama tersebut lalu klik Buat.

  3. Terapkan DeviceInstallationService.swift menggunakan kode berikut.

    import Foundation
    
    class DeviceInstallationService {
    
        enum DeviceRegistrationError: Error {
            case notificationSupport(message: String)
        }
    
        var token : Data? = nil
    
        let DEVICE_INSTALLATION_CHANNEL = "com.<your_organization>.pushdemo/deviceinstallation"
        let GET_DEVICE_ID = "getDeviceId"
        let GET_DEVICE_TOKEN = "getDeviceToken"
        let GET_DEVICE_PLATFORM = "getDevicePlatform"
    
        private let deviceInstallationChannel : FlutterMethodChannel
    
        var notificationsSupported : Bool {
            get {
                if #available(iOS 13.0, *) {
                    return true
                }
                else {
                    return false
                }
            }
        }
    
        init(withBinaryMessenger binaryMessenger : FlutterBinaryMessenger) {
            deviceInstallationChannel = FlutterMethodChannel(name: DEVICE_INSTALLATION_CHANNEL, binaryMessenger: binaryMessenger)
            deviceInstallationChannel.setMethodCallHandler(handleDeviceInstallationCall)
        }
    
        func getDeviceId() -> String {
            return UIDevice.current.identifierForVendor!.description
        }
    
        func getDeviceToken() throws -> String {
            if(!notificationsSupported) {
                let notificationSupportError = getNotificationsSupportError()
                throw DeviceRegistrationError.notificationSupport(message: notificationSupportError)
            }
    
            if (token == nil) {
                throw DeviceRegistrationError.notificationSupport(message: "Unable to resolve token for APNS.")
            }
    
            return token!.reduce("", {$0 + String(format: "%02X", $1)})
        }
    
        func getDevicePlatform() -> String {
            return "apns"
        }
    
        private func handleDeviceInstallationCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
            switch call.method {
            case GET_DEVICE_ID:
                result(getDeviceId())
            case GET_DEVICE_TOKEN:
                getDeviceToken(result: result)
            case GET_DEVICE_PLATFORM:
                result(getDevicePlatform())
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    
        private func getDeviceToken(result: @escaping FlutterResult) {
            do {
                let token = try getDeviceToken()
                result(token)
            }
            catch let error {
                result(FlutterError(code: "UNAVAILABLE", message: error.localizedDescription, details: nil))
            }
        }
    
        private func getNotificationsSupportError() -> String {
    
            if (!notificationsSupported) {
                return "This app only supports notifications on iOS 13.0 and above. You are running \(UIDevice.current.systemVersion)"
            }
    
            return "An error occurred preventing the use of push notifications."
        }
    }
    

    Catatan

    Kelas ini mengimplementasikan mitra khusus platform untuk com.<your_organization>.pushdemo/deviceinstallation saluran. Ini didefinisikan dalam bagian Flutter dari aplikasi dalam DeviceInstallationService.dart. Dalam hal ini, panggilan dilakukan dari kode umum ke host asli. Pastikan untuk mengganti <your_organization> dengan organisasi Anda sendiri di mana pun ini digunakan.

    Kelas ini menyediakan ID unik (menggunakan nilai UIDevice.identifierForVendor ) sebagai bagian dari payload pendaftaran hub pemberitahuan.

  4. Tambahkan File Swift lain ke folder Layanan yang disebut NotificationRegistrationService, lalu tambahkan kode berikut.

    import Foundation
    
    class NotificationRegistrationService {
    
        let NOTIFICATION_REGISTRATION_CHANNEL = "com.<your_organization>.pushdemo/notificationregistration"
        let REFRESH_REGISTRATION = "refreshRegistration"
    
        private let notificationRegistrationChannel : FlutterMethodChannel
    
        init(withBinaryMessenger binaryMessenger : FlutterBinaryMessenger) {
           notificationRegistrationChannel = FlutterMethodChannel(name: NOTIFICATION_REGISTRATION_CHANNEL, binaryMessenger: binaryMessenger)
        }
    
        func refreshRegistration() {
            notificationRegistrationChannel.invokeMethod(REFRESH_REGISTRATION, arguments: nil)
        }
    }
    

    Catatan

    Kelas ini mengimplementasikan mitra khusus platform untuk com.<your_organization>.pushdemo/notificationregistration saluran. Ini didefinisikan dalam bagian Flutter aplikasi dalam NotificationRegistrationService.dart. Dalam hal ini, panggilan dilakukan dari host asli ke kode umum. Sekali lagi, berhati-hatilah untuk mengganti <your_organization> dengan organisasi Anda sendiri di mana pun ini digunakan.

  5. Tambahkan File Swift lain ke folder Layanan yang disebut NotificationActionService, lalu tambahkan kode berikut.

    import Foundation
    
    class NotificationActionService {
    
        let NOTIFICATION_ACTION_CHANNEL = "com.<your_organization>.pushdemo/notificationaction"
        let TRIGGER_ACTION = "triggerAction"
        let GET_LAUNCH_ACTION = "getLaunchAction"
    
        private let notificationActionChannel: FlutterMethodChannel
    
        var launchAction: String? = nil
    
        init(withBinaryMessenger binaryMessenger: FlutterBinaryMessenger) {
            notificationActionChannel = FlutterMethodChannel(name: NOTIFICATION_ACTION_CHANNEL, binaryMessenger: binaryMessenger)
            notificationActionChannel.setMethodCallHandler(handleNotificationActionCall)
        }
    
        func triggerAction(action: String) {
           notificationActionChannel.invokeMethod(TRIGGER_ACTION, arguments: action)
        }
    
        private func handleNotificationActionCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
            switch call.method {
            case GET_LAUNCH_ACTION:
                result(launchAction)
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    }
    

    Catatan

    Kelas ini mengimplementasikan mitra khusus platform untuk com.<your_organization>.pushdemo/notificationaction saluran. Itu didefinisikan dalam bagian Flutter aplikasi dalam NotificationActionService.dart. Panggilan dapat dilakukan di kedua arah dalam kasus ini. Pastikan untuk mengganti <your_organization> dengan organisasi Anda sendiri di mana pun ini digunakan.

  6. Di AppDelegate.swift, tambahkan variabel untuk menyimpan referensi ke layanan yang Anda buat sebelumnya.

    var deviceInstallationService : DeviceInstallationService?
    var notificationRegistrationService : NotificationRegistrationService?
    var notificationActionService : NotificationActionService?
    
  7. Tambahkan fungsi yang disebut processNotificationActions untuk memproses data pemberitahuan. Secara kondisional memicu tindakan tersebut atau menyimpannya untuk digunakan nanti jika tindakan sedang diproses selama peluncuran aplikasi.

    func processNotificationActions(userInfo: [AnyHashable : Any], launchAction: Bool = false) {
        if let action = userInfo["action"] as? String {
            if (launchAction) {
                notificationActionService?.launchAction = action
            }
            else {
                notificationActionService?.triggerAction(action: action)
            }
        }
    }
    
  8. Ambil alih fungsi didRegisterForRemoteNotificationsWithDeviceToken yang mengatur nilai token untuk DeviceInstallationService. Kemudian, panggil refreshRegistration pada NotificationRegistrationService.

    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
      deviceInstallationService?.token = deviceToken
      notificationRegistrationService?.refreshRegistration()
    }
    
  9. Ambil alih fungsi didReceiveRemoteNotification yang meneruskan argumen userInfo ke fungsi processNotificationActions .

    override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        processNotificationActions(userInfo: userInfo)
    }
    
  10. Ambil alih fungsi didFailToRegisterForRemoteNotificationsWithError untuk mencatat kesalahan.

    override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print(error);
    }
    

    Catatan

    Ini tempat penampung yang sangat banyak. Anda akan ingin menerapkan pencatatan dan penanganan kesalahan yang tepat untuk skenario produksi.

  11. Dalam didFinishLaunchingWithOptions, buat instans variabel deviceInstallationService, notificationRegistrationService, dan notificationActionService .

    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    
    deviceInstallationService = DeviceInstallationService(withBinaryMessenger: controller.binaryMessenger)
    notificationRegistrationService = NotificationRegistrationService(withBinaryMessenger: controller.binaryMessenger)
    notificationActionService = NotificationActionService(withBinaryMessenger: controller.binaryMessenger)
    
  12. Dalam fungsi yang sama, minta otorisasi secara kondisional dan daftar untuk pemberitahuan jarak jauh.

    if #available(iOS 13.0, *) {
      UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
          (granted, error) in
    
          if (granted)
          {
              DispatchQueue.main.async {
                  let pushSettings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
                  application.registerUserNotificationSettings(pushSettings)
                  application.registerForRemoteNotifications()
              }
          }
      }
    }
    
  13. Jika launchOptions berisi kunci remoteNotification , panggil processNotificationActions di akhir fungsi didFinishLaunchingWithOptions . Berikan objek userInfo yang dihasilkan dan gunakan true untuk argumen launchAction . Nilai benar menunjukkan bahwa tindakan sedang diproses selama peluncuran aplikasi.

    if let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable : Any] {
        processNotificationActions(userInfo: userInfo, launchAction: true)
    }
    

Menguji solusi

Anda sekarang dapat menguji pengiriman pemberitahuan melalui layanan backend.

Mengirim pemberitahuan pengujian

  1. Buka tab baru di Postman.

  2. Atur permintaan ke POST, dan masukkan alamat berikut:

    https://<app_name>.azurewebsites.net/api/notifications/requests
    
  3. Jika Anda memilih untuk menyelesaikan bagian Autentikasi klien menggunakan Kunci API , pastikan untuk mengonfigurasi header permintaan untuk menyertakan nilai apikey Anda.

    Kunci Nilai
    apikey <your_api_key>
  4. Pilih opsi mentah untuk Isi, lalu pilih JSON dari daftar opsi format, lalu sertakan beberapa konten JSON tempat penampung:

    {
        "text": "Message from Postman!",
        "action": "action_a"
    }
    
  5. Pilih tombol Kode , yang berada di bawah tombol Simpan di kanan atas jendela. Permintaan akan terlihat mirip dengan contoh berikut saat ditampilkan untuk HTML (tergantung pada apakah Anda menyertakan header apikey ):

    POST /api/notifications/requests HTTP/1.1
    Host: https://<app_name>.azurewebsites.net
    apikey: <your_api_key>
    Content-Type: application/json
    
    {
        "text": "Message from backend service",
        "action": "action_a"
    }
    
  6. Jalankan aplikasi PushDemo pada salah satu atau kedua platform target (Android dan iOS).

    Catatan

    Jika Anda menguji di Android , pastikan Anda tidak berjalan di Debug, atau jika aplikasi telah disebarkan dengan menjalankan aplikasi, tutup paksa aplikasi dan mulai lagi dari peluncur.

  7. Di aplikasi PushDemo , ketuk tombol Daftar .

  8. Kembali ke Postman, tutup jendela Hasilkan Cuplikan Kode (jika Anda belum melakukannya) lalu klik tombol Kirim .

  9. Validasi bahwa Anda mendapatkan respons 200 OK di Postman dan pemberitahuan muncul di aplikasi yang menampilkan tindakan ActionA yang diterima.

  10. Tutup aplikasi PushDemo , lalu klik tombol Kirim lagi di Postman.

  11. Validasi bahwa Anda mendapatkan respons 200 OK di Postman lagi. Validasi bahwa pemberitahuan muncul di area pemberitahuan untuk aplikasi PushDemo dengan pesan yang benar.

  12. Ketuk pemberitahuan untuk mengonfirmasi bahwa pemberitahuan membuka aplikasi dan menampilkan pemberitahuan tindakan ActionA yang diterima .

  13. Kembali ke Postman, ubah isi permintaan sebelumnya untuk mengirim pemberitahuan senyap yang menentukan action_b alih-alih action_a untuk nilai tindakan .

    {
        "action": "action_b",
        "silent": true
    }
    
  14. Dengan aplikasi masih terbuka, klik tombol Kirim di Postman.

  15. Validasi bahwa Anda mendapatkan respons 200 OK di Postman dan pemberitahuan muncul di aplikasi yang menampilkan tindakan ActionB yang diterima alih-alih tindakan ActionA diterima.

  16. Tutup aplikasi PushDemo , lalu klik tombol Kirim lagi di Postman.

  17. Validasi bahwa Anda mendapatkan respons 200 OK di Postman dan pemberitahuan senyap tidak muncul di area pemberitahuan.

Pemecahan masalah

Tidak ada respons dari layanan backend

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

Jika pengujian terhadap Aplikasi Azure API, periksa apakah layanan sedang berjalan dan telah disebarkan dan telah dimulai tanpa kesalahan.

Pastikan untuk memeriksa bahwa Anda telah menentukan alamat dasar dengan benar di Postman atau di konfigurasi aplikasi seluler saat menguji melalui klien. Alamat dasar harus secara indikatif menjadi https://<api_name>.azurewebsites.net/ atau https://localhost:5001/ saat pengujian secara lokal.

Tidak menerima pemberitahuan di Android setelah memulai atau menghentikan sesi debug

Pastikan Anda mendaftar lagi setelah memulai atau menghentikan sesi debug. Debugger akan menyebabkan token Firebase baru dibuat. Penginstalan hub pemberitahuan juga harus diperbarui.

Menerima kode status 401 dari layanan backend

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

Jika Anda menerima kesalahan ini saat menguji secara lokal, pastikan nilai kunci yang Anda tentukan dalam konfigurasi klien, cocok dengan nilai pengaturan pengguna Authentication:ApiKey yang digunakan oleh API.

Jika Anda menguji dengan Aplikasi API, pastikan nilai kunci dalam file konfigurasi klien cocok dengan pengaturan aplikasi Authentication:ApiKey yang Anda gunakan di Aplikasi API.

Catatan

Jika Anda telah membuat atau mengubah pengaturan ini setelah Anda menyebarkan layanan backend, maka Anda harus memulai ulang layanan agar berlaku.

Jika Anda memilih untuk tidak menyelesaikan bagian Autentikasi klien menggunakan Kunci API , pastikan Anda tidak menerapkan atribut Otorisasi ke kelas NotificationsController .

Menerima kode status 404 dari layanan backend

Validasi bahwa titik akhir dan metode permintaan HTTP sudah benar. Misalnya, titik akhir harus secara indikatif:

  • [PUT]https://<api_name>.azurewebsites.net/api/notifications/installations
  • [HAPUS]https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • [POST]https://<api_name>.azurewebsites.net/api/notifications/requests

Atau saat menguji secara lokal:

  • [PUT]https://localhost:5001/api/notifications/installations
  • [HAPUS]https://localhost:5001/api/notifications/installations/<installation_id>
  • [POST]https://localhost:5001/api/notifications/requests

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

Tidak dapat mendaftar dan pesan kesalahan hub pemberitahuan ditampilkan

Verifikasi bahwa perangkat pengujian memiliki konektivitas jaringan. Kemudian, tentukan kode status respons Http dengan mengatur titik henti untuk memeriksa nilai properti StatusCode di HttpResponse.

Tinjau saran pemecahan masalah sebelumnya jika berlaku berdasarkan kode status.

Atur titik henti pada baris yang mengembalikan kode status khusus ini untuk API masing-masing. Kemudian coba panggil layanan backend saat men-debug secara lokal.

Validasi layanan backend berfungsi seperti yang diharapkan melalui Postman menggunakan payload yang sesuai. Gunakan payload aktual yang dibuat oleh kode klien untuk platform yang dimaksud.

Tinjau bagian konfigurasi khusus platform untuk memastikan bahwa tidak ada langkah yang terlewatkan. Periksa apakah nilai yang sesuai sedang diselesaikan untuk installation id variabel dan token untuk platform yang sesuai.

Tidak dapat mengatasi ID untuk pesan kesalahan perangkat ditampilkan

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

Langkah berikutnya

Anda sekarang harus memiliki aplikasi Flutter dasar yang terhubung ke hub pemberitahuan melalui layanan backend dan dapat mengirim dan menerima pemberitahuan.

Anda mungkin perlu menyesuaikan contoh yang digunakan dalam tutorial ini agar sesuai dengan skenario Anda sendiri. Menerapkan penanganan kesalahan yang lebih kuat, logika coba lagi, dan pengelogan juga disarankan.

Visual Studio App Center dapat dengan cepat dimasukkan ke dalam aplikasi seluler yang menyediakan analitik dan diagnostik untuk membantu dalam pemecahan masalah.