Megosztás a következőn keresztül:


Oktatóanyag: Leküldéses értesítések küldése Flutter-alkalmazásoknak az Azure Notification Hubs használatával háttérszolgáltatáson keresztül

Minta letöltése A minta letöltése

Ebben az oktatóanyagban Azure Notification Hubs használatával küld értesítéseket egy Flutter alkalmazásba, amely androidos és iOScéloz meg.

A ASP.NET Core Web API háttérrendszere eszközregisztrációs kezelésére szolgál az ügyfél számára a legújabb és legjobb telepítési módszer használatával. A szolgáltatás leküldéses értesítéseket is küld platformfüggetlen módon.

Ezeket a műveleteket a Notification Hubs SDK-val kezeli a háttérműveletek. Az általános megközelítéssel kapcsolatos további részleteket az Az alkalmazás háttérrendszeréből való regisztráció dokumentációjában talál.

Ez az oktatóanyag végigvezeti a következő lépéseken:

Előfeltételek

A folytatáshoz a következőkre van szükség:

Android esetén a következő eszközökre van szüksége:

  • Egy fejlesztő által feloldott fizikai eszköz vagy emulátor (az API 26-os vagy újabb verzióját futtatja a Google Play Services telepítve).

iOS esetén a következőket kell tennie:

  • Aktív Apple Developer-fiók.
  • A fejlesztői fiók(iOS 13.0 vagy újabb rendszert futtató) fizikai iOS-eszköz.
  • Egy .p12fejlesztési tanúsítvány telepítve a kulcskarika lehetővé teszi az alkalmazás fizikai eszközönfuttatását.

Jegyzet

Az iOS-szimulátor nem támogatja a távoli értesítéseket, ezért a minta iOS-en való feltárásakor fizikai eszközre van szükség. Az oktatóanyag elvégzéséhez azonban nem kell futtatnia az alkalmazást Android és iOS.

Ebben az első alapelves példában szereplő lépéseket előzetes tapasztalat nélkül is végrehajthatja. Az alábbi szempontokat azonban érdemes ismernie.

A megadott lépések a macOSvonatkoznak. A Windows az iOS szempontjainak kihagyásával is nyomon követhető.

Leküldéses értesítési szolgáltatások és az Azure Notification Hub beállítása

Ebben a szakaszban Firebase Cloud Messaging (FCM) és Apple Push Notification Services (APNS). Ezután létre kell hoznia és konfigurálnia kell egy értesítési központot, hogy működjön ezekkel a szolgáltatásokkal.

Firebase-projekt létrehozása és a Firebase Cloud Messaging engedélyezése Androidhoz

  1. Jelentkezzen be a Firebase konzol. Hozzon létre egy új Firebase-projektet, amely PushDemoprojektnévként.

    Jegyzet

    A rendszer egyedi nevet hoz létre Önnek. Alapértelmezés szerint ez a megadott név kisbetűs változatából és egy kötőjellel elválasztott generált számból áll. Ezt módosíthatja, ha azt szeretné, hogy az továbbra is globálisan egyedi legyen.

  2. A projekt létrehozása után válassza a Firebase hozzáadása androidos alkalmazáshozlehetőséget.

    Firebase hozzáadása androidos alkalmazáshoz

  3. Az Firebase hozzáadása androidos alkalmazáshoz lapon hajtsa végre az alábbi lépéseket.

    1. Az Android-csomagnév, adja meg a csomag nevét. Például: com.<organization_identifier>.<package_name>.

      Adja meg a csomag nevét

    2. Válassza Alkalmazás regisztrálásalehetőséget.

    3. Válassza a Letöltés google-services.jsonlehetőséget. Ezután mentse a fájlt egy helyi mappába későbbi használatra, és válassza a Továbblehetőséget.

      letöltési google-services.json

    4. Válassza Következőlehetőséget.

    5. Válassza a Tovább a konzolra

      Jegyzet

      Ha a Tovább a konzolra gomb nincs engedélyezve, a telepítés ellenőrzésének ellenőrzése miatt válassza Hagyja ki ezt a lépést.

  4. A Firebase konzolon válassza ki a projekt fogaskerékét. Ezután válassza Projektbeállításoklehetőséget.

    Projektbeállítások kiválasztása

    Jegyzet

    Ha még nem töltötte le a google-services.json fájlt, ezen a lapon töltheti le.

  5. Váltson a felhőbeli üzenetkezelés lapra a tetején. Másolja és mentse a kiszolgálókulcsot későbbi használatra. Ezzel az értékkel konfigurálhatja az értesítési központot.

    Kiszolgálókulcs másolása

Az iOS-alkalmazás regisztrálása leküldéses értesítésekhez

Ha leküldéses értesítéseket szeretne küldeni egy iOS-alkalmazásnak, regisztrálja az alkalmazást az Apple-ben, és regisztráljon leküldéses értesítésekre is.

  1. Ha még nem regisztrálta az alkalmazást, keresse meg az iOS kiépítési portál az Apple Developer Centerben. Jelentkezzen be a portálra Apple ID azonosítójával, lépjen Tanúsítványok, Azonosítók & Profilok, majd válassza Azonosítóklehetőséget. Új alkalmazás regisztrálásához kattintson a + gombra.

    iOS kiépítési portál alkalmazásazonosítóinak lapja

  2. Az Új azonosító regisztrálása képernyőn válassza az alkalmazásazonosítók választógombot. Ezután válassza a Folytatáslehetőséget.

    iOS Kiépítési portál új azonosítólap regisztrálása

  3. Frissítse a következő három értéket az új alkalmazáshoz, majd válassza a Folytatás:

    • Leírás: Írja be az alkalmazás leíró nevét.

    • csomagazonosító: Adja meg a com.<organization_identifier>űrlap csomagazonosítóját.<product_name> az alkalmazásterjesztési útmutatójában. Az alábbi képernyőképen a mobcat értéket használja a rendszer szervezetazonosítóként, és a PushDemo értéket használja a terméknévként.

      iOS kiépítési portál alkalmazásazonosítóját regisztráló lap

    • Leküldéses értesítések: Ellenőrizze a Leküldéses értesítések lehetőséget a Képességek szakaszban.

      űrlap új alkalmazásazonosító regisztrálásához

      Ez a művelet létrehozza az alkalmazásazonosítót, és kéri, hogy erősítse meg az információkat. Válassza a Folytatáslehetőséget, majd válassza a Regisztrálás lehetőséget az új alkalmazásazonosító megerősítéséhez.

      Új alkalmazásazonosító megerősítése

      Miután kiválasztotta Regisztráláslehetőséget, az új alkalmazásazonosító sorelemként jelenik meg a Tanúsítványok, Azonosítók & Profilok lapon.

  4. A Tanúsítványok, Azonosítók & Profilok lap Azonosítókterületén keresse meg a létrehozott alkalmazásazonosító sorelemet. Ezután válassza ki a sorát az Az alkalmazásazonosító konfigurációjának szerkesztése képernyő megjelenítéséhez.

Tanúsítvány létrehozása a Notification Hubshoz

Tanúsítvány szükséges ahhoz, hogy az értesítési központ működjön Apple Push Notification Services (APNS), és kétféleképpen adható meg:

  1. Közvetlenül a Notification Hubba feltölthető p12 leküldéses tanúsítvány létrehozása (az eredeti megközelítés)

  2. Jogkivonatalapú hitelesítéshez használható p8-tanúsítvány létrehozása (az újabb és javasolt megközelítés)

Az újabb megközelítés számos előnnyel rendelkezik az APNS-tokenalapú (HTTP/2) hitelesítésében. Kevesebb lépésre van szükség, de adott forgatókönyvekhez is kötelező megadni. A lépések azonban mindkét megközelítés esetében meg lettek adva, mivel mindkét módszer az oktatóanyag céljaira fog működni.

