Kurz: Odesílání nabízených oznámení do aplikací Xamarin.Forms pomocí Azure Notification Hubs prostřednictvím back-endové služby

Stáhnout ukázku Stažení ukázky

V tomto kurzu použijete Azure Notification Hubs k zasílání nabízených oznámení do aplikace Xamarin.Forms , která cílí na Android a iOS.

Back-end ASP.NET Core webového rozhraní API se používá ke zpracování registrace zařízení pro klienta pomocí nejnovějšího a nejlepšího přístupu k instalaci. Služba bude také odesílat nabízená oznámení prostřednictvím různých platforem.

Tyto operace se zpracovávají pomocí sady Notification Hubs SDK pro back-endové operace. Další podrobnosti o celkovém přístupu najdete v dokumentaci k registraci z back-endu aplikace .

Tento kurz vás provede následujícími kroky:

Požadavky

Pokud chcete postup sledovat, potřebujete:

  • Předplatné Azure, ve kterém můžete vytvářet a spravovat prostředky.
  • Mac s nainstalovanou Visual Studio pro Mac nebo POČÍTAČ se sadou Visual Studio 2019.
  • Uživatelé sady Visual Studio 2019 musí mít také nainstalované úlohy vývoje mobilních aplikací s rozhraním .NET a ASP.NET a vývoj pro web.
  • Možnost spustit aplikaci na Androidu (fyzická zařízení nebo zařízení emulátoru) nebo iOS (pouze fyzická zařízení).

Pro Android musíte mít:

  • Odemčené fyzické zařízení nebo emulátor (se spuštěným rozhraním API 26 a novějším a nainstalovanými službami Google Play)

Pro iOS musíte mít:

Poznámka

Simulátor iOS nepodporuje vzdálená oznámení, a proto se při zkoumání této ukázky v iOSu vyžaduje fyzické zařízení. K dokončení tohoto kurzu ale nemusíte aplikaci spouštět na Androidu i v iOSu .

Můžete postupovat podle kroků v tomto příkladu s prvními principy bez předchozích zkušeností. Výhodou ale bude znalost následujících aspektů.

Důležité

Uvedené kroky jsou specifické pro Visual Studio pro Mac. Postup je možné sledovat pomocí sady Visual Studio 2019 , ale může existovat několik rozdílů, které je potřeba sladit. Například popis uživatelského rozhraní a pracovních postupů, názvy šablon, konfigurace prostředí atd.

Nastavení služeb nabízených oznámení a Centra oznámení Azure

V této části nastavíte službu Firebase Cloud Messaging (FCM) a službu Apple Push Notification Services (APNS). Pak vytvoříte a nakonfigurujete centrum oznámení pro práci s těmito službami.

Vytvoření projektu Firebase a povolení služby Firebase Cloud Messaging pro Android

  1. Přihlaste se ke konzole Firebase. Vytvořte nový projekt Firebase a jako název projektu zadejte PushDemo.

    Poznámka

    Vygeneruje se vám jedinečný název. Ve výchozím nastavení se skládá z malé varianty zadaného názvu a vygenerovaného čísla odděleného pomlčkou. Pokud chcete, můžete ho změnit za předpokladu, že je stále globálně jedinečný.

  2. Po vytvoření projektu vyberte Přidat Firebase do aplikace pro Android.

    Přidání Firebase do aplikace pro Android

  3. Na stránce Add Firebase to your Android app (Přidat Firebase do aplikace pro Android) proveďte následující kroky.

    1. Jako název balíčku pro Android zadejte název balíčku. Příklad: com.<organization_identifier>.<package_name>.

      Zadejte název balíčku.

    2. Vyberte Zaregistrovat aplikaci.

    3. Vyberte Stáhnout google-services.json. Pak soubor uložte do místní složky pro pozdější použití a vyberte Další.

      Stáhnout google-services.json

    4. Vyberte Další.

    5. Vyberte Pokračovat do konzoly.

      Poznámka

      Pokud tlačítko Pokračovat do konzoly není povolené z důvodu kontroly ověření instalace , zvolte Přeskočit tento krok.

  4. V konzole Firebase vyberte ozubené kolo pro váš projekt. Pak vyberte Nastavení projektu.

    Vyberte Nastavení projektu.

    Poznámka

    Pokud jste si soubor google-services.json nestáhli, můžete si ho stáhnout na této stránce.

  5. Přepněte na kartu Cloud Messaging v horní části. Zkopírujte a uložte klíč serveru pro pozdější použití. Tuto hodnotu použijete ke konfiguraci centra oznámení.

    Kopírování klíče serveru

Registrace aplikace pro iOS pro nabízená oznámení

Pokud chcete odesílat nabízená oznámení do aplikace pro iOS, zaregistrujte aplikaci u společnosti Apple a také zaregistrujte nabízená oznámení.

  1. Pokud jste aplikaci ještě nezaregistrovali, přejděte na portál zřizování pro iOS v Centru pro vývojáře Apple. Přihlaste se k portálu pomocí svého Apple ID, přejděte na Certifikáty, Identifikátory & Profily a pak vyberte Identifikátory. Kliknutím + zaregistrujete novou aplikaci.

    Stránka ID aplikací portálu zřizování pro iOS

  2. Na obrazovce Register a New Identifier (Zaregistrovat nový identifikátor ) vyberte přepínač App ID (ID aplikací ). Pak vyberte Pokračovat.

    Stránka registrace nového ID na portálu pro iOS

  3. Aktualizujte pro novou aplikaci následující tři hodnoty a pak vyberte Pokračovat:

    • Popis: Zadejte popisný název aplikace.

    • ID sady prostředků: Zadejte ID sady prostředků formuláře com.organization_identifier<>.<>product_name, jak je uvedeno v Průvodci distribucí aplikací. Na následujícím snímku obrazovky mobcat se hodnota používá jako identifikátor organizace a hodnota PushDemo se používá jako název produktu.

      Stránka registrace id aplikace na portálu pro iOS

    • Nabízená oznámení: Zaškrtněte možnost Nabízená oznámení v části Schopnosti .

      Formulář pro registraci nového ID aplikace

      Tato akce vygeneruje ID aplikace a požádá o potvrzení informací. Vyberte Pokračovat a pak výběrem možnosti Zaregistrovat potvrďte nové ID aplikace.

      Potvrzení nového ID aplikace

      Po výběru možnosti Zaregistrovat se nové ID aplikace zobrazí jako řádková položka na stránce Certifikáty, Identifikátory & Profily .

  4. Na stránce Certifikáty, identifikátory & profily vyhledejte v části Identifikátory řádkovou položku ID aplikace, kterou jste vytvořili. Potom vyberte jeho řádek, aby se zobrazila obrazovka Upravit konfiguraci ID aplikace .

Vytvoření certifikátu pro Notification Hubs

Certifikát se vyžaduje k tomu, aby centrum oznámení fungovalo se službou Apple Push Notification Services (APNS), a dá se poskytnout jedním ze dvou způsobů:

  1. Vytvoření nabízeného certifikátu p12, který je možné nahrát přímo do centra oznámení (původní přístup)

  2. Vytvoření certifikátu p8, který se dá použít k ověřování na základě tokenů (novější a doporučený přístup)

Novější přístup má řadu výhod, které jsou popsané v tématu Ověřování APNS na základě tokenů (HTTP/2). Vyžaduje se méně kroků, ale je to také povinné pro konkrétní scénáře. Pro oba přístupy však byly poskytnuty kroky, protože pro účely tohoto kurzu bude fungovat jeden z těchto přístupů.