1. LEHETŐSÉG: P12 leküldéses tanúsítvány létrehozása, amely közvetlenül feltölthető a Notification Hubba
  1. Mac gépén futtassa a Keychain Access eszközt. A Segédprogramok mappából vagy a Egyéb mappából nyitható meg a launchpaden.

  2. Válassza Kulcskarika-hozzáférési, bontsa ki Tanúsítvány-asszisztens, majd válassza Tanúsítvány kérése hitelesítésszolgáltatótóllehetőséget.

    Kulcskarika-hozzáférés használata új tanúsítvány

    Jegyzet

    Alapértelmezés szerint a Keychain Access kiválasztja a lista első elemét. Ez akkor lehet probléma, ha a Tanúsítványok kategóriában van, és Az Apple Worldwide Developer Relations hitelesítésszolgáltatója nem az első elem a listában. A CSR (tanúsítvány-aláírási kérelem) létrehozása előtt győződjön meg arról, hogy nincs kulcseleme, vagy a Apple Worldwide Developer Relations hitelesítésszolgáltató kulcs van kiválasztva.

  3. Válassza ki a felhasználói e-mail-címét, adja meg a Közös név értéket, győződjön meg arról, hogy megadja a lemezre mentett , majd válassza a Folytatáslehetőséget. Hagyja üresen hitelesítésszolgáltatói e-mail-címet, mert nincs rá szükség.

    Várható tanúsítványinformációk

  4. Adja meg a Tanúsítvány-aláírási kérelem (CSR) fájl nevétMentés máskéntmezőben, jelölje ki a helyet a Hol, majd válassza a Mentéslehetőséget.

    Válasszon egy fájlnevet a tanúsítvány

    Ez a művelet a kiválasztott helyre menti a CSR-fájlt. Az alapértelmezett hely Asztali. Jegyezze meg a fájlhoz választott helyet.

  5. Térjen vissza a Tanúsítványok, Azonosítók & Profilok lapra az iOS kiépítési portál, görgessen le az ellenőrzött Leküldéses értesítések beállításhoz, majd válassza a konfigurálása a tanúsítvány létrehozásához.

    Alkalmazásazonosító szerkesztése lap

  6. Megjelenik Apple Push Notification service TLS/SSL-tanúsítványok ablak. Válassza a Tanúsítvány létrehozása gombot a Fejlesztési TLS/SSL-tanúsítvány szakaszban.

    Tanúsítvány létrehozása alkalmazásazonosítóhoz gomb

    Megjelenik az Új tanúsítvány létrehozása képernyő.

    Jegyzet

    Ez az oktatóanyag fejlesztési tanúsítványt használ. Ugyanezt a folyamatot használja a rendszer egy éles tanúsítvány regisztrálásakor. Csak győződjön meg arról, hogy ugyanazt a tanúsítványtípust használja az értesítések küldésekor.

  7. Válassza a Fájl kiválasztásalehetőséget, keresse meg azt a helyet, ahová a CSR-fájltmentette, majd a betöltéshez kattintson duplán a tanúsítvány nevére. Ezután válassza a Folytatáslehetőséget.

  8. Miután a portál létrehozta a tanúsítványt, válassza a Letöltés gombot. Mentse a tanúsítványt, és jegyezze meg a mentés helyét.

    Létrehozott tanúsítvány letöltési lapja

    A rendszer letölti és menti a tanúsítványt a számítógépre a Letöltések mappában.

    Tanúsítványfájl megkeresése a Letöltések mappában

    Jegyzet

    Alapértelmezés szerint a letöltött fejlesztési tanúsítvány neve aps_development.cer.

  9. Kattintson duplán a letöltött leküldéses tanúsítványra aps_development.cer. Ez a művelet telepíti az új tanúsítványt a kulcskarikán, ahogy az az alábbi képen is látható:

    kulcskarika-hozzáférési tanúsítványok listája az új tanúsítvány

    Jegyzet

    Bár a tanúsítványban szereplő név eltérő lehet, a név előtagja Apple Development iOS Push Services lesz, és a megfelelő csomagazonosítót társítja hozzá.

  10. A Kulcskarika-hozzáférésben Vezérlő + Kattintson a Tanúsítványok kategóriában létrehozott új leküldéses tanúsítványra. Válassza Exportáláslehetőséget, nevezze el a fájlt, jelölje ki a p12 formátumot, majd válassza a Mentéslehetőséget.

    Tanúsítvány exportálása p12 formátumban

    Dönthet úgy, hogy jelszóval védi a tanúsítványt, de a jelszó megadása nem kötelező. Ha meg szeretné kerülni a jelszó létrehozását, kattintson OK gombra. Jegyezze fel az exportált p12-tanúsítvány fájlnevét és helyét. ApN-ekkel történő hitelesítés engedélyezésére szolgálnak.

    Jegyzet

    A p12-fájl neve és helye eltérhet az oktatóanyagban láthatótól.

2. LEHETŐSÉG: Jogkivonatalapú hitelesítéshez használható p8-tanúsítvány létrehozása
  1. Jegyezze fel a következő részleteket:

    • alkalmazásazonosító előtag (csapatazonosító)
    • csomagazonosító
  2. A tanúsítványok, azonosítók & profilokterületen kattintson Kulcsokelemre.

    Jegyzet

    Ha már rendelkezik APNS-konfigurált kulccsal, újra használhatja a közvetlenül a létrehozása után letöltött p8-tanúsítványt. Ha igen, figyelmen kívül hagyhatja 3 lépését 5.

  3. Új kulcs létrehozásához kattintson a + gombra (vagy a Kulcs létrehozása gombra).

  4. Adjon meg egy megfelelő kulcsnevet értéket, majd ellenőrizze az Apple Push Notifications szolgáltatás (APNS) beállítását, majd kattintson a Folytatáselemre, majd a következő képernyőn regisztrálása elemre.

  5. Kattintson a Letöltés elemre, majd helyezze át a p8 fájlt (AuthKey_előtaggal) egy biztonságos helyi könyvtárba, majd kattintson a Készgombra.

    Jegyzet

    Ügyeljen arra, hogy a p8-fájl biztonságos helyen maradjon (és mentsen biztonsági másolatot). A kulcs letöltése után nem tölthető le újra a kiszolgálópéldány eltávolításakor.

  6. A kulcsokkattintson a létrehozott kulcsra (vagy egy meglévő kulcsra, ha ezt választotta).

  7. Jegyezze fel a kulcsazonosító értékét.

  8. Nyissa meg a p8-tanúsítványt egy tetszőleges alkalmazással, például Visual Studio Code. Jegyezze fel a kulcs értékét (-----BEGIN PRIVATE KEY----- és -----END PRIVATE KEY-----között).

    -----BEGIN TITKOS KULCS-----
    <key_value>
    -----END TITKOS KULCS-----

    Jegyzet

    Ez a token értéke, amelyet később a notification hub konfigurálásához használunk.

A lépések végén a következő információkkal kell rendelkeznie, amelyeket később használhat a Az értesítési központ konfigurálása APNS-adatokkal:

  • csapatazonosító (lásd az 1. lépést)
  • csomagazonosító (lásd az 1. lépést)
  • kulcsazonosító (lásd a 7. lépést)
  • token értéke (a 8. lépésben kapott p8 kulcsérték)

Kiépítési profil létrehozása az alkalmazáshoz

  1. Térjen vissza a iOS kiépítési portálra, válassza a Tanúsítványok, Azonosítók & Profiloklehetőséget, a bal oldali menüben válassza Profilok lehetőséget, majd válassza a + új profil létrehozásához. Megjelenik az Új kiépítési profil regisztrálása képernyő.

  2. A kiépítési profil típusaként válassza iOS-alkalmazásfejlesztési a Fejlesztési területen, majd válassza a Folytatáslehetőséget.

    Kiépítési profilok listája

  3. Ezután válassza ki a alkalmazásazonosító legördülő listából létrehozott alkalmazásazonosítót, majd válassza a Folytatáslehetőséget.

    Az alkalmazásazonosító kiválasztása

  4. A Tanúsítványok kiválasztása ablakban válassza ki a kódaláíráshoz használt fejlesztési tanúsítványt, majd válassza a Folytatáslehetőséget.

    Jegyzet

    Ez a tanúsítvány nem az előző . lépésben létrehozott leküldéses tanúsítvány. Ez a fejlesztési tanúsítványa. Ha nem létezik, létre kell hoznia, mivel ez az oktatóanyag előfeltétele. A fejlesztői tanúsítványok az Apple Developer Portal, Xcode vagy Visual Studiosegítségével hozhatók létre.

  5. Térjen vissza a Tanúsítványok, Azonosítók & Profilok lapra, válassza Profilok lehetőséget a bal oldali menüből, majd válassza a + új profil létrehozásához. Megjelenik az Új kiépítési profil regisztrálása képernyő.

  6. A Tanúsítványok kiválasztása ablakban válassza ki a létrehozott fejlesztési tanúsítványt. Ezután válassza a Folytatáslehetőséget.

  7. Ezután válassza ki a teszteléshez használni kívánt eszközöket, majd válassza a Folytatáslehetőséget.

  8. Végül válassza ki a profil nevét Kiépítési profil neve, majd válassza a létrehozása lehetőséget.

    Kiépítési profil nevének kiválasztása

  9. Az új kiépítési profil létrehozásakor válassza a Letöltéslehetőséget. Jegyezze meg a mentés helyét.

  10. Keresse meg a kiépítési profil helyét, majd kattintson rá duplán a fejlesztői gépen való telepítéshez.

Értesítési központ létrehozása

Ebben a szakaszban létrehoz egy értesítési központot, és konfigurálja a hitelesítést APNS. P12 leküldéses tanúsítványt vagy jogkivonatalapú hitelesítést is használhat. Ha már létrehozott értesítési központot szeretne használni, ugorjon az 5. lépésre.

  1. Jelentkezzen be az Azure.

  2. Kattintson az Erőforrás létrehozása, majd a Notification Hub, majd a Létrehozáselemre.

  3. Frissítse a következő mezőket, majd kattintson a létrehozása gombra:

    BASIC DETAILS

    Előfizetés: Válassza ki a cél Előfizetés a legördülő listából
    erőforráscsoport: Hozzon létre egy új erőforráscsoport- (vagy válasszon egy meglévőt)

    NÉVTÉR RÉSZLETEI

    Notification Hub Namespace: Adja meg a Notification Hub névterének globálisan egyedi nevét

    Jegyzet

    Győződjön meg arról, hogy az Új létrehozása beállítás van kiválasztva ehhez a mezőhöz.

    NOTIFICATION HUB RÉSZLETEI

    Notification Hub: Adjon nevet a Notification Hub
    Hely: Válasszon egy megfelelő helyet a legördülő listából
    tarifacsomag: Az alapértelmezett ingyenes lehetőség megtartása

    Jegyzet

    Hacsak nem érte el az ingyenes szinten található hubok maximális számát.

  4. A Notification Hub kiépítése után keresse meg az erőforrást.

  5. Lépjen az új Notification Hub.

  6. Válassza hozzáférési szabályzatok a listából (a MANAGEterületen).

  7. Jegyezze fel a házirend neve értékeket a hozzájuk tartozó kapcsolati sztring értékekkel együtt.