MOŽNOST 1: Vytvoření nabízeného certifikátu p12, který je možné nahrát přímo do centra oznámení
  1. Na počítači Mac spusťte nástroj Klíčenky. Můžete ho otevřít ze složky Utility nebo ze složky Jiné na hlavním panelu.

  2. Vyberte Přístup ke svazku klíčů, rozbalte Pomocník s certifikáty a pak vyberte Požádat o certifikát od certifikační autority.

    Žádost o nový certifikát pomocí klíčenky

    Poznámka

    Ve výchozím nastavení vybere přístup řetězce klíčů první položku v seznamu. To může být problém, pokud jste v kategorii Certifikáty a certifikační autorita Apple Worldwide Developer Relations Certifikační autorita není první položkou v seznamu. Před vygenerováním žádosti o podepsání certifikátu (CERTIFICATE Signing Request) se ujistěte, že máte položku, která není klíčem, nebo že je vybraný klíč certifikační autority Apple Worldwide Developer Relations .

  3. Vyberte adresu Email uživatele, zadejte hodnotu Běžný název, ujistěte se, že jste zadali Možnost Uloženo na disk, a pak vyberte Pokračovat. Adresu Email certifikační autority ponechte prázdnou, protože se nevyžaduje.

    Očekávané informace o certifikátu

  4. Zadejte název souboru žádosti o podepsání certifikátu (CSR) do pole Uložit jako, vyberte umístění v části Kde a pak vyberte Uložit.

    Zvolte název souboru pro certifikát.

    Tato akce uloží soubor CSR do vybraného umístění. Výchozí umístění je Plocha. Zapamatujte si umístění zvolené pro soubor.

  5. Vraťte se na stránku Certifikáty, identifikátory & profily na portálu pro zřizování iOS, posuňte se dolů k zaškrtnuté možnosti Nabízená oznámení a pak výběrem možnosti Konfigurovat vytvořte certifikát.

    Stránka Upravit ID aplikace

  6. Zobrazí se okno Certifikáty TLS/SSL služby Apple Push Notification . V části Vývoj certifikátu TLS/SSL vyberte tlačítko Vytvořit certifikát.

    Tlačítko Vytvořit certifikát pro ID aplikace

    Zobrazí se obrazovka Vytvořit nový certifikát .

    Poznámka

    Tento kurz používá certifikát pro vývoj. Stejný postup se používá při registraci produkčního certifikátu. Jen se ujistěte, že při odesílání oznámení používáte stejný typ certifikátu.

  7. Vyberte Zvolit soubor, přejděte do umístění, kam jste soubor CSR uložili, a potom poklikáním na název certifikátu ho načtěte. Pak vyberte Pokračovat.

  8. Jakmile portál vytvoří certifikát, vyberte tlačítko Stáhnout . Uložte certifikát a zapamatujte si umístění, do kterého je uložený.

    Stránka pro stažení vygenerovaného certifikátu

    Certifikát se stáhne a uloží do počítače ve složce Stažené soubory .

    Vyhledejte soubor certifikátu ve složce Stažené soubory.

    Poznámka

    Ve výchozím nastavení má stažený vývojový certifikát název aps_development.cer.

  9. Poklikejte na stažený certifikát push certificate aps_development.cer. Tato akce nainstaluje nový certifikát do klíčenky, jak je znázorněno na následujícím obrázku:

    Seznam přístupových certifikátů pro řetězce klíčů zobrazující nový certifikát

    Poznámka

    I když se název v certifikátu může lišit, název bude mít předponu Apple Development iOS Push Services a bude k němu přidružený příslušný identifikátor sady.

  10. V části Přístup ke klíčovněklikněte + na nový certifikát push, který jste vytvořili v kategorii Certifikáty. Vyberte Exportovat, pojmenujte soubor, vyberte formát p12 a pak vyberte Uložit.

    Export certifikátu ve formátu p12

    Certifikát můžete chránit heslem, ale heslo je volitelné. Pokud chcete obejít vytváření hesla, klikněte na OK . Poznamenejte si název souboru a umístění exportovaného certifikátu p12. Používají se k povolení ověřování pomocí služby APN.

    Poznámka

    Název a umístění vašeho souboru p12 se může lišit od toho, co je znázorněno v tomto kurzu.

MOŽNOST 2: Vytvoření certifikátu p8, který se dá použít k ověřování na základě tokenů
  1. Poznamenejte si následující podrobnosti:

    • Předpona ID aplikace (ID týmu)
    • ID sady
  2. Zpět v části Certifikáty, Identifikátory & Profily klikněte na Klíče.

    Poznámka

    Pokud už máte klíč pro APNS nakonfigurovaný, můžete znovu použít certifikát p8, který jste stáhli hned po jeho vytvoření. Pokud ano, můžete kroky 35 ignorovat.

  3. Kliknutím na + tlačítko (nebo na tlačítko Vytvořit klíč ) vytvořte nový klíč.

  4. Zadejte vhodnou hodnotu názvu klíče , pak zaškrtněte možnost Služba Apple Push Notifications (APNS) a na další obrazovce klikněte na Pokračovat a pak na Zaregistrovat .

  5. Klikněte na Stáhnout , přesuňte soubor p8 (s předponou AuthKey_) do zabezpečeného místního adresáře a klikněte na Hotovo.

    Poznámka

    Soubor p8 uchovávejte na bezpečném místě (a uložte si zálohu). Po stažení není možné klíč znovu stáhnout, protože se odebere serverová kopie.

  6. V části Klíče klikněte na klíč, který jste vytvořili (nebo na existující klíč, pokud jste se ho rozhodli použít).

  7. Poznamenejte si hodnotu ID klíče .

  8. Otevřete certifikát p8 ve vhodné aplikaci podle vašeho výběru, jako je Visual Studio Code. Poznamenejte si hodnotu klíče (mezi -----BEGIN PRIVATE KEY----- a -----END PRIVATE KEY-----).

    -----BEGIN PRIVATE KEY-----
    <key_value>
    -----END PRIVÁTNÍ KLÍČ-----

    Poznámka

    Toto je hodnota tokenu , která se později použije ke konfiguraci centra oznámení.

Na konci těchto kroků byste měli mít následující informace pro pozdější použití v části Konfigurace centra oznámení s informacemi O APNS:

  • ID týmu (viz krok 1)
  • ID sady prostředků (viz krok 1)
  • ID klíče (viz krok 7)
  • Hodnota tokenu (hodnota klíče p8 získaná v kroku 8)

Vytvoření zřizovacího profilu pro aplikaci

  1. Vraťte se na portál pro zřizování iOS, vyberte Certifikáty, identifikátory & profily, v nabídce vlevo vyberte Profily a pak výběrem vytvořte + nový profil. Zobrazí se obrazovka Zaregistrovat nový zřizovací profil .

  2. Jako typ zřizovacího profilu v části Vývoj vyberte Vývoj aplikací pro iOS a pak vyberte Pokračovat.

    Seznam zřizovacích profilů

  3. Pak v rozevíracím seznamu ID aplikace vyberte ID aplikace, které jste vytvořili, a vyberte Pokračovat.

    Vyberte ID aplikace.

  4. V okně Vybrat certifikáty vyberte certifikát pro vývoj, který používáte k podepisování kódu, a vyberte Pokračovat.

    Poznámka

    Tento certifikát není certifikátem push, který jste vytvořili v předchozím kroku. Toto je váš certifikát pro vývoj. Pokud neexistuje, musíte ho vytvořit, protože se jedná o předpoklad pro tento kurz. Certifikáty pro vývojáře je možné vytvářet na portálu Pro vývojáře Apple, prostřednictvím Xcode nebo v sadě Visual Studio.

  5. Vraťte se na stránku Certifikáty, identifikátory & profily , v nabídce vlevo vyberte Profily a pak výběrem vytvořte + nový profil. Zobrazí se obrazovka Zaregistrovat nový zřizovací profil .

  6. V okně Vybrat certifikáty vyberte certifikát pro vývoj, který jste vytvořili. Pak vyberte Pokračovat.

  7. Dále vyberte zařízení, která chcete použít k testování, a vyberte Pokračovat.

  8. Nakonec zvolte název profilu v části Název zřizovacího profilu a vyberte Vygenerovat.

    Volba názvu zřizovacího profilu

  9. Po vytvoření nového zřizovacího profilu vyberte Stáhnout. Zapamatujte si umístění, do kterého se uloží.

  10. Přejděte do umístění zřizovacího profilu a poklikáním ho nainstalujte na vývojový počítač.

Vytvoření centra oznámení

V této části vytvoříte centrum oznámení a nakonfigurujete ověřování pomocí APNS. Můžete použít certifikát p12 push nebo ověřování založené na tokenech. Pokud chcete použít centrum oznámení, které jste už vytvořili, můžete přeskočit ke kroku 5.

  1. Přihlaste se k Azure.

  2. Klikněte na Vytvořit prostředek, vyhledejte a zvolte Centrum oznámení a pak klikněte na Vytvořit.

  3. Aktualizujte následující pole a pak klikněte na Vytvořit:

    ZÁKLADNÍ PODROBNOSTI

    Předplatné: V rozevíracím seznamu zvolte cílové předplatné.
    Skupina prostředků: Vytvoření nové skupiny prostředků (nebo výběr existující skupiny)

    PODROBNOSTI O OBORU NÁZVŮ

    Obor názvů centra oznámení: Zadejte globálně jedinečný název oboru názvů centra oznámení .

    Poznámka

    Ujistěte se, že je pro toto pole vybraná možnost Vytvořit nový .

    PODROBNOSTI CENTRA OZNÁMENÍ

    Centrum oznámení: Zadejte název centra oznámení.
    Umístění: V rozevíracím seznamu vyberte vhodné umístění.
    Cenová úroveň: Zachovat výchozí možnost Free

    Poznámka

    Pokud jste nedosáhli maximálního počtu center na úrovni Free.

  4. Po zřízení centra oznámení přejděte k ho prostředku.

  5. Přejděte do nového centra oznámení.

  6. V seznamu (v části SPRAVOVAT) vyberte Zásady přístupu.

  7. Poznamenejte si hodnoty Název zásady spolu s odpovídajícími hodnotami připojovacího řetězce .

Konfigurace centra oznámení s využitím informací APNS

V části Notification Services (Služby oznámení) vyberte Apple a pak postupujte podle postupu, který jste zvolili dříve v části Creating a Certificate for Notification Hubs (Vytvoření certifikátu pro Notification Hubs ).

Poznámka

Produkčnírežim pro aplikační režim používejte jenom v případě, že chcete odesílat nabízená oznámení uživatelům, kteří zakoupili vaši aplikaci z obchodu.

MOŽNOST 1: Použití nabízeného certifikátu .p12

  1. Vyberte Certifikát.

  2. Vyberte ikonu souboru.

  3. Vyberte soubor .p12, který jste vyexportovali dříve, a pak vyberte Otevřít.

  4. V případě potřeby zadejte správné heslo.

  5. Vyberte Režim sandboxu .

  6. Vyberte Uložit.