A Notification Hub konfigurálása APNS-adatokkal

Az Notification Servicesterületen válassza Apple, majd kövesse a megfelelő lépéseket az Tanúsítvány létrehozása a Notification Hubshoz szakaszban korábban választott módszer alapján.

Jegyzet

Az Éles csak akkor használja alkalmazásmódhoz, csak akkor, ha leküldéses értesítéseket szeretne küldeni azoknak a felhasználóknak, akik az alkalmazást az áruházból vásárolták.

1. LEHETŐSÉG: .p12 leküldéses tanúsítvány használata

  1. Válassza Tanúsítványlehetőséget.

  2. Válassza ki a fájl ikont.

  3. Jelölje ki a korábban exportált .p12 fájlt, majd válassza a Megnyitáslehetőséget.

  4. Szükség esetén adja meg a megfelelő jelszót.

  5. Válassza Tesztkörnyezet módot.

  6. Válassza Mentéslehetőséget.

2. LEHETŐSÉG: Jogkivonatalapú hitelesítés használata

  1. Válassza Tokenlehetőséget.

  2. Adja meg a korábban beszerzett alábbi értékeket:

    • kulcsazonosító
    • csomagazonosító
    • csapatazonosító
    • token
  3. Válassza Tesztkörnyezetlehetőséget.

  4. Válassza Mentéslehetőséget.

Az értesítési központ konfigurálása FCM-adatokkal

  1. Válassza Google (GCM/FCM) a bal oldali menü Beállítások szakaszában.
  2. Adja meg a kiszolgálókulcsot, feljegyzett Google Firebase Console.
  3. Válassza mentése az eszköztáron lehetőséget.

ASP.NET Core Web API háttéralkalmazás létrehozása

Ebben a szakaszban a ASP.NET Core Web API háttérrendszerét hozza létre eszközregisztrációs kezeléséhez és az értesítések Flutter mobilalkalmazásba való küldéséhez.

Webes projekt létrehozása

  1. A Visual Studioválassza FájlÚj megoldáslehetőséget.

  2. Válassza .NET Core>App>ASP.NET Core>API>Nextlehetőséget.

  3. Az Az új ASP.NET Core Web API párbeszédpanelen válassza .NET Core 3.1Target Framework lehetőséget.

  4. Adja meg PushDemoApi a projektnév, majd válassza a létrehozása lehetőséget.

  5. Indítsa el a hibakeresést (parancs + Enter) a sablonalapú alkalmazás teszteléséhez.

    Jegyzet

    A sablonalapú alkalmazás úgy van konfigurálva, hogy a WeatherForecastController használja a launchUrl. Ez Tulajdonságok>launchSettings.jsonbeállításban van beállítva.

    Ha a rendszer egy érvénytelen fejlesztési tanúsítványt kap, üzenet jelenik meg:

    1. Kattintson az Igen gombra a "dotnet dev-certs https" eszköz futtatásához a probléma megoldásához. A "dotnet dev-certs https" eszköz ezután megkéri, hogy adjon meg jelszót a tanúsítványhoz és a kulcskarika jelszavához.

    2. Kattintson Igen gombra, amikor a rendszer Az új tanúsítvány telepítése és megbízhatósága, majd adja meg a kulcskarika jelszavát.

  6. Bontsa ki a Vezérlők mappát, majd törölje WeatherForecastController.cs.

  7. WeatherForecast.cstörlése.

  8. Állítson be helyi konfigurációs értékeket a Secret Manager eszközhasználatával. A titkos kulcsok megoldástól való leválasztása biztosítja, hogy ne kerülnek a forráskontrollba. Nyissa meg Terminál, majd nyissa meg a projektfájl könyvtárát, és futtassa a következő parancsokat:

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

    Cserélje le a helyőrző értékeket a saját értesítési központ nevére és kapcsolati sztringértékére. A létrehozott egy értesítési központot szakaszban. Ellenkező esetben megkeresheti őket Azure.

    NotificationHub:Name:
    A Áttekintéstetején található Essentials összefoglalásában Név című témakörben talál.

    NotificationHub:ConnectionString:
    Lásd DefaultFullSharedAccessSignaturehozzáférési szabályzatok

    Jegyzet

    Éles helyzetekben a kapcsolati sztring biztonságos tárolásához olyan lehetőségeket tekinthet meg, mint például az Azure KeyVault . Az egyszerűség kedvéért a titkos kulcsok hozzá lesznek adva az Azure App Service alkalmazásbeállításokhoz.

Ügyfelek hitelesítése API-kulccsal (nem kötelező)

Az API-kulcsok nem olyan biztonságosak, mint a jogkivonatok, de elegendőek lesznek az oktatóanyag céljaira. Az API-kulcsok egyszerűen konfigurálhatók a ASP.NET Köztes szoftver.

  1. Adja hozzá a API-kulcsot a helyi konfigurációs értékekhez.

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

    Jegyzet

    Cserélje le a helyőrző értékét a sajátjára, és jegyezze fel.

  2. Vezérlő + Kattintson a PushDemoApi projektre, válassza Új mappa lehetőséget a Hozzáadás menüből, majd kattintson hozzáadása Hitelesítésmappanév.

  3. Vezérlő + Kattintson a elemre a Hitelesítési mappában, majd válassza Új fájl... lehetőséget a Hozzáadás menüből.

  4. Válassza az Általános>Üres osztálylehetőséget, adja meg a névApiKeyAuthOptions.cs, majd kattintson Új a következő implementáció hozzáadásához.

    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. Vegyen fel egy másik Üres osztály a Hitelesítési nevű mappába ApiKeyAuthHandler.cs, majd adja hozzá a következő implementációt.

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

    Jegyzet

    A Authentication Handler olyan típus, amely implementálja a séma viselkedését, ebben az esetben egy egyéni API-kulcsséma.

  6. Adjon hozzá egy másik Üres osztály a Hitelesítési nevű mappához ApiKeyAuthenticationBuilderExtensions.cs, majd adja hozzá a következő implementációt.

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

    Jegyzet

    Ez a bővítménymetódus leegyszerűsíti a köztes szoftver konfigurációs kódját Startup.cs így olvashatóbbá és általánosabban követhetővé válik.

  7. A Startup.csfrissítse a ConfigureServices metódust az API Key-hitelesítés konfigurálásához a -szolgáltatások hívása alatt. AddControllers metódus.

    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. Továbbra is Startup.cs, frissítse a konfigurálása metódust, hogy meghívja a UseAuthentication és UseAuthorization bővítménymetódusokat az alkalmazás IApplicationBuilder. Győződjön meg arról, hogy ezek a metódusok UseRouting és alkalmazás előtt vannak meghívva. UseEndpoints.

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

    Jegyzet

    A UseAuthentication meghívása regisztrálja a korábban regisztrált hitelesítési sémákat használó köztes szoftvert (ConfigureServices). Ezt minden olyan köztes szoftver előtt meg kell hívni, amely a felhasználók hitelesítésétől függ.

Függőségek hozzáadása és szolgáltatások konfigurálása

ASP.NET Core támogatja a függőséginjektálást (DI) szoftvertervezési mintát, amely az osztályok és függőségeik közötti vezérlési (IoC-) elérésére szolgáló technika.

Az értesítési központ és a Notification Hubs SDK használata háttérműveletekhez egy szolgáltatásba van beágyazva. A szolgáltatás regisztrálva van, és megfelelő absztrakción keresztül érhető el.

  1. Vezérlő + Kattintson a a Függőségek mappára, majd válassza a NuGet-csomagok kezelése...lehetőséget.

  2. Keressen Microsoft.Azure.NotificationHubs, és győződjön meg róla, hogy ellenőrizve van.

  3. Kattintson a Csomagok hozzáadásaelemre, majd kattintson elfogadása gombra, amikor a licencfeltételek elfogadására kéri a rendszer.

  4. Vezérlő + Kattintson a PushDemoApi projektre, válassza Új mappa lehetőséget a Hozzáadás menüben, majd kattintson a hozzáadása Modellekmappanévparancsra.

  5. Vezérlő + Kattintson a Modellek mappára, majd válassza Új fájl... lehetőséget a Hozzáadás menüből.

  6. Válassza ÁltalánosÜres osztály, adja meg a NévPushTemplates.cs, majd kattintson Új a következő implementáció hozzáadásához.

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

    Jegyzet

    Ez az osztály tartalmazza az ebben a forgatókönyvben megkövetelt általános és csendes értesítések jogkivonatos értesítési hasznos adatait. A hasznos adatok a telepítési kívül vannak definiálva, hogy lehetővé tegyék a kísérletezést anélkül, hogy frissíteniük kellene a meglévő telepítéseket a szolgáltatáson keresztül. Az oktatóanyag hatókörén kívül esik a telepítések ilyen módon végzett módosításainak kezelése. Éles környezetben fontolja meg egyéni sablonok.

  7. Adjon hozzá egy másik Üres osztály a Modellek nevű mappához DeviceInstallation.cs, majd adja hozzá a következő implementációt.

    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. Adjon hozzá egy másik Üres osztály a Modellek nevű mappához NotificationRequest.cs, majd adja hozzá a következő implementációt.

    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. Vegyen fel egy másik Üres osztály a Modellek nevű mappába NotificationHubOptions.cs, majd adja hozzá a következő implementációt.

    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class NotificationHubOptions
        {
            [Required]
            public string Name { get; set; }
    
            [Required]
            public string ConnectionString { get; set; }
        }
    }
    
  10. Adjon hozzá egy új mappát a PushDemoApi projekthez, amelynek neve Services.

  11. Vegyen fel egy Üres felületi a Services nevű mappába INotificationService.cs, majd adja hozzá a következő implementációt.

    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. Adjon hozzá egy Üres osztályNotificationHubsService.csnevű Services mappához, majd adja hozzá a következő kódot az INotificationService felület implementálásához:

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

    Jegyzet

    A SendTemplateNotificationAsync megadott címkekifejezés legfeljebb 20 címke lehet. A legtöbb operátor esetében 6-ra van korlátozva, de ebben az esetben a kifejezés csak az ORS-eket (||) tartalmazza. Ha a kérelemben több mint 20 címke szerepel, akkor több kérelemre kell felosztani őket. További részletekért tekintse meg az Útválasztási és címkekifejezések dokumentációját.

  13. A Startup.csfrissítse a ConfigureServices metódust, hogy a NotificationHubsService a INotificationServiceegyetlentonos implementációjaként adja hozzá.

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

Az értesítési API létrehozása

  1. Vezérlő + Kattintson a Vezérlők mappára, majd válassza Új fájl... lehetőséget a Hozzáadás menüből.

  2. Válassza ASP.NET Core>Web API Controller Class, adja meg NotificationsController a Név, majd kattintson Újgombra.

    Jegyzet

    Ha a Visual Studio 2019követi, válassza a API-vezérlőt olvasási/írási műveletekkel sablonnal.

  3. Adja hozzá a következő névtereket a fájl elejéhez.

    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. Frissítse a sablonos vezérlőt úgy, hogy az ControllerBase származik, és az ApiController attribútummal van díszítve.

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

    Jegyzet

    A Vezérlő alaposztály támogatja a nézeteket, de erre ebben az esetben nincs szükség, ezért ControllerBase használható helyette. Ha Visual Studio 2019követ, kihagyhatja ezt a lépést.

  5. Ha az Ügyfelek hitelesítése API-kulcs szakasz használatával végzett, akkor a NotificationsController is fel kell díszítenie az Engedélyezés attribútummal.

    [Authorize]
    
  6. Frissítse a konstruktort, hogy fogadja el az INotificationService regisztrált példányát argumentumként, és rendelje hozzá egy olvasható taghoz.

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  7. A launchSettings.json (a Tulajdonságok mappában) módosítsa a launchUrlweatherforecast-ról api/notifications-ra, hogy megfeleljen a RegistrationsControllerRoute attribútumban megadott URL-címnek.

  8. Kezdje el a hibakeresést (Parancs + Enter) annak ellenőrzéséhez, hogy az alkalmazás működik-e az új NotificationsController, és 401 Jogosulatlan állapotot ad vissza.

    Jegyzet

    Előfordulhat, hogy a Visual Studio nem indítja el automatikusan az alkalmazást a böngészőben. Mostantól Postman fogja használni az API teszteléséhez.

  9. Egy új Postman lapon állítsa be a kérést a GET. Adja meg az alábbi címet az applicationUrl helyőrző helyett a TulajdonságoklaunchSettings.jsoncímű témakörben található https applicationUrl.

    <applicationUrl>/api/notifications
    

    Jegyzet

    Az applicationUrl az alapértelmezett profilhozhttps://localhost:5001kell lennie. Ha IIS- használ (windowsos Visual Studio 2019 alapértelmezés szerint), az iisSettings elemben megadott applicationUrl kell használnia. Ha a cím helytelen, 404-et kap.

  10. Ha a Ügyfelek hitelesítése API-kulcs szakasz használatával történő hitelesítését választotta, mindenképpen konfigurálja a kérés fejléceit úgy, hogy az tartalmazza a apikey értékét.

    Kulcs Érték
    apikey <your_api_key>
  11. Kattintson a Küldés gombra.

    Jegyzet

    200 OK állapotot kell kapnia néhány JSON- tartalommal.

    Ha SSL-tanúsítvány-ellenőrzésre figyelmeztetést kap, a Beállításokbeállításban kikapcsolhatja az SSL-tanúsítvány-ellenőrzés kérését Postman.

  12. Cserélje le a NotificationsController.cs sablonalapú osztálymeta-metódusát a következő kódra.

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

Az API-alkalmazás létrehozása

Most létrehoz egy API-alkalmazásAzure App Service a háttérszolgáltatás üzemeltetéséhez.

  1. Jelentkezzen be az Azure Portal.

  2. Kattintson Erőforrás létrehozása, majd API-alkalmazás, majd a Létrehozásgombra.

  3. Frissítse a következő mezőket, majd kattintson létrehozása gombra.

    alkalmazás neve:
    Adjon meg egy globálisan egyedi nevet a API-alkalmazás

    előfizetés:
    Válassza ki ugyanazt a célt, Előfizetés, amelyben létrehozta az értesítési központot.

    erőforráscsoport:
    Válassza ki ugyanazt a erőforráscsoportot, amelyben létrehozta az értesítési központot.

    App Service-csomag/hely:
    Új App Service-csomag létrehozása

    Jegyzet

    Váltson az alapértelmezett beállításról olyan csomagra, amely SSL- támogatást tartalmaz. Ellenkező esetben meg kell tennie a megfelelő lépéseket a mobilalkalmazás használatakor, hogy megakadályozza http kérelmek blokkolását.

    Application Insights:
    Tartsa meg a javasolt beállítást (új erőforrás jön létre ezzel a névvel), vagy válasszon egy meglévő erőforrást.

  4. A API-alkalmazás kiépítése után keresse meg az erőforrást.

  5. Jegyezze fel a URL- tulajdonságot az Essentials összefoglalásában az Áttekintéstetején. Ez az URL-cím az oktatóanyag későbbi részében használt háttérvégpont.

    Jegyzet

    Az URL-cím a korábban megadott API-alkalmazásnevet használja, https://<app_name>.azurewebsites.netformátummal.

  6. Válassza Konfigurációs lehetőséget a listából (a Beállításokterületen).

  7. Az alábbi beállítások mindegyikéhez kattintson az Új alkalmazásbeállítás gombra a Név és egy Értékmegadásához, majd kattintson OKgombra.

    Név Érték
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Jegyzet

    Ezek ugyanazok a beállítások, amelyeket korábban a felhasználói beállításokban definiált. Ezeket át kell tudnia másolni. A -hitelesítés:ApiKey beállítás csak akkor szükséges, ha az ügyfelek hitelesítése API-kulcs szakasz használatával végzett hitelesítést választotta. Éles forgatókönyvek esetén olyan lehetőségeket tekinthet meg, mint például Azure KeyVault. Ezek ebben az esetben alkalmazásbeállításokként lettek hozzáadva az egyszerűség kedvéért.

  8. Az összes alkalmazásbeállítás hozzáadása után kattintson a Mentésgombra, majd Folytassa.

A háttérszolgáltatás közzététele

Ezután üzembe helyezi az alkalmazást az API-alkalmazásban, hogy minden eszközről elérhető legyen.

Jegyzet

Az alábbi lépések a Mac Visual Studio. Ha windowsos Visual Studio 2019 követ, a közzétételi folyamat más lesz. Lásd: Közzététel az Azure App Service-ben Windowsrendszeren.

  1. Ha még nem tette meg, módosítsa a konfigurációt Hibakeresési verzióról kiadási.

  2. Vezérlő + Kattintson a PushDemoApi projektre, majd válassza Közzététel az Azure-ban... a Közzététel menüből.

  3. Kövesse a hitelesítési folyamatot, ha a rendszer erre kéri. Használja az előző használt fiókot az API-alkalmazás szakasz létrehozásához.

  4. Válassza ki a közzétételi célként korábban létrehozott Azure App Service API-alkalmazás, majd kattintson a Közzétételgombra.

A varázsló befejezése után közzéteszi az alkalmazást az Azure-ban, majd megnyitja az alkalmazást. Jegyezze fel a URL-, ha még nem tette meg. Ez az URL-cím az oktatóanyag későbbi részében használt háttérvégpont.

A közzétett API érvényesítése

  1. Postman nyisson meg egy új lapot, állítsa be a kérelmet a PUT , és adja meg az alábbi címet. Cserélje le a helyőrzőt az előző a háttérszolgáltatás szakaszában jegyzett alapcímre.

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

    Jegyzet

    Az alapcímnek https://<app_name>.azurewebsites.net/ formátumban kell lennie

  2. Ha a Ügyfelek hitelesítése API-kulcs szakasz használatával történő hitelesítését választotta, mindenképpen konfigurálja a kérés fejléceit úgy, hogy az tartalmazza a apikey értékét.

    Kulcs Érték
    apikey <your_api_key>
  3. Válassza a Törzsnyers lehetőséget, majd a formátumbeállítások listájában válassza JSON, majd adjon meg néhány helyőrzőt JSON--tartalmat:

    {}
    
  4. Kattintson a Küldésgombra.

    Jegyzet

    A szolgáltatástól 422 UnprocessableEntity állapotot kell kapnia.

  5. Hajtsa végre ismét az 1–4. lépést, de ezúttal adja meg a kérelmek végpontjának megadását, hogy ellenőrizze, hogy 400 hibás kérés választ kap.

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