MOŽNOST 2: Použití ověřování na základě tokenů

  1. Vyberte Token.

  2. Zadejte následující hodnoty, které jste získali dříve:

    • ID klíče
    • ID sady
    • ID týmu
    • Token
  3. Zvolte Sandbox.

  4. Vyberte Uložit.

Konfigurace centra oznámení s využitím informací FCM

  1. V části Nastavení v nabídce vlevo vyberte Google (GCM/FCM).
  2. Zadejte klíč serveru , který jste si poznamenali z konzoly Google Firebase Console.
  3. Na panelu nástrojů vyberte Uložit .

Vytvoření back-endové aplikace ASP.NET Core webového rozhraní API

V této části vytvoříte back-end webového rozhraní API ASP.NET Core, který bude zpracovávat registraci zařízení a odesílání oznámení do mobilní aplikace Xamarin.Forms.

Vytvoření webového projektu

  1. V sadě Visual Studio vyberte Soubor>nové řešení.

  2. VyberteAplikace>.NET Core>ASP.NET Core>Další rozhraní API>.

  3. V dialogovém okně Konfigurace nového webového rozhraní API ASP.NET Core vyberte Cílová architekturarozhraní .NET Core 3.1.

  4. Jako Název projektu zadejte PushDemoApi a pak vyberte Vytvořit.

  5. Spusťte ladění (příkaz Enter + ) a otestujte aplikaci v šabloně.

    Poznámka

    Aplikace v šabloně je nakonfigurovaná tak, aby jako launchUrl používala WeatherForecastController. Toto nastavení je nastaveno vlaunchSettings.jsonVlastnosti>.

    Pokud se zobrazí výzva se zprávou o nalezení neplatného vývojového certifikátu :

    1. Kliknutím na Ano potvrďte souhlas se spuštěním nástroje dotnet dev-certs https, který tento problém vyřeší. Nástroj dotnet dev-certs https vás pak vyzve k zadání hesla pro certifikát a hesla pro klíčku.

    2. Po zobrazení výzvy k instalaci a důvěryhodnosti nového certifikátu klikněte na Ano a pak zadejte heslo pro klíčku.

  6. Rozbalte složku Kontrolery a pak odstraňte WeatherForecastController.cs.

  7. Odstranit WeatherForecast.cs.

  8. Nastavte hodnoty místní konfigurace pomocí nástroje Secret Manager. Oddělení tajných kódů od řešení zajistí, že neskončí ve správě zdrojového kódu. Otevřete Terminál , přejděte do adresáře souboru projektu a spusťte následující příkazy:

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

    Zástupné hodnoty nahraďte vlastním názvem centra oznámení a hodnotami připojovací řetězec. Poznamenali jste si je v části Vytvoření centra oznámení . V opačném případě je můžete vyhledat v Azure.

    NotificationHub:Name:
    Název najdete v souhrnu Základy v horní části Přehled.

    NotificationHub:ConnectionString:
    Viz DefaultFullSharedAccessSignature v zásadách přístupu.

    Poznámka

    V produkčních scénářích se můžete podívat na možnosti bezpečného uložení připojovací řetězec, jako je Azure KeyVault. Pro zjednodušení se tajné kódy přidají do Azure App Service nastavení aplikace.

Ověřování klientů pomocí klíče rozhraní API (volitelné)

Klíče rozhraní API nejsou tak zabezpečené jako tokeny, ale pro účely tohoto kurzu budou stačit. Klíč rozhraní API je možné snadno nakonfigurovat prostřednictvím middlewaru ASP.NET.

  1. Přidejte klíč rozhraní API k hodnotám místní konfigurace.

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

    Poznámka

    Zástupnou hodnotu byste měli nahradit vlastní hodnotou a poznamenejte si ji.

  2. Ovládací prvek + Klikněte na projekt PushDemoApi, v nabídce Přidat zvolte Nová složka a pak jako název složky klikněte na Přidat pomocí ověřování.

  3. Ovládací prvek + Klikněte na složku Ověřování a pak v nabídce Přidat zvolte Nový soubor.

  4. Vyberte Obecná>prázdná třída, jako Název zadejte ApiKeyAuthOptions.cs a pak klikněte na Nová a přidejte následující implementaci.

    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. Přidejte další prázdnou třídu do složky Ověřovánís názvem ApiKeyAuthHandler.cs a pak přidejte následující implementaci.

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

    Poznámka

    Obslužná rutina ověřování je typ, který implementuje chování schématu, v tomto případě vlastní schéma klíče rozhraní API.

  6. Do složky Authentication přidejte další prázdnou třídus názvem ApiKeyAuthenticationBuilderExtensions.cs a pak přidejte následující implementaci.

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

    Poznámka

    Tato metoda rozšíření zjednodušuje konfigurační kód middlewaru v Startup.cs je čitelnější a obecně jednodušší.

  7. V Startup.cs aktualizujte metodu ConfigureServices a nakonfigurujte ověřování pomocí klíče rozhraní API pod voláním služeb. Metoda 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. Stále v Startup.csaktualizujte metodu Configure tak, aby volala metody rozšíření UseAuthentication a UseAuthorization v nástroji IApplicationBuilder aplikace. Ujistěte se, že se tyto metody volají po PoužitíRouting a před aplikací. Použijte Koncové body.

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

    Poznámka

    Volání UseAuthentication zaregistruje middleware, který používá dříve zaregistrovaná schémata ověřování (z ConfigureServices). Musí se volat před jakýmkoli middlewarem, který závisí na ověření uživatelů.

Přidání závislostí a konfigurace služeb

ASP.NET Core podporuje vzor návrhu softwaru pro injektáž závislostí (DI), což je technika pro dosažení inverze řízení (IoC) mezi třídami a jejich závislostmi.

Použití centra oznámení a sady Notification Hubs SDK pro back-endové operace je zapouzdřeno v rámci služby. Služba se zaregistruje a zpřístupní prostřednictvím vhodné abstrakce.

  1. Ovládací prvek + Klikněte na složku Dependencies (Závislosti ) a pak zvolte Manage NuGet Packages(Spravovat balíčky NuGet...).

  2. Vyhledejte Microsoft.Azure.NotificationHubs a ujistěte se, že je zaškrtnuté.

  3. Klikněte na Přidat balíčky a po zobrazení výzvy k přijetí licenčních podmínek klikněte na Přijmout .

  4. Ovládací prvek + Klikněte na projekt PushDemoApi, v nabídce Přidat zvolte Nová složka a pak jako název složky klikněte na Přidat pomocí modelů.

  5. Ovládací prvek + Klikněte na složku Modely a pak v nabídce Přidat zvolte Nový soubor.

  6. Vyberte Obecná>prázdná třída, jako Název zadejte PushTemplates.cs a pak klikněte na Nová a přidejte následující implementaci.

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

    Poznámka

    Tato třída obsahuje tokenizované datové části oznámení pro obecná a bezobslužná oznámení vyžadovaná tímto scénářem. Datové části jsou definovány mimo instalaci , aby bylo možné experimentovat bez nutnosti aktualizovat stávající instalace prostřednictvím služby. Zpracování změn v instalacích tímto způsobem je pro tento kurz mimo rozsah. V produkčním prostředí zvažte vlastní šablony.

  7. Do složky Models přidejte další prázdnou třídus názvem DeviceInstallation.cs a pak přidejte následující implementaci.

    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. Do složky Models přidejte další prázdnou třídus názvem NotificationRequest.cs a pak přidejte následující implementaci.

    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. Do složky Models přidejte další prázdnou třídus názvem NotificationHubOptions.cs a pak přidejte následující implementaci.

    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class NotificationHubOptions
        {
            [Required]
            public string Name { get; set; }
    
            [Required]
            public string ConnectionString { get; set; }
        }
    }
    
  10. Do projektu PushDemoApi přidejte novou složku s názvem Services.

  11. Přidejte prázdné rozhraní do složky Službys názvem INotificationService.cs a pak přidejte následující implementaci.

    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. Do složky Services přidejte prázdnou třídu s názvem NotificationHubsService.cs a pak přidejte následující kód pro implementaci rozhraní 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);
            }
        }
    }
    

    Poznámka

    Výraz značky zadaný pro SendTemplateNotificationAsync je omezený na 20 značek. Pro většinu operátorů je omezen na 6, ale výraz v tomto případě obsahuje pouze ORS (||). Pokud je v požadavku více než 20 značek, musí být rozděleny do několika požadavků. Další podrobnosti najdete v dokumentaci ke směrování a výrazům značek .

  13. V Startup.cs aktualizujte metodu ConfigureServices tak, aby přidala NotificationHubsService jako jednoúčelovou implementaci 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();
    }
    