Jegyzet

Az API-t még nem lehet érvényes kérelemadatokkal tesztelni, mivel ehhez platformspecifikus információkra lesz szükség az ügyfél-mobilalkalmazásból.

Platformfüggetlen Flutter-alkalmazás létrehozása

Ebben a szakaszban egy Flutter mobilalkalmazást hoz létre, amely platformfüggetlen módon implementálja a leküldéses értesítéseket.

Lehetővé teszi, hogy regisztráljon és töröljön egy értesítési központból a létrehozott háttérszolgáltatáson keresztül.

Riasztás jelenik meg egy művelet megadásakor, és az alkalmazás az előtérben van. Ellenkező esetben az értesítések megjelennek az értesítési központban.

Jegyzet

A regisztrációs (és törlési) műveleteket általában az alkalmazás életciklusának megfelelő pontján (vagy talán az első futtatás során) hajtaná végre explicit felhasználói regisztráció/regisztráció törlése nélkül. Ez a példa azonban explicit felhasználói bevitelt igényel, hogy a funkció könnyebben vizsgálható és tesztelhető legyen.

A Flutter-megoldás létrehozása

  1. Nyissa meg a Visual Studio Codeúj példányát.

  2. Nyissa meg a parancskatalógus (Shift + Command + P).

  3. Válassza a Flutter: New Project parancsot, majd nyomja le Enterbillentyűt.

  4. Adja meg a projektnévpush_demo, majd válasszon egy projekthelyet.

  5. Amikor a rendszer erre kéri, válassza a Csomagok lekéréselehetőséget.

  6. Vezérlő + Kattintson a a kotlin mappára (alkalmazás>src>), majd válassza a Megjelenítés a Finderbenlehetőséget. Ezután nevezze át a gyermekmappát (a kotlin mappában) com, <your_organization>és pushdemo névre.

    Jegyzet

    A Visual Studio Code sablon használatakor ezek a mappák alapértelmezés szerint com, példa, <project_name>. Feltételezve, hogy mobcat használja a szervezet, a mappastruktúra indikatív módon a következőképpen jelenik meg:

    • kotlin
      • Com
        • mobcat
          • pushdemo
  7. A Visual Studio Codeandroidosappbuild.gradle applicationId értékét frissítse.

    Jegyzet

    A <your_organization> helyőrzőhöz saját szervezetnevet kell használnia. Ha például a szervezet mobcat használ, com.mobcat.pushdemo.

  8. Frissítse a csomag attribútumát a AndroidManifest.xml fájlokban, src>hibakeresési, src>, illetve src>profil alatt. Győződjön meg arról, hogy az értékek megfelelnek az előző lépésben használt applicationId.

    <manifest
        xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.<your_organization>.pushdemo>">
        ...
    </manifest>
    
  9. Frissítse a android:label attribútumot a AndroidManifest.xml fájlban src>PushDemo. Ezután adja hozzá a android:allowBackup attribútumot közvetlenül a android:labelalatt, és állítsa az értékét hamis.

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="PushDemo"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher">
        ...
    </application>
    
  10. Nyissa meg az alkalmazásszintű build.gradle fájlt (androidos>alkalmazás>build.gradle), majd frissítse a compileSdkVersion (az androidos szakaszból) az API 29használatára. Ezután frissítse a minSdkVersion és targetSdkVersion értékeket (a defaultConfig szakaszból) a 26, illetve a 29 .

    Jegyzet

    Ebben az oktatóanyagban csak azokat az eszközöket támogatjuk, amelyek API 26-os vagy annál magasabb szintű futnak, azonban kiterjesztheti a régebbi verziókat futtató eszközökre.

  11. Vezérlő + Kattintson a az ios mappára, majd válassza a Megnyitás Xcode-banlehetőséget.

  12. Az Xcodekattintson a Runner (a xcodeproj a tetején, nem a mappára). Ezután válassza a Futó célcsoportot, és válassza az Általános lapot. Ha a Minden összeállítási konfiguráció ki van választva, frissítse a Csomagazonosítócom.<your_organization>.PushDemo.

    Jegyzet

    A <your_organization> helyőrzőhöz saját szervezetnevet kell használnia. Ha például a szervezet mobcat használ, az a com.mobcat.PushDemocsomagazonosítójának értékét eredményezi.

  13. Kattintson Info.plist, majd frissítse a Csomag nevét értéket a PushDemo

  14. Zárja be Xcode, és térjen vissza Visual Studio Code.

  15. Visszatérve Visual Studio Code, nyissa meg pubspec.yaml, adja hozzá a http és flutter_secure_storageDart-csomagokat függőségként. Ezután mentse a fájlt, és kattintson a Csomagok lekérése, amikor a rendszer erre kéri.

    dependencies:
      flutter:
        sdk: flutter
    
      http: ^0.12.1
      flutter_secure_storage: ^3.3.3
    
  16. Terminálterületen módosítsa a könyvtárat az ios mappára (a Flutter-projekthez). Ezután hajtsa végre a pod telepítési parancsot az új podok telepítéséhez (amelyet a flutter_secure_storage csomag megkövetel).

  17. Vezérlő + Kattintson a a lib mappára, majd válassza Új fájl lehetőséget a menüből a main_page.dart fájlnév használatával. Ezután adja hozzá a következő kódot.

    import 'package:flutter/material.dart';
    
    class MainPage extends StatefulWidget {
      @override
      _MainPageState createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[],
            )
          )
        );
      }
    }
    
  18. A main.dartcserélje le a sablonkódot a következőre.

    import 'package:flutter/material.dart';
    import 'package:push_demo/main_page.dart';
    
    final navigatorKey = GlobalKey<NavigatorState>();
    
    void main() => runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey));
    
  19. A terminál, buildelje és futtassa az alkalmazást az egyes célplatformokon a sablonalapú alkalmazás eszköz(ek)en való futtatásának teszteléséhez. Győződjön meg arról, hogy a támogatott eszközök csatlakoztatva vannak.

    flutter run
    

Platformfüggetlen összetevők implementálása

  1. Vezérlő + Kattintson a a lib mappára, majd válassza Új mappa lehetőséget a menüből, modellek a mappanév.

  2. Vezérlő + Kattintson a modellek mappára, majd a device_installation.dart fájlnév használatával válassza Új fájl lehetőséget a menüből. Ezután adja hozzá a következő kódot.

    class DeviceInstallation {
        final String deviceId;
        final String platform;
        final String token;
        final List<String> tags;
    
        DeviceInstallation(this.deviceId, this.platform, this.token, this.tags);
    
        DeviceInstallation.fromJson(Map<String, dynamic> json)
          : deviceId = json['installationId'],
            platform = json['platform'],
            token = json['pushChannel'],
            tags = json['tags'];
    
        Map<String, dynamic> toJson() =>
        {
          'installationId': deviceId,
          'platform': platform,
          'pushChannel': token,
          'tags': tags,
        };
    }
    
  3. Adjon hozzá egy új fájlt a modellekhezpush_demo_action.dart nevű mappához, definiálja az ebben a példában támogatott műveletek felsorolását.

    enum PushDemoAction {
      actionA,
      actionB,
    }
    
  4. Adjon hozzá egy új mappát a -szolgáltatások nevű projekthez, majd adjon hozzá egy új fájlt a device_installation_service.dart nevű mappához az alábbi implementációval.

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

    Jegyzet

    A <your_organization> helyőrzőhöz saját szervezetnevet kell használnia. Ha például mobcat a szervezetnél, az MethodChannel a com.mobcat.pushdemo/deviceinstallationnevét eredményezi.

    Ez az osztály a mögöttes natív platformmal együttműködve szerzi be a szükséges eszköztelepítési adatokat. A MethodChannel megkönnyíti a kétirányú aszinkron kommunikációt a mögöttes natív platformokkal. A csatorna platformspecifikus megfelelője a későbbi lépésekben jön létre.

  5. Adjon hozzá egy másik fájlt a notification_action_service.dart nevű mappához, az alábbi implementációval.

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

    Jegyzet

    Ez egy egyszerű mechanizmus az értesítési műveletek kezelésének központosítására, hogy azok platformfüggetlen módon, erősen gépelt számbavétellel kezelhetők legyenek. A szolgáltatás lehetővé teszi, hogy a mögöttes natív platform aktiváljon egy műveletet, ha az értesítés hasznos adataiban meg van adva. Emellett lehetővé teszi, hogy a közös kód visszamenőlegesen ellenőrizze, hogy az alkalmazás indításakor adott-e meg egy műveletet, amint a Flutter készen áll a feldolgozásra. Ha például az alkalmazás elindul, koppintson egy értesítésre az értesítési központból.

  6. Adjon hozzá egy új fájlt a szolgáltatásoknotification_registration_service.dart nevű mappához az alábbi implementációval.

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

    Jegyzet

    Ez az osztály a DeviceInstallationService használatát és a háttérszolgáltatáshoz érkező kéréseket foglalja magában a szükséges regisztrációs, regisztráció-törlési és frissítési műveletek végrehajtásához. Az apiKey argumentum csak akkor szükséges, ha a Ügyfelek hitelesítése API-kulcs szakasz használatával végzett.

  7. Adjon hozzá egy új fájlt a config.dart nevű lib mappához az alábbi implementációval.

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

    Jegyzet

    Ez az alkalmazáskulcsok definiálásának egyszerű módja. Cserélje le a helyőrző értékeket a sajátjára. Ezeket fel kellett volna jegyeznie a háttérszolgáltatás létrehozásakor. Az API-alkalmazás URL-címénekhttps://<api_app_name>.azurewebsites.net/kell lennie. Az apiKey tag csak akkor szükséges, ha a Ügyfelek hitelesítése API-kulcs szakasz használatával végzett.

    Mindenképpen vegye fel ezt a gitignore-fájlba, hogy ne véglegesítse ezeket a titkos kulcsokat a forrásvezérlőben.

Platformfüggetlen felhasználói felület implementálása

  1. A main_page.dartcserélje le a build függvényt a következőre.

    @override
    Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 40.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              FlatButton(
                child: Text("Register"),
                onPressed: registerButtonClicked,
              ),
              FlatButton(
                child: Text("Deregister"),
                onPressed: deregisterButtonClicked,
              ),
            ],
          ),
        ),
      );
    }
    
  2. Adja hozzá a szükséges importálást a main_page.dart fájl elejéhez.

    import 'package:push_demo/services/notification_registration_service.dart';
    import 'config.dart';
    
  3. Adjon hozzá egy mezőt a _MainPageState osztályhoz a NotificationRegistrationServicehivatkozásának tárolásához.

    final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
    
  4. A _MainPageState osztályban implementálja a regisztrálása és Deregister gombjainak a lenyomott eseményekhez. Hívja meg a megfelelő Regisztráljon/Deregister metódusokat, majd jelenítsen meg egy riasztást az eredmény jelzésére.

    void registerButtonClicked() async {
        try {
          await notificationRegistrationService.registerDevice(List<String>());
          await showAlert(message: "Device registered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      void deregisterButtonClicked() async {
        try {
          await notificationRegistrationService.deregisterDevice();
          await showAlert(message: "Device deregistered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      Future<void> showAlert({ message: String }) async {
        return showDialog<void>(
          context: context,
          barrierDismissible: false,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('PushDemo'),
              content: SingleChildScrollView(
                child: ListBody(
                  children: <Widget>[
                    Text(message),
                  ],
                ),
              ),
              actions: <Widget>[
                FlatButton(
                  child: Text('OK'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
      }
    
  5. Most main.dart, győződjön meg arról, hogy a következő importálások vannak jelen a fájl tetején.

    import 'package:flutter/material.dart';
    import 'package:push_demo/models/push_demo_action.dart';
    import 'package:push_demo/services/notification_action_service.dart';
    import 'package:push_demo/main_page.dart';
    
  6. Deklaráljon egy változót, amely a NotificationActionService egy példányára mutató hivatkozást tárol, és inicializálja azt.

    final notificationActionService = NotificationActionService();
    
  7. Függvények hozzáadása egy művelet aktiválásakor megjelenő riasztások kezeléséhez.

    void notificationActionTriggered(PushDemoAction action) {
      showActionAlert(message: "${action.toString().split(".")[1]} action received");
    }
    
    Future<void> showActionAlert({ message: String }) async {
      return showDialog<void>(
        context: navigatorKey.currentState.overlay.context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('PushDemo'),
            content: SingleChildScrollView(
              child: ListBody(
                children: <Widget>[
                  Text(message),
                ],
              ),
            ),
            actions: <Widget>[
              FlatButton(
                child: Text('OK'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }
    
  8. Frissítse a függvényt, hogy megfigyelje a NotificationActionServiceactionTriggered streamet, és ellenőrizze az alkalmazás indításakor rögzített műveleteket.

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

    Jegyzet

    Ez egyszerűen a leküldéses értesítési műveletek fogadásának és propagálásának szemléltetése. Ezeket általában csendben kezelik, például egy adott nézetre navigálnak, vagy frissítenek néhány adatot ahelyett, hogy riasztást jelenítenének meg ebben az esetben.

A natív Android-projekt konfigurálása leküldéses értesítésekhez

A Google Services JSON-fájljának hozzáadása

  1. Vezérlő + Kattintson a az androidos mappára, majd válassza a Megnyitás az Android Studio-ben lehetőséget. Ezután váltson a Project nézetre (ha még nem tette meg).

  2. Keresse meg a korábban letöltött google-services.json fájlt, amikor beállította a PushDemo projektet a firebase-konzol. Ezután húzza a alkalmazás modul gyökérkönyvtárába (androidos>androidos>alkalmazás).

Összeállítási beállítások és engedélyek konfigurálása

  1. Váltson a Project nézetre androidos.

  2. Nyissa meg a AndroidManifest.xml, majd adja hozzá a INTERNET- és READ_PHONE_STATE engedélyeket az alkalmazás eleme után a záró címke előtt.

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

A Firebase SDK-k hozzáadása

  1. Az Android Studionyissa meg a projektszintű build.gradle fájlt (Gradle Scriptsbuild.gradle (Project: android)). és győződjön meg arról, hogy rendelkezik a "com.google.gms:google-services" osztályúttal a buildscript>függőségek csomópontban.

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

    Jegyzet

    Győződjön meg arról, hogy a Android Projectlétrehozásakor a Firebase Console utasításainak megfelelően a legújabb verzióra hivatkozik.

  2. Az alkalmazásszintű build.gradle fájlban (Gradle Scripts>build.gradle (Modul: alkalmazás)) alkalmazza a Google Services Gradle beépülő modult. Alkalmazza a beépülő modult közvetlenül az androidos csomópont felett.

    // ...
    
    // Add the following line:
    apply plugin: 'com.google.gms.google-services'  // Google Services plugin
    
    android {
      // ...
    }
    
  3. Ugyanabban a fájlban, a függőségek csomópontban adja hozzá a Cloud Messaging Android-kódtár függőségét.

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

    Jegyzet

    Győződjön meg arról, hogy a Cloud Messaging Android-ügyfél dokumentációjánakalapján a legújabb verzióra hivatkozik.

  4. Mentse a módosításokat, majd kattintson a Szinkronizálás most gombra (az eszköztár parancssorából), vagy Projekt szinkronizálása Gradle Files.

Leküldéses értesítések kezelése Androidhoz

  1. Az Android StudioControlClick on the com.your_organization.pushdemo package folder (appsrckotlin), válassza Csomag lehetőséget az Új menüből. Adja meg szolgáltatások nevét, majd nyomja le a Returnbillentyűt.

  2. Vezérlő + Kattintson a a szolgáltatások mappára, válassza Kotlin-fájl/osztály az Új menüből. Adja meg a DeviceInstallationService nevet, majd nyomja le a Returnbillentyűt.

  3. Implementálja a DeviceInstallationService az alábbi kóddal.

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

    Jegyzet

    Ez az osztály a com.<your_organization>.pushdemo/deviceinstallation csatorna platformspecifikus megfelelőjét implementálja. Ezt az alkalmazás Flutter részében definiálták DeviceInstallationService.dart. Ebben az esetben a hívások a közös kódból a natív gazdagépre kerülnek. Mindenképpen cserélje le a <your_organization> a saját szervezetére, ahol ezt használja.

    Ez az osztály egyedi azonosítót biztosít (Secure.AndroidIdhasználatával) az értesítési központ regisztrációs hasznos adatainak részeként.

  4. Vegyen fel egy másik Kotlin-fájl/osztály a szolgáltatások nevű mappába NotificationRegistrationService, majd adja hozzá a következő kódot.

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

    Jegyzet

    Ez az osztály a com.<your_organization>.pushdemo/notificationregistration csatorna platformspecifikus megfelelőjét implementálja. Ezt az alkalmazás Flutter részében definiálták NotificationRegistrationService.dart. Ebben az esetben a hívások a natív gazdagépről a közös kódra kerülnek. Ügyeljen arra, hogy a <your_organization> a saját szervezetére cserélje, bárhol is használják.

  5. Vegyen fel egy másik Kotlin-fájl/osztály a szolgáltatások nevű mappába NotificationActionService, majd adja hozzá a következő kódot.

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

    Jegyzet

    Ez az osztály a com.<your_organization>.pushdemo/notificationaction csatorna platformspecifikus megfelelőjét implementálja. Ezt az alkalmazás Flutter részében definiálták NotificationActionService.dart. Ebben az esetben mindkét irányban lehet hívást kezdeményezni. Mindenképpen cserélje le a <your_organization> a saját szervezetére, ahol ezt használja.

  6. Adjon hozzá egy új Kotlin-fájl/osztály a com.your_organization.pushdemo csomaghoz, amelynek neve PushNotificationsFirebaseMessagingService, majd implementálja az alábbi kóddal.

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

    Jegyzet

    Ez az osztály felelős az értesítések kezeléséért, ha az alkalmazás az előtérben fut. Feltételesen meghívja a triggerAction a NotificationActionService, ha egy művelet szerepel a onMessageReceivedértesítési hasznos adatában. Ez meghívja refreshRegistration a NotificationRegistrationService, amikor a Firebase jogkivonat újragenerálódik az onNewToken függvény felülírásával.

    Még egyszer, ügyeljen arra, hogy a <your_organization> a saját szervezetére cserélje, bárhol is használják.

  7. Az AndroidManifest.xml (alkalmazás>src>) adja hozzá a PushNotificationsFirebaseMessagingService a alkalmazás eleméhez a com.google.firebase.MESSAGING_EVENT szándékszűrővel.

    <manifest>
        <application>
            <!-- EXISTING MANIFEST CONTENT -->
             <service
                android:name="com.<your_organization>.pushdemo.PushNotificationsFirebaseMessagingService"
                android:exported="false">
                <intent-filter>
                    <action android:name="com.google.firebase.MESSAGING_EVENT" />
                </intent-filter>
            </service>
        </application>
    </manifest>
    
  8. A DeviceInstallationServicevisszafelé győződjön meg arról, hogy a következő importálások találhatók a fájl tetején.

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

    Jegyzet

    Cserélje le a <your_organization> a saját szervezeti értékére.

  9. Frissítse a helyőrző szöveg Placeholder_Get_Value_From_FirebaseMessagingService_Implementation, hogy lekérje a jogkivonat értékét a PushNotificationFirebaseMessagingService.

    fun getDeviceToken() : String {
        if(!playServicesAvailable) {
            throw Exception(getPlayServicesError())
        }
    
        // Get token from the PushNotificationsFirebaseMessagingService.token field.
        val token = PushNotificationsFirebaseMessagingService.token
    
        if (token.isNullOrBlank()) {
            throw Exception("Unable to resolve token for FCM.")
        }
    
        return token
    }
    
  10. MainActivityesetén győződjön meg arról, hogy az alábbi importálások találhatók a fájl tetején.

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

    Jegyzet

    Cserélje le a <your_organization> a saját szervezeti értékére.

  11. Adjon hozzá egy változót a DeviceInstallationServicehivatkozásának tárolásához.

    private lateinit var deviceInstallationService: DeviceInstallationService
    
  12. Adjon hozzá egy processNotificationActions nevű függvényt annak ellenőrzéséhez, hogy egy szándék rendelkezik-e műveletnevű extra értékkel. Feltételesen aktiválja a műveletet, vagy tárolja későbbi használatra, ha a műveletet az alkalmazás indításakor dolgozzák fel.

     private fun processNotificationActions(intent: Intent, launchAction: Boolean = false) {
        if (intent.hasExtra("action")) {
            var action = intent.getStringExtra("action");
    
            if (action.isNotEmpty()) {
                if (launchAction) {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.launchAction = action
                }
                else {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.triggerAction(action)
                }
            }
        }
    }
    
  13. Felülbírálja a onNewIntent függvényt processNotificationActionsmeghívásához.

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

    Jegyzet

    Mivel a MainActivity LaunchMode SingleTopértékre van állítva, a Szándék a meglévő Tevékenység példányhoz lesznek elküldve a onNe A-függvény helyett a függvényt, ezért a bejövő szándék kell kezelnie az onCreate és onNewIntent függvények .

  14. Bírálja felül a onCreate függvényt, állítsa a deviceInstallationService a DeviceInstallationServiceúj példányára.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        flutterEngine?.let {
            deviceInstallationService = DeviceInstallationService(context, it)
        }
    }
    
  15. Állítsa be a notificationActionService és notificationRegistrationService tulajdonságait PushNotificationFirebaseMessagingServices.

    flutterEngine?.let {
      deviceInstallationService = DeviceInstallationService(context, it)
      PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it)
      PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it)
    }
    
  16. Ugyanabban a függvényben feltételesen hívja meg FirebaseInstanceId.getInstance().instanceId. Implementálja az OnCompleteListener az eredményül kapott token értékének beállításához PushNotificationFirebaseMessagingService, mielőtt meghívja refreshRegistration.

    if(deviceInstallationService?.playServicesAvailable) {
        FirebaseInstanceId.getInstance().instanceId
            .addOnCompleteListener(OnCompleteListener { task ->
                if (!task.isSuccessful)
                    return@OnCompleteListener
    
                PushNotificationsFirebaseMessagingService.token = task.result?.token
                PushNotificationsFirebaseMessagingService.notificationRegistrationService?.refreshRegistration()
            })
    }
    
  17. Még mindig onCreate, hívja meg processNotificationActions a függvény végén. A launchAction argumentum igaz használatával jelezheti, hogy a művelet feldolgozása folyamatban van az alkalmazás indítása során.

    processNotificationActions(this.intent, true)
    

Jegyzet

A leküldéses értesítések fogadásához minden futtatáskor újra regisztrálnia kell az alkalmazást, és le kell állítania egy hibakeresési munkamenetből.

A natív iOS-projekt konfigurálása leküldéses értesítésekhez

A futó cél és az Info.plist konfigurálása

  1. Visual Studio CodeVezérlő + Kattintson a az ios mappára, majd válassza a Megnyitás Xcode-banlehetőséget.

  2. A Xcodekattintson Runner (a xcodeproj a tetején, nem a mappára), majd válassza ki a Runner cél, majd Aláírási & képességek. Ha a Minden buildkonfiguráció ki van választva, válassza ki a fejlesztői fiókját a Csapat. Győződjön meg arról, hogy az "Aláírás automatikus kezelése" beállítás be van jelölve, és az aláíró tanúsítvány és a kiépítési profil automatikusan be van jelölve.

    Jegyzet

    Ha nem látja az új kiépítési profil értékét, próbálja meg frissíteni az aláírási identitás profiljait a Xcode>Beállítások>Fiók beállítás kiválasztásával, majd válassza a Manuális profilok letöltése gombot a profilok letöltéséhez.

  3. Kattintson a + Képességelemre, majd keresse meg leküldéses értesítéseket. leküldéses értesítések dupla kattintással kattintson a a funkció hozzáadásához.

  4. Nyissa meg Info.plist, és állítsa Minimális rendszerverzió 13.0.

    Jegyzet

    Ebben az oktatóanyagban csak az iOS 13.0-s vagy újabb rendszerű eszközök támogatottak, de kiterjesztheti a régebbi verziókat futtató eszközökre.

  5. Nyissa meg Runner.entitlements, és győződjön meg arról, hogy az APS-környezet beállítása fejlesztési.

Leküldéses értesítések kezelése iOS rendszeren

  1. Vezérlő + Kattintson a a Futó mappára (a Runner projekten belül), majd válassza Új csoport a Szolgáltatások használatával.

  2. Vezérlő + Kattintson a a Szolgáltatások mappára, majd válassza Új fájl...lehetőséget. Ezután válassza Swift-fájl, majd kattintson a Továbbgombra. Adja meg a névhez DeviceInstallationService, majd kattintson a létrehozása gombra.

  3. Implementálja DeviceInstallationService.swift az alábbi kóddal.

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

    Jegyzet

    Ez az osztály a com.<your_organization>.pushdemo/deviceinstallation csatorna platformspecifikus megfelelőjét implementálja. Ezt az alkalmazás Flutter részében definiálták DeviceInstallationService.dart. Ebben az esetben a hívások a közös kódból a natív gazdagépre kerülnek. Mindenképpen cserélje le a <your_organization> a saját szervezetére, ahol ezt használja.

    Ez az osztály egyedi azonosítót biztosít (a UIDevice.identifierForVendor értékkel) az értesítési központ regisztrációs hasznos adatainak részeként.

  4. Vegyen fel egy másik Swift-fájl a Services nevű mappába NotificationRegistrationService, majd adja hozzá a következő kódot.

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

    Jegyzet

    Ez az osztály a com.<your_organization>.pushdemo/notificationregistration csatorna platformspecifikus megfelelőjét implementálja. Ezt az alkalmazás Flutter részében definiálták NotificationRegistrationService.dart. Ebben az esetben a hívások a natív gazdagépről a közös kódra kerülnek. Ügyeljen arra, hogy a <your_organization> a saját szervezetére cserélje, bárhol is használják.

  5. Vegyen fel egy másik Swift-fájl a Services nevű mappába NotificationActionService, majd adja hozzá a következő kódot.

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

    Jegyzet

    Ez az osztály a com.<your_organization>.pushdemo/notificationaction csatorna platformspecifikus megfelelőjét implementálja. Ezt az alkalmazás Flutter részében definiálták NotificationActionService.dart. Ebben az esetben mindkét irányban lehet hívást kezdeményezni. Mindenképpen cserélje le a <your_organization> a saját szervezetére, ahol ezt használja.

  6. Az AppDelegate.swiftadjon hozzá változókat a korábban létrehozott szolgáltatásokra mutató hivatkozás tárolásához.

    var deviceInstallationService : DeviceInstallationService?
    var notificationRegistrationService : NotificationRegistrationService?
    var notificationActionService : NotificationActionService?
    
  7. Adjon hozzá egy processNotificationActions nevű függvényt az értesítési adatok feldolgozásához. Feltételesen aktiválja a műveletet, vagy tárolja későbbi használatra, ha a műveletet az alkalmazás indításakor dolgozzák fel.

    func processNotificationActions(userInfo: [AnyHashable : Any], launchAction: Bool = false) {
        if let action = userInfo["action"] as? String {
            if (launchAction) {
                notificationActionService?.launchAction = action
            }
            else {
                notificationActionService?.triggerAction(action: action)
            }
        }
    }
    
  8. Bírálja felül a didRegisterForRemoteNotificationsWithDeviceToken függvényt, amely az DeviceInstallationServicetoken értékét állítja be. Ezután hívja meg refreshRegistration a NotificationRegistrationService.

    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
      deviceInstallationService?.token = deviceToken
      notificationRegistrationService?.refreshRegistration()
    }
    
  9. Felülbírálja a didReceiveRemoteNotification függvényt, amely átadja a userInfo argumentumot a processNotificationActions függvénynek.

    override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        processNotificationActions(userInfo: userInfo)
    }
    
  10. Bírálja felül a didFailToRegisterForRemoteNotificationsWithError függvényt a hiba naplózásához.

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

    Jegyzet

    Ez nagyon helyőrző. Az éles forgatókönyvekhez megfelelő naplózást és hibakezelést kell implementálnia.

  11. A didFinishLaunchingWithOptionsfájlban példányosíthatja a deviceInstallationService, notificationRegistrationServiceés notificationActionService változókat.

    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    
    deviceInstallationService = DeviceInstallationService(withBinaryMessenger: controller.binaryMessenger)
    notificationRegistrationService = NotificationRegistrationService(withBinaryMessenger: controller.binaryMessenger)
    notificationActionService = NotificationActionService(withBinaryMessenger: controller.binaryMessenger)
    
  12. Ugyanebben a függvényben feltételesen kérjen engedélyt, és regisztráljon távoli értesítésekre.

    if #available(iOS 13.0, *) {
      UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
          (granted, error) in
    
          if (granted)
          {
              DispatchQueue.main.async {
                  let pushSettings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
                  application.registerUserNotificationSettings(pushSettings)
                  application.registerForRemoteNotifications()
              }
          }
      }
    }
    
  13. Ha a launchOptions tartalmazza a remoteNotification kulcsot, hívja meg processNotificationActions a didFinishLaunchingWithOptions függvény végén. Adja át az eredményül kapott userInfo objektumot, és használja igaz a launchAction argumentumhoz. A igaz érték azt jelzi, hogy a művelet feldolgozása az alkalmazás indításakor történik.

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

A megoldás tesztelése

Mostantól tesztelheti az értesítések küldését a háttérszolgáltatáson keresztül.

Tesztértesítés küldése

  1. Nyisson meg egy új lapot Postman.

  2. Állítsa be a kérelmet a POST, és adja meg a következő címet:

    https://<app_name>.azurewebsites.net/api/notifications/requests
    
  3. Ha a Ügyfelek hitelesítése API-kulcs szakasz használatával történő hitelesítését választotta, mindenképpen konfigurálja a kérés fejléceit úgy, hogy az tartalmazza a apikey értékét.

    Kulcs Érték
    apikey <your_api_key>
  4. Válassza a Törzsnyers lehetőséget, majd a formátumbeállítások listájában válassza JSON, majd adjon meg néhány helyőrzőt JSON--tartalmat:

    {
        "text": "Message from Postman!",
        "action": "action_a"
    }
    
  5. Válassza a Kód gombot, amely az ablak jobb felső részén található Mentés gomb alatt található. A kérésnek a következő példához hasonlóan kell kinéznie, amikor HTML- jelenik meg (attól függően, hogy tartalmazott-e apikey fejlécet):

    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. Futtassa a PushDemo alkalmazást valamelyik vagy mindkét célplatformon (Android és iOS).

    Jegyzet

    Ha Android- tesztel, győződjön meg arról, hogy nem a hibakeresésifut, vagy ha az alkalmazást az alkalmazás futtatásával telepítette, akkor zárja be az alkalmazást, és indítsa újra a indítóból.

  7. A PushDemo alkalmazásban koppintson a Regisztrálás gombra.

  8. Vissza Postman, zárja be a Kódrészletek létrehozása ablakot (ha még nem tette meg), majd kattintson a Küldés gombra.

  9. Ellenőrizze, hogy 200 OK választ kap-e Postman, és a riasztás megjelenik az alkalmazásban, amely műveletérkezett.

  10. Zárja be a PushDemo alkalmazást, majd kattintson ismét a Küldés gombra Postman.

  11. Ellenőrizze, hogy 200 OK választ kap-e újra Postman. Ellenőrizze, hogy megjelenik-e értesítés a PushDemo alkalmazás értesítési területén a megfelelő üzenettel.

  12. Koppintson az értesítésre annak megerősítéséhez, hogy megnyitja az alkalmazást, és megjeleníti az riasztáshoz kapott ActionA-műveletet.

  13. Visszatérve Postman, módosítsa az előző kérelem törzsét úgy, hogy az művelet értékének action_a helyett csendes értesítést küldjön, amely action_b ad meg.

    {
        "action": "action_b",
        "silent": true
    }
    
  14. Ha az alkalmazás továbbra is nyitva van, kattintson a Küldés gombra Postman.

  15. Ellenőrizze, hogy 200 OK választ kap-e Postman, és hogy a riasztás megjelenik az alkalmazásban, amely MűveletA művelet helyett kapott ActionB-műveletet.

  16. Zárja be a PushDemo alkalmazást, majd kattintson ismét a Küldés gombra Postman.

  17. Ellenőrizze, hogy 200 OK választ kap-e Postman, és hogy a csendes értesítés nem jelenik meg az értesítési területen.

Hibaelhárítás

Nincs válasz a háttérszolgáltatástól

Helyi teszteléskor győződjön meg arról, hogy a háttérszolgáltatás fut, és a megfelelő portot használja.

Ha az Azure API Appteszteli, ellenőrizze, hogy a szolgáltatás fut-e, és üzembe lett helyezve, és hiba nélkül elindult-e.

Győződjön meg arról, hogy helyesen adta meg az alapcímet Postman vagy a mobilalkalmazás konfigurációjában az ügyfélen keresztüli teszteléskor. Az alapcímnek indikatív módon https://<api_name>.azurewebsites.net/ vagy https://localhost:5001/ kell lennie a helyi tesztelés során.

Hibakeresési munkamenet indítása vagy leállítása után nem érkezik értesítés Android rendszeren

Győződjön meg arról, hogy a hibakeresési munkamenet indítása vagy leállítása után újra regisztrál. A hibakereső létrehoz egy új Firebase--jogkivonatot. Az értesítési központ telepítését is frissíteni kell.

401 állapotkód fogadása a háttérszolgáltatástól

Ellenőrizze, hogy a apikey kérelemfejlécet állítja-e be, és ez az érték megegyezik a háttérszolgáltatáshoz konfigurált értékkel.

Ha ezt a hibát helyi teszteléskor kapja, győződjön meg arról, hogy az ügyfélkonfigurációban megadott kulcsérték megegyezik a Authentication:ApiKey felhasználóbeállítási értékkel, amelyet a APIhasznál.

Ha egy API-alkalmazástesztel, győződjön meg arról, hogy az ügyfélkonfigurációs fájl kulcsértéke megegyezik a Hitelesítés:ApiKey alkalmazásbeállítással, amelyet az API-alkalmazáshasznál.

Jegyzet

Ha ezt a beállítást a háttérszolgáltatás üzembe helyezése után hozta létre vagy módosította, a szolgáltatás érvénybe lépéséhez újra kell indítania a szolgáltatást.

Ha úgy döntött, hogy nem végzi el a Ügyfelek hitelesítése API-kulcs szakasz használatával, győződjön meg arról, hogy nem alkalmazta a Engedélyezés attribútumot a NotificationsController osztályra.

404-alapú állapotkód fogadása a háttérszolgáltatástól

Ellenőrizze, hogy a végpont és a HTTP-kérési módszer helyes-e. A végpontoknak például indikatív módon a következőnek kell lenniük:

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

Vagy helyi tesztelés esetén:

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

Az ügyfélalkalmazás alapcímének megadásakor győződjön meg arról, hogy az /végződik. Az alapcímnek indikatív módon https://<api_name>.azurewebsites.net/ vagy https://localhost:5001/ kell lennie a helyi tesztelés során.

Nem lehet regisztrálni, és megjelenik egy értesítési központ hibaüzenete

Ellenőrizze, hogy a teszteszköz rendelkezik-e hálózati kapcsolattal. Ezután a Http-válasz állapotkódjának meghatározásához állítson be egy töréspontot a HttpResponseStatusCode tulajdonságértékének vizsgálatához.

Tekintse át az előző hibaelhárítási javaslatokat, ahol lehetséges, az állapotkód alapján.

Állítson be egy töréspontot azokra a sorokra, amelyek az adott API adott állapotkódjait adják vissza. Ezután próbálja meg meghívni a háttérszolgáltatást helyi hibakereséskor.

Ellenőrizze, hogy a háttérszolgáltatás a várt módon működik-e Postman a megfelelő hasznos adatokkal. Használja a szóban forgó platform ügyfélkódja által létrehozott tényleges hasznos adatokat.

Tekintse át a platformspecifikus konfigurációs szakaszokat, hogy ne maradjon le a lépésekről. Ellenőrizze, hogy a megfelelő platform installation id és token változóihoz megfelelő értékek vannak-e feloldva.

Az eszközhöz tartozó azonosító nem oldható fel hibaüzenet jelenik meg

Tekintse át a platformspecifikus konfigurációs szakaszokat, hogy ne maradjon le a lépésekről.

Következő lépések

Most már rendelkeznie kell egy alapszintű Flutter-alkalmazással, amely egy háttérszolgáltatáson keresztül csatlakozik egy értesítési központhoz, és értesítéseket küldhet és fogadhat.

Az oktatóanyagban használt példát valószínűleg a saját forgatókönyvéhez kell igazítania. A robusztusabb hibakezelés, az újrapróbálkozási logika és a naplózás megvalósítása is ajánlott.

Visual Studio App Center gyorsan beépíthető a elemzési és diagnosztikai biztosító mobilalkalmazásokba, hogy segítsenek a hibaelhárításban.