Vytvoření rozhraní API pro oznámení

  1. Ovládací prvek + Klikněte na složku Kontrolery a pak v nabídce Přidat zvolte Nový soubor.

  2. Vyberte ASP.NET Core>Třída kontroleru webového rozhraní API, jako Název zadejte NotificationsController a pak klikněte na Nový.

    Poznámka

    Pokud sledujete visual Studio 2019, zvolte šablonu Kontroler rozhraní API s akcemi čtení/zápisu .

  3. Na začátek souboru přidejte následující obory názvů.

    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. Aktualizujte řadič šablony tak, aby byl odvozen z ControllerBase a je opatřen atributem ApiController .

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

    Poznámka

    Základní třída Controller poskytuje podporu zobrazení, ale v tomto případě to není potřeba, a proto lze místo toho použít ControllerBase . Pokud sledujete visual Studio 2019, můžete tento krok přeskočit.

  5. Pokud jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API , měli byste také připojit NotificationsControlleratributem Autorizovat .

    [Authorize]
    
  6. Aktualizujte konstruktor tak, aby přijal zaregistrovanou instanci INotificationService jako argument a přiřaďte ji členu jen pro čtení.

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  7. V launchSettings.json (ve složce Properties ) změňte launchUrl z weatherforecast na api/notifications tak, aby odpovídalo adrese URL zadané v atributu RegistrationsControllerRoute .

  8. Spusťte ladění (Command + Enter) a ověřte, že aplikace funguje s novým notificationControllerem a vrátí stav 401 Neautorizováno .

    Poznámka

    Visual Studio nemusí automaticky spustit aplikaci v prohlížeči. K testování rozhraní API od tohoto okamžiku použijete Nástroj Postman .

  9. Na nové kartě Postman nastavte požadavek na GET. Zadejte adresu níže a nahraďte zástupný symbol< applicationUrl> řetězcem https applicationUrl, který najdete v části Vlastnosti>launchSettings.json.

    <applicationUrl>/api/notifications
    

    Poznámka

    ApplicationUrl by měl být 'https://localhost:5001' pro výchozí profil. Pokud používáte službu IIS (výchozí nastavení v sadě Visual Studio 2019 ve Windows), měli byste místo toho použít adresu applicationUrl zadanou v položce iisSettings . Pokud je adresa nesprávná, dostanete odpověď 404.

  10. Pokud jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API , nezapomeňte nakonfigurovat hlavičky požadavku tak, aby obsahovaly hodnotu apikey .

    Klíč Hodnotu
    klíč rozhraní api <your_api_key>
  11. Klikněte na tlačítko Odeslat .

    Poznámka

    U nějakého obsahu JSON byste měli obdržet stav 200 OK.

    Pokud se zobrazí upozornění na ověření certifikátu SSL , můžete nastavení postman požadavku na ověření certifikátu SSL vypnout v Nastavení.

  12. Nahraďte šablonované metody tříd v NotificationsController.cs následujícím kódem.

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

Vytvoření aplikace API

Teď vytvoříte aplikaci API v Azure App Service pro hostování back-endové služby.

  1. Přihlaste se k Azure Portal.

  2. Klikněte na Vytvořit prostředek, vyhledejte a zvolte Aplikace API a pak klikněte na Vytvořit.

  3. Aktualizujte následující pole a klikněte na Vytvořit.

    Název aplikace:
    Zadejte globálně jedinečný název aplikace API.

    Předplatné:
    Zvolte stejné cílové předplatné, ve které jste vytvořili centrum oznámení.

    Skupina prostředků:
    Zvolte stejnou skupinu prostředků , ve které jste vytvořili centrum oznámení.

    App Service plán/umístění:
    Vytvoření nového plánu App Service

    Poznámka

    Přejděte z výchozí možnosti na plán, který zahrnuje podporu SSL . V opačném případě budete muset při práci s mobilní aplikací provést příslušné kroky, aby se zabránilo zablokování požadavků HTTP .

    Application Insights:
    Ponechte si navrženou možnost (nový prostředek se vytvoří pod tímto názvem) nebo vyberte existující prostředek.

  4. Po zřízení aplikace API přejděte k danému prostředku.

  5. Poznamenejte si vlastnost URL v souhrnu essentials v horní části přehledu. Tato adresa URL je váš back-endový koncový bod , který se použije později v tomto kurzu.

    Poznámka

    Adresa URL používá název aplikace API, který jste zadali dříve, ve formátu https://<app_name>.azurewebsites.net.

  6. V seznamu vyberte Konfigurace (v části Nastavení).

  7. Pro každé z níže uvedených nastavení klikněte na Nové nastavení aplikace a zadejte Název a Hodnotu a potom klikněte na OK.

    Jméno Hodnotu
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Poznámka

    Jedná se o stejná nastavení, která jste definovali dříve v uživatelských nastaveních. Měli byste být schopni je zkopírovat. Nastavení Authentication:ApiKey je povinné jenom v případě, že jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API . V produkčních scénářích se můžete podívat na možnosti, jako je Azure KeyVault. Ty byly v tomto případě přidány jako nastavení aplikace pro zjednodušení.

  8. Po přidání všech nastavení aplikace klikněte na Uložit a pak na Pokračovat.

Publikování back-endové služby

Dále aplikaci nasadíte do aplikace API, aby byla přístupná ze všech zařízení.

Poznámka

Následující kroky jsou specifické pro Visual Studio pro Mac. Pokud používáte Visual Studio 2019 ve Windows, tok publikování se bude lišit. Viz Publikování do Azure App Service ve Windows.

  1. Pokud jste to ještě neudělali, změňte konfiguraci z Ladění na Vydání .

  2. Ovládací prvek + Klikněte na projekt PushDemoApi a pak v nabídce Publish (Publikovat) zvolte Publish to Azure... (Publikovat do Azure... ).

  3. Pokud se zobrazí výzva, postupujte podle toku ověřování. Použijte účet, který jste použili při předchozím vytvoření oddílu aplikace API .

  4. Jako cíl publikování vyberte aplikaci api Azure App Service, kterou jste vytvořili dříve, a pak klikněte na Publikovat.

Po dokončení průvodce publikuje aplikaci do Azure a otevře ji. Poznamenejte si adresu URL , pokud jste to ještě neudělali. Tato adresa URL je váš back-endový koncový bod , který se použije později v tomto kurzu.

Ověření publikovaného rozhraní API

  1. V nástroji Postman otevřete novou kartu, nastavte požadavek na PUT a zadejte níže uvedenou adresu. Zástupný symbol nahraďte základní adresou, kterou jste si poznamenali v předchozím oddílu publikování back-endové služby .

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

    Poznámka

    Základní adresa by měla být ve formátu . https://<app_name>.azurewebsites.net/

  2. Pokud jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API , nezapomeňte nakonfigurovat hlavičky požadavku tak, aby obsahovaly hodnotu klíče rozhraní API .

    Klíč Hodnotu
    klíč rozhraní API <your_api_key>
  3. Zvolte nezpracovanou možnost pro text, pak v seznamu možností formátování zvolte JSON a pak přidejte nějaký zástupný obsah JSON :

    {}
    
  4. Klikněte na Odeslat.

    Poznámka

    Ze služby byste měli obdržet stav 422 UnprocessableEntity .

  5. Znovu proveďte kroky 1 až 4, ale tentokrát zadejte koncový bod požadavků, abyste ověřili, že obdržíte odpověď 400 – Chybný požadavek .

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

Poznámka

Rozhraní API zatím není možné otestovat pomocí platných dat požadavků, protože to bude vyžadovat informace specifické pro platformu z klientské mobilní aplikace.

Vytvoření multiplatformní aplikace Xamarin.Forms

V této části vytvoříte mobilní aplikaci Xamarin.Forms , která implementuje nabízená oznámení pro různé platformy.

Umožňuje registraci a zrušení registrace z centra oznámení prostřednictvím back-endové služby, kterou jste vytvořili.

Upozornění se zobrazí, když je zadaná akce a aplikace je v popředí. V opačném případě se oznámení zobrazí v centru oznámení.

Poznámka

Akce registrace (a zrušení registrace) byste obvykle prováděli v příslušném bodě životního cyklu aplikace (nebo možná jako součást prvního spuštění) bez explicitních vstupů registrace/zrušení registrace uživatele. Tento příklad ale bude vyžadovat explicitní uživatelský vstup, aby bylo možné tuto funkci snadněji prozkoumat a otestovat.

Vytvoření řešení Xamarin.Forms

  1. V sadě Visual Studio vytvořte nové řešení Xamarin.Forms, které jako šablonu použije prázdnou aplikaci Formulářů a jako název projektu zadáte PushDemo.

    Poznámka

    V dialogovém okně Konfigurovat prázdnou aplikaci formulářů se ujistěte , že identifikátor organizace odpovídá hodnotě, kterou jste použili dříve, a zkontrolujte cíle pro Android i iOS .

  2. Ovládací prvek + Klikněte na řešení PushDemo a pak zvolte Aktualizovat balíčky NuGet.

  3. Ovládací prvek + Klikněte na řešení PushDemo a pak zvolte Spravovat balíčky NuGet.

  4. Vyhledejte Newtonsoft.Json a ujistěte se, že je zaškrtnutý.

  5. Klikněte na Přidat balíčky a po zobrazení výzvy k přijetí licenčních podmínek klikněte na Přijmout .

  6. Sestavte a spusťte aplikaci na každé cílové platformě (příkaz Enter + ) a otestujte spuštění aplikace v šabloně na vašich zařízeních.

Implementace komponent pro různé platformy

  1. Ovládací prvek + Klikněte na projekt PushDemo, v nabídce Přidat zvolte Nová složka a pak jako název složky klikněte na Přidat pomocí modelů.

  2. Ovládací prvek + Klikněte na složku Models (Modely) a pak v nabídce Add (Přidat) zvolte New File... (Nový soubor).

  3. Vyberte Obecná>prázdná třída, zadejte DeviceInstallation.cs a pak přidejte následující implementaci.

    using System.Collections.Generic;
    using Newtonsoft.Json;
    
    namespace PushDemo.Models
    {
        public class DeviceInstallation
        {
            [JsonProperty("installationId")]
            public string InstallationId { get; set; }
    
            [JsonProperty("platform")]
            public string Platform { get; set; }
    
            [JsonProperty("pushChannel")]
            public string PushChannel { get; set; }
    
            [JsonProperty("tags")]
            public List<string> Tags { get; set; } = new List<string>();
        }
    }
    
  4. Přidejte prázdný výčet do složky Models s názvem PushDemoAction.cs s následující implementací.

    namespace PushDemo.Models
    {
        public enum PushDemoAction
        {
            ActionA,
            ActionB
        }
    }
    
  5. Přidejte novou složku do projektu PushDemo s názvem Services a pak přidejte prázdnou třídu do této složky s názvem ServiceContainer.cs s následující implementací.

    using System;
    using System.Collections.Generic;
    
    namespace PushDemo.Services
    {
       public static class ServiceContainer
       {
           static readonly Dictionary<Type, Lazy<object>> services
               = new Dictionary<Type, Lazy<object>>();
    
           public static void Register<T>(Func<T> function)
               => services[typeof(T)] = new Lazy<object>(() => function());
    
           public static T Resolve<T>()
               => (T)Resolve(typeof(T));
    
           public static object Resolve(Type type)
           {
               {
                   if (services.TryGetValue(type, out var service))
                       return service.Value;
    
                   throw new KeyNotFoundException($"Service not found for type '{type}'");
               }
           }
       }
    }
    

    Poznámka

    Toto je zkrácená verze třídy ServiceContainer z úložiště XamCAT . Použije se jako odlehčený kontejner IoC (Inversion of Control).

  6. Přidejte prázdné rozhraní do složky Službys názvem IDeviceInstallationService.cs a pak přidejte následující kód.

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

    Poznámka

    Toto rozhraní bude implementováno a spouštěno každým cílem později, aby poskytovalo funkce specifické pro platformu a informace o instalaci zařízení vyžadované back-endovou službou.

  7. Do složky Služby přidejte další prázdné rozhraní s názvem INotificationRegistrationService.cs a pak přidejte následující kód.

    using System.Threading.Tasks;
    
    namespace PushDemo.Services
    {
        public interface INotificationRegistrationService
        {
            Task DeregisterDeviceAsync();
            Task RegisterDeviceAsync(params string[] tags);
            Task RefreshRegistrationAsync();
        }
    }
    

    Poznámka

    Tím se zpracuje interakce mezi klientem a back-endovou službou.

  8. Do složky Services přidejte další prázdné rozhraní s názvem INotificationActionService.cs a pak přidejte následující kód.

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

    Poznámka

    Používá se jako jednoduchý mechanismus pro centralizaci zpracování akcí oznámení.

  9. Přidejte prázdné rozhraní do složky Servicess názvem IPushDemoNotificationActionService.cs odvozené od INotificationActionService s následující implementací.

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

    Poznámka

    Tento typ je specifický pro aplikaci PushDemo a používá výčet PushDemoAction k identifikaci akce, která je aktivována způsobem silného typu.

  10. Přidejte prázdnou třídu do složky Services s názvem NotificationRegistrationService.cs implementaci INotificationRegistrationService s následujícím kódem.

    using System;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    using PushDemo.Models;
    using Xamarin.Essentials;
    
    namespace PushDemo.Services
    {
        public class NotificationRegistrationService : INotificationRegistrationService
        {
            const string RequestUrl = "api/notifications/installations";
            const string CachedDeviceTokenKey = "cached_device_token";
            const string CachedTagsKey = "cached_tags";
    
            string _baseApiUrl;
            HttpClient _client;
            IDeviceInstallationService _deviceInstallationService;
    
            public NotificationRegistrationService(string baseApiUri, string apiKey)
            {
                _client = new HttpClient();
                _client.DefaultRequestHeaders.Add("Accept", "application/json");
                _client.DefaultRequestHeaders.Add("apikey", apiKey);
    
                _baseApiUrl = baseApiUri;
            }
    
            IDeviceInstallationService DeviceInstallationService
                => _deviceInstallationService ??
                    (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>());
    
            public async Task DeregisterDeviceAsync()
            {
                var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey)
                    .ConfigureAwait(false);
    
                if (cachedToken == null)
                    return;
    
                var deviceId = DeviceInstallationService?.GetDeviceId();
    
                if (string.IsNullOrWhiteSpace(deviceId))
                    throw new Exception("Unable to resolve an ID for the device.");
    
                await SendAsync(HttpMethod.Delete, $"{RequestUrl}/{deviceId}")
                    .ConfigureAwait(false);
    
                SecureStorage.Remove(CachedDeviceTokenKey);
                SecureStorage.Remove(CachedTagsKey);
            }
    
            public async Task RegisterDeviceAsync(params string[] tags)
            {
                var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags);
    
                await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation)
                    .ConfigureAwait(false);
    
                await SecureStorage.SetAsync(CachedDeviceTokenKey, deviceInstallation.PushChannel)
                    .ConfigureAwait(false);
    
                await SecureStorage.SetAsync(CachedTagsKey, JsonConvert.SerializeObject(tags));
            }
    
            public async Task RefreshRegistrationAsync()
            {
                var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey)
                    .ConfigureAwait(false);
    
                var serializedTags = await SecureStorage.GetAsync(CachedTagsKey)
                    .ConfigureAwait(false);
    
                if (string.IsNullOrWhiteSpace(cachedToken) ||
                    string.IsNullOrWhiteSpace(serializedTags) ||
                    string.IsNullOrWhiteSpace(DeviceInstallationService.Token) ||
                    cachedToken == DeviceInstallationService.Token)
                    return;
    
                var tags = JsonConvert.DeserializeObject<string[]>(serializedTags);
    
                await RegisterDeviceAsync(tags);
            }
    
            async Task SendAsync<T>(HttpMethod requestType, string requestUri, T obj)
            {
                string serializedContent = null;
    
                await Task.Run(() => serializedContent = JsonConvert.SerializeObject(obj))
                    .ConfigureAwait(false);
    
                await SendAsync(requestType, requestUri, serializedContent);
            }
    
            async Task SendAsync(
                HttpMethod requestType,
                string requestUri,
                string jsonRequest = null)
            {
                var request = new HttpRequestMessage(requestType, new Uri($"{_baseApiUrl}{requestUri}"));
    
                if (jsonRequest != null)
                    request.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
    
                var response = await _client.SendAsync(request).ConfigureAwait(false);
    
                response.EnsureSuccessStatusCode();
            }
        }
    }
    

    Poznámka

    Argument apiKey se vyžaduje jenom v případě, že jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API .

  11. Přidejte prázdnou třídu do složky Services s názvem PushDemoNotificationActionService.cs implementaci IPushDemoNotificationActionService s následujícím kódem.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using PushDemo.Models;
    
    namespace PushDemo.Services
    {
        public class PushDemoNotificationActionService : IPushDemoNotificationActionService
        {
            readonly Dictionary<string, PushDemoAction> _actionMappings = new Dictionary<string, PushDemoAction>
            {
                { "action_a", PushDemoAction.ActionA },
                { "action_b", PushDemoAction.ActionB }
            };
    
            public event EventHandler<PushDemoAction> ActionTriggered = delegate { };
    
            public void TriggerAction(string action)
            {
                if (!_actionMappings.TryGetValue(action, out var pushDemoAction))
                    return;
    
                List<Exception> exceptions = new List<Exception>();
    
                foreach (var handler in ActionTriggered?.GetInvocationList())
                {
                    try
                    {
                        handler.DynamicInvoke(this, pushDemoAction);
                    }
                    catch (Exception ex)
                    {
                        exceptions.Add(ex);
                    }
                }
    
                if (exceptions.Any())
                    throw new AggregateException(exceptions);
            }
        }
    }
    
  12. Přidejte prázdnou třídu do projektu PushDemo s názvem Config.cs s následující implementací.

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

    Poznámka

    Používá se jako jednoduchý způsob, jak udržet tajné kódy mimo správu zdrojového kódu. Tyto hodnoty můžete nahradit jako součást automatizovaného sestavení nebo je přepsat pomocí místní částečné třídy. Uděláte to v dalším kroku.

    Pole ApiKey se vyžaduje jenom v případě, že jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API .

  13. Přidejte další prázdnou třídu do projektu PushDemo , tentokrát s názvem Config.local_secrets.cs s následující implementací.

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

    Poznámka

    Zástupné hodnoty nahraďte vlastními. Měli jste si je poznamenat při vytváření back-endové služby. Adresa URL aplikace API by měla být https://<api_app_name>.azurewebsites.net/. Nezapomeňte přidat *.local_secrets.* soubor gitignore, abyste se vyhnuli potvrzení tohoto souboru.

    Pole ApiKey se vyžaduje jenom v případě, že jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API .

  14. Přidejte prázdnou třídu do projektu PushDemo s názvem Bootstrap.cs s následující implementací.

    using System;
    using PushDemo.Services;
    
    namespace PushDemo
    {
        public static class Bootstrap
        {
            public static void Begin(Func<IDeviceInstallationService> deviceInstallationService)
            {
                ServiceContainer.Register(deviceInstallationService);
    
                ServiceContainer.Register<IPushDemoNotificationActionService>(()
                    => new PushDemoNotificationActionService());
    
                ServiceContainer.Register<INotificationRegistrationService>(()
                    => new NotificationRegistrationService(
                        Config.BackendServiceEndpoint,
                        Config.ApiKey));
            }
        }
    }
    

    Poznámka

    Metoda Begin bude volána jednotlivými platformami při spuštění aplikace s předáváním implementace IDeviceInstallationService specifické pro platformu.

    Argument konstruktoru ApiKeynotificationRegistrationService se vyžaduje pouze v případě, že jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API.

Implementace uživatelského rozhraní pro různé platformy

  1. V projektu PushDemo otevřete soubor MainPage.xaml a nahraďte ovládací prvek StackLayout následujícím kódem.

    <StackLayout VerticalOptions="EndAndExpand"  
                 HorizontalOptions="FillAndExpand"
                 Padding="20,40">
        <Button x:Name="RegisterButton"
                Text="Register"
                Clicked="RegisterButtonClicked" />
        <Button x:Name="DeregisterButton"
                Text="Deregister"
                Clicked="DeregisterButtonClicked" />
    </StackLayout>
    
  2. Teď v MainPage.xaml.cs přidejte pole pro čtení jen pro uložení odkazu na implementaci INotificationRegistrationService .

    readonly INotificationRegistrationService _notificationRegistrationService;
    
  3. V konstruktoru MainPage přeložte implementaci INotificationRegistrationService pomocí ServiceContainer a přiřaďte ji k pomocnému poli notificationRegistrationService .

    public MainPage()
    {
        InitializeComponent();
    
        _notificationRegistrationService =
            ServiceContainer.Resolve<INotificationRegistrationService>();
    }
    
  4. Implementujte obslužné rutiny událostí pro tlačítka RegisterButton a DeregisterButtonClicked události, které volají odpovídající metody Register/Deregister .

    void RegisterButtonClicked(object sender, EventArgs e)
        => _notificationRegistrationService.RegisterDeviceAsync().ContinueWith((task)
            => { ShowAlert(task.IsFaulted ?
                    task.Exception.Message :
                    $"Device registered"); });
    
    void DeregisterButtonClicked(object sender, EventArgs e)
        => _notificationRegistrationService.DeregisterDeviceAsync().ContinueWith((task)
            => { ShowAlert(task.IsFaulted ?
                    task.Exception.Message :
                    $"Device deregistered"); });
    
    void ShowAlert(string message)
        => MainThread.BeginInvokeOnMainThread(()
            => DisplayAlert("PushDemo", message, "OK").ContinueWith((task)
                => { if (task.IsFaulted) throw task.Exception; }));
    
  5. Teď se v App.xaml.cs ujistěte, že se odkazuje na následující obory názvů.

    using PushDemo.Models;
    using PushDemo.Services;
    using Xamarin.Essentials;
    using Xamarin.Forms;
    
  6. Implementujte obslužnou rutinu události IPushDemoNotificationActionServiceActionTriggered události.

    void NotificationActionTriggered(object sender, PushDemoAction e)
        => ShowActionAlert(e);
    
    void ShowActionAlert(PushDemoAction action)
        => MainThread.BeginInvokeOnMainThread(()
            => MainPage?.DisplayAlert("PushDemo", $"{action} action received", "OK")
                .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }));
    
  7. V konstruktoru aplikace přeložte implementaci IPushNotificationActionService pomocí ServiceContainer a přihlaste se k odběru události IPushDemoNotificationActionServiceActionTriggered .

    public App()
    {
        InitializeComponent();
    
        ServiceContainer.Resolve<IPushDemoNotificationActionService>()
            .ActionTriggered += NotificationActionTriggered;
    
        MainPage = new MainPage();
    }
    

    Poznámka

    Slouží pouze k předvedení příjmu a šíření akcí nabízených oznámení. Obvykle by se tyto akce zpracovávaly bezobslužně, například při přechodu do určitého zobrazení nebo při aktualizaci dat, místo aby se upozornění zobrazovalo prostřednictvím kořenové stránky, v tomto případě hlavní stránky .

Konfigurace nativního projektu androidu pro nabízená oznámení

Ověření názvu a oprávnění balíčku

  1. V souboru PushDemo.Android otevřete možnosti projektu a pak aplikaci pro Android v části Sestavení .

  2. Zkontrolujte, že název balíčku odpovídá hodnotě, kterou jste použili v projektu Firebase ConsolePushDemo . Název balíčku byl ve formátu com.<organization>.pushdemo.

  3. Nastavte Minimální verzi Androidu na Android 8.0 (úroveň rozhraní API 26) a Cílovou verzi Androidu na nejnovější úroveň rozhraní API.

    Poznámka

    Pro účely tohoto kurzu jsou podporována pouze zařízení s rozhraním API úrovně 26 a vyšší , ale můžete ho rozšířit o zařízení se staršími verzemi.

  4. Ujistěte se, že jsou v části Požadovaná oprávnění povolená oprávnění k internetu a READ_PHONE_STATE.

  5. Klikněte na OK.

Přidání základního balíčku Xamarin Google Play Services a Xamarin.Firebase.Messaging

  1. V pushdemo.android, control + klikněte na složku Packages a pak zvolte Spravovat balíčky NuGet....

  2. Vyhledejte Xamarin.GooglePlayServices.Base (ne Basement) a ujistěte se, že je zaškrtnuté.

  3. Vyhledejte Xamarin.Firebase.Messaging a ujistěte se, že je zaškrtnuté.

  4. Klikněte na Přidat balíčky a po zobrazení výzvy k přijetí licenčních podmínek klikněte na Přijmout.

Přidání souboru JSON služeb Google

  1. Ovládací prvek + Klikněte na PushDemo.Android projekt a pak v nabídce Přidat zvolte Existující soubor.

  2. Zvolte soubor google-services.json , který jste stáhli dříve při nastavování projektu PushDemo v konzole Firebase a pak klikněte na Otevřít.

  3. Po zobrazení výzvy zvolte Kopírovat soubor do adresáře.

  4. Ovládací prvek + V rámci projektu klikněte na souborPushDemo.Android google-services.json a pak se ujistěte, že je akce Sestavení nastavená na GoogleServicesJson.

Zpracování nabízených oznámení pro Android

  1. Ovládací prvek + Klikněte na PushDemo.Android projekt, v nabídce Přidat zvolte Nová složka a pak klikněte na Přidat pomocí služeb jako název složky.

  2. Ovládací prvek + Klikněte na složku Služby a pak v nabídce Přidat zvolte Nový soubor.

  3. Vyberte Obecná>prázdná třída, jako Název zadejte DeviceInstallationService.cs a pak klikněte na Nová a přidejte následující implementaci.

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

    Poznámka

    Tato třída poskytuje jedinečné ID (pomocí Secure.AndroidId) jako součást datové části registrace centra oznámení.

  4. Do složky Services přidejte další prázdnou třídus názvem PushNotificationFirebaseMessagingService.cs a pak přidejte následující implementaci.

    using Android.App;
    using Android.Content;
    using Firebase.Messaging;
    using PushDemo.Services;
    
    namespace PushDemo.Droid.Services
    {
        [Service]
        [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
        public class PushNotificationFirebaseMessagingService : FirebaseMessagingService
        {
            IPushDemoNotificationActionService _notificationActionService;
            INotificationRegistrationService _notificationRegistrationService;
            IDeviceInstallationService _deviceInstallationService;
    
            IPushDemoNotificationActionService NotificationActionService
                => _notificationActionService ??
                    (_notificationActionService =
                    ServiceContainer.Resolve<IPushDemoNotificationActionService>());
    
            INotificationRegistrationService NotificationRegistrationService
                => _notificationRegistrationService ??
                    (_notificationRegistrationService =
                    ServiceContainer.Resolve<INotificationRegistrationService>());
    
            IDeviceInstallationService DeviceInstallationService
                => _deviceInstallationService ??
                    (_deviceInstallationService =
                    ServiceContainer.Resolve<IDeviceInstallationService>());
    
            public override void OnNewToken(string token)
            {
                DeviceInstallationService.Token = token;
    
                NotificationRegistrationService.RefreshRegistrationAsync()
                    .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; });
            }
    
            public override void OnMessageReceived(RemoteMessage message)
            {
                if(message.Data.TryGetValue("action", out var messageAction))
                    NotificationActionService.TriggerAction(messageAction);
            }
        }
    }
    
  5. V MainActivity.cs se ujistěte, že jsou na začátek souboru přidané následující obory názvů.

    using System;
    using Android.App;
    using Android.Content;
    using Android.Content.PM;
    using Android.OS;
    using Android.Runtime;
    using Firebase.Iid;
    using PushDemo.Droid.Services;
    using PushDemo.Services;
    
  6. V MainActivity.cs nastavte LaunchMode na SingleTop , aby se MainActivity při otevření nevytvořila znovu.

    [Activity(
        Label = "PushDemo",
        LaunchMode = LaunchMode.SingleTop,
        Icon = "@mipmap/icon",
        Theme = "@style/MainTheme",
        MainLauncher = true,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    
  7. Přidejte privátní vlastnosti a odpovídající záložní pole pro uložení odkazu na implementace IPushNotificationActionService a IDeviceInstallationService .

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
    IPushDemoNotificationActionService NotificationActionService
        => _notificationActionService ??
            (_notificationActionService =
            ServiceContainer.Resolve<IPushDemoNotificationActionService>());
    
    IDeviceInstallationService DeviceInstallationService
        => _deviceInstallationService ??
            (_deviceInstallationService =
            ServiceContainer.Resolve<IDeviceInstallationService>());
    
  8. Implementujte rozhraní IOnSuccessListener pro načtení a uložení tokenu Firebase .

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener
    {
        ...
    
        public void OnSuccess(Java.Lang.Object result)
            => DeviceInstallationService.Token =
                result.Class.GetMethod("getToken").Invoke(result).ToString();
    }
    
  9. Přidejte novou metodu s názvem ProcessNotificationActions , která zkontroluje, jestli má daný záměr další hodnotu s názvem action. Podmíněně aktivujte danou akci pomocí implementace IPushDemoNotificationActionService .

    void ProcessNotificationActions(Intent intent)
    {
        try
        {
            if (intent?.HasExtra("action") == true)
            {
                var action = intent.GetStringExtra("action");
    
                if (!string.IsNullOrEmpty(action))
                    NotificationActionService.TriggerAction(action);
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }
    }
    
  10. Přepsat OnNewIntent metoda volání ProcessNotificationActions metoda.

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

    Poznámka

    Vzhledem k tomu, LaunchMode pro aktivitu je nastavena na SingleTop, Intent se odešle do existující instance Activity prostřednictvím OnNewIntent metoda místo OnCreate metoda, takže musíte zpracovat příchozí záměr v obou OnCreate a OnNewIntent metody.

  11. Aktualizujte metodu OnCreate tak, aby volala Bootstrap.Begin hned po volání předání base.OnCreate implementace IDeviceInstallationService specifické pro platformu.

    Bootstrap.Begin(() => new DeviceInstallationService());
    
  12. Ve stejné metodě podmíněně volejte GetInstanceId na instanci FirebaseApp hned po volání , Bootstrap.Begina přidejte MainActivity jako IOnSuccessListener.

    if (DeviceInstallationService.NotificationsSupported)
    {
        FirebaseInstanceId.GetInstance(Firebase.FirebaseApp.Instance)
            .GetInstanceId()
            .AddOnSuccessListener(this);
    }
    
  13. Stále v OnCreate volejteProcessNotificationActions bezprostředně po volání předání LoadApplication aktuálního záměru.

    ...
    
    LoadApplication(new App());
    
    ProcessNotificationActions(Intent);
    

Poznámka

Abyste mohli dál dostávat nabízená oznámení, musíte aplikaci při každém spuštění znovu zaregistrovat a zastavit ji v ladicí relaci.

Konfigurace nativního projektu iOS pro nabízená oznámení

Konfigurace souboru Info.plist a Entitlements.plist

  1. Ujistěte se, že jste se přihlásili ke svému vývojářskému účtu Apple vpředvolbáchsady Visual Studio>...>Publikování>Byly staženy účty Apple Developer a příslušný certifikát a profil zřizování. Tyto prostředky byste měli vytvořit v rámci předchozích kroků.

  2. V PushDemo.iOS otevřete Soubor Info.plist a ujistěte se, že BundleIdentifier odpovídá hodnotě použité pro příslušný profil zřizování na portálu Apple Developer Portal. BundleIdentifier byl ve formátu com.<organization>.PushDemo.

  3. Ve stejném souboru nastavte Minimální verze systému na 13.0.

    Poznámka

    Pro účely tohoto kurzu jsou podporována pouze zařízení se systémem iOS 13.0 a novějším , ale můžete ho rozšířit o zařízení se staršími verzemi.

  4. Otevřete Možnosti projektu pro PushDemo.iOS (poklikejte na projekt).

  5. V části Project Options (Možnosti projektu) v části Build iOS Bundle Signing (Vytvořit > podepisování sady prostředků iOS) zkontrolujte, že je v části Team (Tým) vybraný váš vývojářský účet. Pak se ujistěte, že je vybraná možnost Automaticky spravovat podepisování a že jsou automaticky vybrány podpisový certifikát a profil zřizování.

    Poznámka

    Pokud podpisový certifikát a zřizovací profil nebyly vybrány automaticky, zvolte Ruční zřizování a pak klikněte na Možnosti podepisování sady prostředků. Ujistěte se, že je váš tým vybraný pro podpisovou identitu a že je vybraný zřizovací profil specifický pro PushDemo pro zřizovací profil pro konfiguraci ladění i verze a že je v obou případech pro platformu vybraný iPhone.

  6. V pushdemo.iOS otevřete Entitlements.plist a ujistěte se, že při zobrazení na kartě Nároky je zaškrtnuté políčko Povolit nabízená oznámení. Pak se ujistěte, že je nastavení Prostředí APS při zobrazení na kartě Zdroj nastavené na vývoj.

Zpracování nabízených oznámení pro iOS

  1. Ovládací prvek + Klikněte na projekt PushDemo.iOS, v nabídce Přidat zvolte Nová složka a pak jako název složky klikněte na Přidat pomocí služeb.

  2. Ovládací prvek + Klikněte na složku Služby a pak v nabídce Přidat zvolte Nový soubor.

  3. Vyberte Obecná>prázdná třída, jako Název zadejte DeviceInstallationService.cs a pak klikněte na Nová a přidejte následující implementaci.

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

    Poznámka

    Tato třída poskytuje jedinečné ID (pomocí hodnoty UIDevice.IdentifierForVendor ) a datovou část registrace centra oznámení.

  4. Přidejte do projektu PushDemo.iOS novou složku s názvem Extensions a pak přidejte prázdnou třídu do této složky s názvem NSDataExtensions.cs s následující implementací.

    using System.Text;
    using Foundation;
    
    namespace PushDemo.iOS.Extensions
    {
        internal static class NSDataExtensions
        {
            internal static string ToHexString(this NSData data)
            {
                var bytes = data.ToArray();
    
                if (bytes == null)
                    return null;
    
                StringBuilder sb = new StringBuilder(bytes.Length * 2);
    
                foreach (byte b in bytes)
                    sb.AppendFormat("{0:x2}", b);
    
                return sb.ToString().ToUpperInvariant();
            }
        }
    }
    
  5. V AppDelegate.cs se ujistěte, že jsou na začátek souboru přidané následující obory názvů.

    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;
    using Foundation;
    using PushDemo.iOS.Extensions;
    using PushDemo.iOS.Services;
    using PushDemo.Services;
    using UIKit;
    using UserNotifications;
    using Xamarin.Essentials;
    
  6. Přidejte privátní vlastnosti a jejich příslušná zálohovaná pole pro uložení odkazu na implementace IPushDemoNotificationActionService, INotificationRegistrationService a IDeviceInstallationService .

    IPushDemoNotificationActionService _notificationActionService;
    INotificationRegistrationService _notificationRegistrationService;
    IDeviceInstallationService _deviceInstallationService;
    
    IPushDemoNotificationActionService NotificationActionService
        => _notificationActionService ??
            (_notificationActionService =
            ServiceContainer.Resolve<IPushDemoNotificationActionService>());
    
    INotificationRegistrationService NotificationRegistrationService
        => _notificationRegistrationService ??
            (_notificationRegistrationService =
            ServiceContainer.Resolve<INotificationRegistrationService>());
    
    IDeviceInstallationService DeviceInstallationService
        => _deviceInstallationService ??
            (_deviceInstallationService =
            ServiceContainer.Resolve<IDeviceInstallationService>());
    
  7. Přidejte metodu RegisterForRemoteNotifications pro registraci nastavení oznámení uživatele a pak pro vzdálená oznámení pomocí APNS.

    void RegisterForRemoteNotifications()
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
                UIUserNotificationType.Alert |
                UIUserNotificationType.Badge |
                UIUserNotificationType.Sound,
                new NSSet());
    
            UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
            UIApplication.SharedApplication.RegisterForRemoteNotifications();
        });
    }
    
  8. Přidejte metodu CompleteRegistrationAsync pro nastavení IDeviceInstallationService.Token hodnoty vlastnosti. Aktualizujte registraci a pokud byl token zařízení aktualizovaný od posledního uložení, uloží se do mezipaměti.

    Task CompleteRegistrationAsync(NSData deviceToken)
    {
        DeviceInstallationService.Token = deviceToken.ToHexString();
        return NotificationRegistrationService.RefreshRegistrationAsync();
    }
    
  9. Přidejte metodu ProcessNotificationActions pro zpracování dat oznámení NSDictionary a podmíněné volání NotificationActionService.TriggerAction.

    void ProcessNotificationActions(NSDictionary userInfo)
    {
        if (userInfo == null)
            return;
    
        try
        {
            var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString;
    
            if (!string.IsNullOrWhiteSpace(actionValue?.Description))
                NotificationActionService.TriggerAction(actionValue.Description);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
    
  10. Přepište metodu RegisteredForRemoteNotifications předávání argumentu deviceToken metodě CompleteRegistrationAsync .

    public override void RegisteredForRemoteNotifications(
        UIApplication application,
        NSData deviceToken)
        => CompleteRegistrationAsync(deviceToken).ContinueWith((task)
            => { if (task.IsFaulted) throw task.Exception; });
    
  11. Přepište Metodu ReceivedRemoteNotification předáním argumentu userInfometodě ProcessNotificationActions .

    public override void ReceivedRemoteNotification(
        UIApplication application,
        NSDictionary userInfo)
        => ProcessNotificationActions(userInfo);
    
  12. Přepište metodu FailedToRegisterForRemoteNotifications a zaprotokolujte chybu.

    public override void FailedToRegisterForRemoteNotifications(
        UIApplication application,
        NSError error)
        => Debug.WriteLine(error.Description);
    

    Poznámka

    To je velmi zástupný symbol. V produkčních scénářích budete chtít implementovat správné protokolování a zpracování chyb.

  13. Aktualizujte metodu FinishedLaunching tak, aby volala Bootstrap.Begin hned po volání předání Forms.Init implementace IDeviceInstallationService specifické pro platformu.

    Bootstrap.Begin(() => new DeviceInstallationService());
    
  14. Ve stejné metodě podmíněně požádejte o autorizaci a zaregistrujte vzdálená oznámení ihned po Bootstrap.Begin.

    if (DeviceInstallationService.NotificationsSupported)
    {
        UNUserNotificationCenter.Current.RequestAuthorization(
                UNAuthorizationOptions.Alert |
                UNAuthorizationOptions.Badge |
                UNAuthorizationOptions.Sound,
                (approvalGranted, error) =>
                {
                    if (approvalGranted && error == null)
                        RegisterForRemoteNotifications();
                });
    }
    
  15. Stále v FinishedLaunching, volejte ProcessNotificationActions ihned po volání, LoadApplication pokud argument options obsahuje UIApplication.LaunchOptionsRemoteNotificationKey předání výsledného objektu userInfo .

    using (var userInfo = options?.ObjectForKey(
        UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary)
            ProcessNotificationActions(userInfo);
    

Testování řešení

Teď můžete otestovat odesílání oznámení prostřednictvím back-endové služby.

Odeslání testovacího oznámení

  1. Otevřete novou kartu v nástroji Postman.

  2. Nastavte požadavek na POST a zadejte následující adresu:

    https://<app_name>.azurewebsites.net/api/notifications/requests
    
  3. Pokud jste se rozhodli dokončit část Ověřování klientů pomocí klíče rozhraní API , nezapomeňte nakonfigurovat hlavičky požadavku tak, aby obsahovaly hodnotu klíče rozhraní API .

    Klíč Hodnotu
    klíč rozhraní API <your_api_key>
  4. Zvolte nezpracovanou možnost pro text, pak v seznamu možností formátování zvolte JSON a pak přidejte nějaký zástupný obsah JSON :

    {
        "text": "Message from Postman!",
        "action": "action_a"
    }
    
  5. Vyberte tlačítko Kód , které je pod tlačítkem Uložit v pravém horním rohu okna. Požadavek by měl při zobrazení html vypadat podobně jako v následujícím příkladu (v závislosti na tom, jestli jste zahrnuli hlavičku 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. Spusťte aplikaci PushDemo na jedné nebo obou cílových platformách (Android a iOS).

    Poznámka

    Pokud testujete na Androidu, ujistěte se, že neběžíte v ladění, nebo pokud byla aplikace nasazená spuštěním aplikace, vynuťte ukončení aplikace a spusťte ji znovu ze spouštěče.

  7. V aplikaci PushDemo klepněte na tlačítko Zaregistrovat .

  8. Zpět v Nástroji Postmanzavřete okno Generovat fragmenty kódu (pokud jste to ještě neudělali) a klikněte na tlačítko Odeslat .

  9. Ověřte, že se v nástroji Postman zobrazí odpověď 200 OK a že se v aplikaci zobrazí upozornění s přijatou akcí ActionA.

  10. Zavřete aplikaci PushDemo a potom v nástroji Postman znovu klikněte na tlačítko Odeslat.

  11. Ověřte, že se v Nástroji Postman znovu zobrazí odpověď 200 OK. Ověřte, že se v oznamovací oblasti aplikace PushDemo zobrazí oznámení se správnou zprávou.

  12. Klepnutím na oznámení potvrďte, že se otevře aplikace a zobrazí se upozornění akcePři přijetí akce .

  13. Zpátky v Nástroji Postman upravte text předchozí žádosti tak, aby se odeslalo tiché oznámení, které místo action_a pro hodnotu akce zadá action_b.

    {
        "action": "action_b",
        "silent": true
    }
    
  14. Když je aplikace stále otevřená, klikněte na tlačítko Odeslat v nástroji Postman.

  15. Ověřte, že v nástroji Postman dostanete odpověď 200 OK a že se upozornění zobrazí v aplikaci s přijatou akcí ActionB místo akce ActionA.

  16. Zavřete aplikaci PushDemo a potom v nástroji Postman znovu klikněte na tlačítko Odeslat.

  17. Ověřte, že v nástroji Postman obdržíte odpověď 200 OK a že se v oznamovací oblasti nezobrazuje tiché oznámení.

Řešení potíží

Žádná odpověď z back-endové služby

Při místním testování se ujistěte, že je back-endová služba spuštěná a používá správný port.

Pokud testujete aplikaci Azure API, zkontrolujte, jestli je služba spuštěná, nasazená a spuštěná bez chyby.

Při testování prostřednictvím klienta nezapomeňte zkontrolovat, že jste v nástroji Postman nebo v konfiguraci mobilní aplikace zadali základní adresu správně. Základní adresa by při místním testování měla být https://<api_name>.azurewebsites.net/ nebo https://localhost:5001/ .

Nepřijímají se oznámení v Androidu po spuštění nebo zastavení ladicí relace

Po spuštění nebo zastavení ladicí relace se znovu zaregistrujte. Ladicí program způsobí vygenerování nového tokenu Firebase . Musí se také aktualizovat instalace centra oznámení.

Příjem stavového kódu 401 z back-endové služby

Ověřte, že nastavujete hlavičku požadavku apikey a že tato hodnota odpovídá té, kterou jste nakonfigurovali pro back-endovou službu.

Pokud se při místním testování zobrazí tato chyba, ujistěte se, že hodnota klíče, kterou jste definovali v konfiguraci klienta, odpovídá hodnotě nastavení uživatele Authentication:ApiKey používané rozhraním API.

Pokud testujete pomocí aplikace API, ujistěte se, že hodnota klíče v konfiguračním souboru klienta odpovídá nastavení aplikace Authentication:ApiKey , které používáte v aplikaci API.

Poznámka

Pokud jste toto nastavení vytvořili nebo změnili po nasazení back-endové služby, musíte službu restartovat, aby se projevilo.

Pokud jste se rozhodli nedokončíte část Ověřování klientů pomocí klíče rozhraní API , ujistěte se, že jste nepoužádali atribut Authorize na třídu NotificationsController .

Příjem stavového kódu 404 z back-endové služby

Ověřte správnost koncového bodu a metody požadavku HTTP. Koncové body by například měly být:

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

Nebo při místním testování:

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

Při zadávání základní adresy v klientské aplikaci se ujistěte, že končí na /. Základní adresa by při místním testování měla být https://<api_name>.azurewebsites.net/ nebo https://localhost:5001/ .

Nepovedlo se zaregistrovat a zobrazila se chybová zpráva centra oznámení

Ověřte, že je testovací zařízení připojeno k síti. Pak určete stavový kód odpovědi HTTP nastavením zarážky pro kontrolu hodnoty vlastnosti StatusCode v HttpResponse.

Pokud je to možné, projděte si předchozí návrhy řešení potíží na základě stavového kódu.

Nastavte zarážku na řádky, které vracejí tyto konkrétní stavové kódy pro příslušné rozhraní API. Pak zkuste volat back-endovou službu při místním ladění.

Pomocí příslušné datové části ověřte, že back-endová služba funguje podle očekávání prostřednictvím nástroje Postman . Použijte skutečnou datovou část vytvořenou kódem klienta pro danou platformu.

Projděte si části konfigurace specifické pro platformu a ujistěte se, že nedošlo k vynechání žádných kroků. Zkontrolujte, jestli se pro příslušnou platformu překládají vhodné hodnoty proměnných installation id a token .

Nepodařilo se přeložit ID zařízení, zobrazuje se chybová zpráva

Projděte si části konfigurace specifické pro platformu a ujistěte se, že nedošlo k vynechání žádných kroků.

Další kroky

Teď byste měli mít základní aplikaci Xamarin.Forms připojenou k centru oznámení prostřednictvím back-endové služby a mít možnost odesílat a přijímat oznámení.

Pravděpodobně budete muset přizpůsobit příklad použitý v tomto kurzu tak, aby odpovídal vašemu vlastnímu scénáři. Doporučuje se také implementace robustnějšího zpracování chyb, logiky opakování a protokolování.

Visual Studio App Center je možné rychle začlenit do mobilních aplikací, které poskytují analýzy a diagnostiku , které vám pomůžou při řešení potíží.