Oktatóanyag: Leküldéses értesítések küldése Flutter-alkalmazásokba az Azure Notification Hubs használatával háttérszolgáltatáson keresztül
Ebben az oktatóanyagban az Azure Notification Hubs használatával küld leküldéses értesítéseket egy Androidot és iOS-t célzó Flutter-alkalmazásba.
A ASP.NET Core Webes API-háttérrendszer az ügyfél eszközregisztrációjának kezelésére szolgál 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.
Ezek a műveletek a Notification Hubs SDK-val kezelhetők a háttérműveletekhez. Az általános megközelítéssel kapcsolatos további részletekért tekintse meg a Regisztráció az alkalmazás háttérrendszeréből dokumentációt.
Ez az oktatóanyag végigvezeti az alábbi lépéseket:
- A leküldéses értesítési szolgáltatások és az Azure Notification Hubs beállítása.
- Hozzon létre egy ASP.NET Core Webes API háttéralkalmazást.
- Platformfüggetlen Flutter-alkalmazás létrehozása.
- Konfigurálja a natív Android-projektet leküldéses értesítésekhez.
- Konfigurálja a natív iOS-projektet leküldéses értesítésekhez.
- A megoldás teszteléséhez.
Előfeltételek
A lépések követéséhez a következőkre van szükség:
- Egy Azure-előfizetés ahol létrehozni és -erőforrások kezeléséhez.
- A Flutter eszközkészlet (az előfeltételekkel együtt).
- Visual Studio Code telepített Flutter és Dart beépülő modulokkal .
- A könyvtárfüggőségek kezelésére telepített CocoaPods .
- Az alkalmazás futtatásának lehetősége Android (fizikai vagy emulátor) vagy iOS rendszeren (csak fizikai eszközökön).
Android esetén a következőkre van szüksége:
- Egy fejlesztő feloldott egy fizikai eszközt vagy egy emulátort (az API 26-os vagy újabb verzióját futtatva, amelyen telepítve van a Google Play Services).
iOS esetén a következőkre van szükség:
- Az aktív Apple Developer-fiók.
- Egy fizikai iOS-eszköz, amely regisztrálva van a fejlesztői fiókjában(iOS 13.0-s vagy újabb rendszert futtat).
- A kulcskarikára telepített .p12fejlesztői tanúsítvány lehetővé teszi egy alkalmazás fizikai eszközön való futtatását.
Megjegyzés
Az iOS-szimulátor nem támogatja a távoli értesítéseket, ezért fizikai eszközre van szükség a minta iOS-en való vizsgálatához. Az oktatóanyag elvégzéséhez azonban nem kell futtatnia az alkalmazást Android és iOS rendszeren is.
Az első alapelveket tartalmazó példában szereplő lépéseket előzetes tapasztalat nélkül is követheti. Az alábbi szempontok ismerete azonban hasznos lehet.
- Apple Fejlesztői portál.
- ASP.NET Core.
- Google Firebase-konzol.
- Microsoft Azure és Leküldéses értesítések küldése iOS-alkalmazásokba az Azure Notification Hubs használatával.
- Flutter és Dart platformfüggetlen fejlesztéshez.
- Kotlin és Swift androidos és iOS-alapú natív fejlesztéshez.
A megadott lépések a macOS rendszerre vonatkoznak. Windows rendszeren aziOS-szempontok kihagyásával is követheti a lépéseket.
Leküldéses értesítési szolgáltatások és az Azure Notification Hub beállítása
Ebben a szakaszban a Firebase Cloud Messaging (FCM) és az Apple Push Notification Services (APNS) szolgáltatást állítja be. 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
Jelentkezzen be a Firebase-konzolra. Hozzon létre egy új Firebase-projektet, amely a PushDemo nevet adja meg projektnévként.
Megjegyzés
A rendszer létrehoz egy egyedi nevet. Alapértelmezés szerint ez a megadott név kisbetűs változata, valamint egy kötőjellel elválasztott generált számból áll. Ezt módosíthatja, ha szeretné, feltéve, hogy az továbbra is globálisan egyedi.
A projekt létrehozása után válassza a Firebase hozzáadása az Android-alkalmazáshoz lehetőséget.
Az Add Firebase to your Android app (Tűzbázis hozzáadása androidos alkalmazáshoz ) lapon hajtsa végre az alábbi lépéseket.
Az Android-csomag neveként adja meg a csomag nevét. Például:
com.<organization_identifier>.<package_name>
.Válassza az Alkalmazás regisztrálása lehetőséget.
Válassza a Letöltés google-services.json lehetőséget. Ezután mentse a fájlt egy helyi mappába későbbi használatra, és válassza a Tovább gombot.
Kattintson a Tovább gombra.
Válassza a Folytatás konzolra lehetőséget
Megjegyzés
Ha a Folytatás konzolra gomb nincs engedélyezve, a telepítés ellenőrzésének ellenőrzése miatt válassza a Lépés kihagyása lehetőséget.
A Firebase konzolon válassza ki a projekthez tartozó fogaskerék elemet. Ezután válassza a Projektbeállítások lehetőséget.
Megjegyzés
Ha még nem töltötte le a google-services.json fájlt, letöltheti erre a lapra.
Váltson a felső Cloud Messaging (Felhőbeli üzenetkezelés ) lapra. Másolja ki és mentse a Kiszolgálókulcsot későbbi használatra. Ezzel az értékkel konfigurálhatja az értesítési központot.
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 alkalmazását az Apple-ben, és regisztráljon leküldéses értesítésekre is.
Ha még nem regisztrálta az alkalmazást, keresse meg az iOS kiépítési portálját az Apple Fejlesztői központban. Jelentkezzen be a portálra az Apple ID azonosítójával, lépjen a Tanúsítványok, azonosítók & Profilok elemre, majd válassza az Azonosítók lehetőséget. Kattintson ide + egy új alkalmazás regisztrálásához.
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ás elemet.
Frissítse a következő három értéket az új alkalmazáshoz, majd válassza a Folytatás lehetőséget:
Leírás: Adjon meg egy leíró nevet az alkalmazásnak.
Csomagazonosító: Adja meg a com.organization_identifier<> űrlap csomagazonosítóját.<>product_name az alkalmazásterjesztési útmutatóban leírtak szerint. Az alábbi képernyőképen az
mobcat
érték szervezeti azonosítóként, a PushDemo érték pedig a terméknév.Leküldéses értesítések: Ellenőrizze a Leküldéses értesítések lehetőséget a Képességek szakaszban.
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ás, majd a Regisztráció lehetőséget az új alkalmazásazonosító megerősítéséhez.
Miután kiválasztotta a Regisztráció lehetőséget, az új alkalmazásazonosító sorelemként jelenik meg a Tanúsítványok, azonosítók & Profilok lapon.
A Tanúsítványok, azonosítók & Profilok lapon, az Azonosítók területen keresse meg a létrehozott Alkalmazásazonosító sorelemet. Ezután válassza ki a sorát 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 az Apple Push Notification Services (APNS) szolgáltatással, és kétféleképpen nyújtható:
P12 leküldéses tanúsítvány létrehozása, amely közvetlenül a Notification Hubra tölthető fel (az eredeti megközelítés)
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 dokumentált módon. 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éshez 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 a Notification Hubra tölthető fel
Mac gépen futtassa a Keychain Access eszközt. A Utilities mappából vagy a Launchpad Egyéb mappájából nyitható meg.
Válassza a Keychain Access lehetőséget, bontsa ki a Tanúsítványsegéd elemet, majd válassza a Tanúsítvány kérése hitelesítésszolgáltatótól lehetőséget.
Megjegyzés
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ó 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 az Apple Worldwide Developer Relations hitelesítésszolgáltatója kulcs van kiválasztva.
Válassza ki a felhasználó Email címét, adja meg a Common Name (Közös név) értéket, győződjön meg arról, hogy a Mentés lemezre lehetőséget adja meg, majd válassza a Folytatás lehetőséget. Hagyja üresen a hitelesítésszolgáltató Email Cím mezőt, mert nincs rá szükség.
Adja meg a Tanúsítvány-aláírási kérelem (CSR) fájl nevét a Mentés másként területen, válassza ki a helyet a Hol, majd válassza a Mentés lehetőséget.
Ez a művelet a CSR-fájlt a kiválasztott helyre menti. Az alapértelmezett hely az Asztal. Jegyezze meg a fájlhoz kiválasztott helyet.
Térjen vissza a Tanúsítványok, azonosítók & Profilok lapra az iOS kiépítési portálon, görgessen le a leküldéses értesítések jelölőnégyzethez, majd válassza a Konfigurálás lehetőséget a tanúsítvány létrehozásához.
Megjelenik az Apple Leküldéses értesítési szolgáltatás TLS/SSL-tanúsítványok ablaka . Válassza a Tanúsítvány létrehozása gombot a Fejlesztési TLS/SSL-tanúsítvány szakaszban.
Megjelenik az Új tanúsítvány létrehozása képernyő.
Megjegyzés
Ez az oktatóanyag fejlesztési tanúsítványt használ. Ugyanezt a folyamatot használja az é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.
Válassza a Fájl kiválasztása lehetőséget, keresse meg azt a helyet, ahová a CSR-fájlt mentette, majd kattintson duplán a tanúsítvány nevére a betöltéséhez. Ezután válassza a Folytatás elemet.
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.
A rendszer letölti és menti a tanúsítványt a számítógépre a Letöltések mappában.
Megjegyzés
Alapértelmezés szerint a letöltött fejlesztési tanúsítvány neve aps_development.cer.
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, az alábbi képen látható módon:
Megjegyzés
Bár a tanúsítványban szereplő név eltérő lehet, a név az Apple Development iOS Push Services előtaggal lesz ellátva, és hozzá lesz rendelve a megfelelő csomagazonosító.
A Kulcskarika-hozzáférés területen + kattintson a Tanúsítványok kategóriában létrehozott új leküldéses tanúsítványra . Válassza az Exportálás lehetőséget, nevezze el a fájlt, válassza ki a p12 formátumot, majd válassza a Mentés lehetőséget.
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 az OK gombra . Jegyezze fel az exportált p12-tanúsítvány fájlnevét és helyét. Az APN-ekkel történő hitelesítés engedélyezésére szolgálnak.
Megjegyzés
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
Jegyezze fel a következő részleteket:
- Alkalmazásazonosító előtag (csapatazonosító)
- Csomagazonosító
A Tanúsítványok, azonosítók & profilok területen kattintson a Kulcsok elemre.
Megjegyzés
Ha már rendelkezik az APNS-hez konfigurált kulccsal, használhatja újra 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 a 3 – 5. lépést.
Kattintson a + gombra (vagy a Kulcs létrehozása gombra) egy új kulcs létrehozásához.
Adjon meg egy megfelelő Kulcsnév értéket, majd ellenőrizze az Apple Push Notifications szolgáltatás (APNS) beállítását, majd kattintson a Folytatás, majd a Regisztráció elemre a következő képernyőn.
Kattintson a Letöltés gombra, majd helyezze át a p8 fájlt ( AuthKey_ előtaggal) egy biztonságos helyi könyvtárba, majd kattintson a Kész gombra.
Megjegyzés
Ügyeljen arra, hogy a p8-fájl biztonságos helyen legyen (és mentsen egy 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.
A Kulcsok területen kattintson a létrehozott kulcsra (vagy egy meglévő kulcsra, ha ezt választotta).
Jegyezze fel a Kulcsazonosító értéket.
Nyissa meg a p8-tanúsítványt egy tetszőleges alkalmazásban, például a Visual Studio Code-ban. Jegyezze fel a kulcs értékét ( -----BEGIN PRIVATE KEY----- és -----END PRIVATE KEY----- között).
-----BEGIN PRIVATE KEY-----
<key_value>
-----END PRIVATE KEY-----Megjegyzés
Ez az a tokenérték , amelyet később a Notification Hub konfigurálásához használunk.
Ezeknek a lépéseknek a végén a következő információkkal kell rendelkeznie, amelyeket később használhat az Értesítési központ konfigurálása APNS-adatokkal című cikkben:
- Csapatazonosító (lásd: 1. lépés)
- Csomagazonosító (lásd: 1. lépés)
- Kulcsazonosító (lásd a 7. lépést)
- Jogkivonat értéke (a 8. lépésben kapott p8 kulcsérték)
Üzembe helyezési profil létrehozása az alkalmazáshoz
Térjen vissza az iOS kiépítési portálra, válassza a Tanúsítványok, azonosítók & Profilok lehetőséget, válassza a profilok lehetőséget a bal oldali menüben, majd válasszon + új profil létrehozásához. Megjelenik az Új kiépítési profil regisztrálása képernyő.
A kiépítési profil típusaként válassza az iOS-alkalmazásfejlesztés lehetőséget a Fejlesztés területen, majd válassza a Folytatás lehetőséget.
Ezután válassza ki a létrehozott alkalmazásazonosítót az Alkalmazásazonosító legördülő listából, majd válassza a Folytatás lehetőséget.
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ás lehetőséget.
Megjegyzés
Ez a tanúsítvány nem az előző lépésben létrehozott leküldéses tanúsítvány. Ez az Ön 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 Fejlesztői portálon, az Xcode-on vagy a Visual Studióban hozhatók létre.
Térjen vissza a Tanúsítványok, azonosítók & Profilok lapra, válassza a Profilok lehetőséget a bal oldali menüből, majd válassza ki + az új profil létrehozásához. Megjelenik az Új kiépítési profil regisztrálása képernyő.
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ás elemet.
Ezután válassza ki a teszteléshez használni kívánt eszközöket, majd válassza a Folytatás lehetőséget.
Végül válassza ki a profil nevét a Kiépítési profil neve területen, majd válassza a Létrehozás lehetőséget.
Az új kiépítési profil létrehozásakor válassza a Letöltés lehetőséget. Jegyezze meg a mentés helyét.
Keresse meg a kiépítési profil helyét, majd kattintson rá duplán a fejlesztő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 az APNS használatával. P12 leküldéses tanúsítványt vagy jogkivonat-alapú hitelesítést is használhat. Ha egy már létrehozott értesítési központot szeretne használni, ugorjon az 5. lépésre.
Jelentkezzen be az Azure-ba.
Kattintson az Erőforrás létrehozása elemre, keresse meg és válassza az Értesítési központ lehetőséget, majd kattintson a Létrehozás gombra.
Frissítse a következő mezőket, majd kattintson a Létrehozás gombra:
ALAPSZINTŰ RÉSZLETEK
Előfizetés: Válassza ki a cél-előfizetést a legördülő listából
Erőforráscsoport: Új erőforráscsoport létrehozása (vagy meglévő kiválasztása)NÉVTÉR RÉSZLETEI
Notification Hub-névtér: Adjon meg egy globálisan egyedi nevet a Notification Hub névteréhez
Megjegyzés
Győződjön meg arról, hogy az Új létrehozása lehetőség van kiválasztva ehhez a mezőhöz.
ÉRTESÍTÉSI KÖZPONT ADATAI
Értesítési központ: Adja meg a Notification Hub nevét
Helyen: Válasszon egy megfelelő helyet a legördülő listából
Tarifacsomag: Az alapértelmezett ingyenes beállítás megtartásaMegjegyzés
Hacsak nem érte el az ingyenes szinten található központok maximális számát.
A Notification Hub kiépítése után keresse meg az erőforrást.
Lépjen az új Értesítési központra.
Válassza a Hozzáférési szabályzatok elemet a listából (a KEZELÉS területen).
Jegyezze fel a Szabályzatnév értékeket a hozzájuk tartozó kapcsolati sztringértékekkel együtt.
A Notification Hub konfigurálása APNS-adatokkal
A Notification Services (Értesítési szolgáltatások) területen válassza az Apple lehetőséget, majd kövesse a megfelelő lépéseket az Értesítési központok tanúsítványának létrehozása szakaszban korábban kiválasztott megközelítés alapján.
Megjegyzés
Csak akkor használja az Alkalmazáshoz készült élesüzemmódot , 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
Válassza a Tanúsítvány elemet.
Válassza a fájl ikont.
Jelölje ki a korábban exportált .p12 fájlt, majd válassza a Megnyitás lehetőséget.
Szükség esetén adja meg a megfelelő jelszót.
Válassza a Védőfal módot.
Kattintson a Mentés gombra.
2. LEHETŐSÉG: Jogkivonatalapú hitelesítés használata
Válassza a Jogkivonat lehetőséget.
Adja meg a korábban beszerzett alábbi értékeket:
- Kulcsazonosító
- Csomagazonosító
- Csapatazonosító
- Token
Válassza a Tesztkörnyezet lehetőséget.
Kattintson a Mentés gombra.
Az értesítési központ konfigurálása FCM-adatokkal
- A bal oldali menü Beállítások szakaszában válassza a Google (GCM/FCM) lehetőséget.
- Adja meg a Google Firebase-konzolról feljegyzett kiszolgálókulcsot.
- Válassza az eszköztár Save (Mentés) elemét.
ASP.NET Core Webes API háttéralkalmazás létrehozása
Ebben a szakaszban a ASP.NET Core Webes API-háttérrendszert hozza létre az eszközregisztráció és az értesítések Flutter mobilalkalmazásba való küldéséhez.
Webes projekt létrehozása
A Visual Studióban válassza a Fájl>új megoldás lehetőséget.
Válassza a .NETCore-alkalmazás>>ASP.NET Core>API>Tovább lehetőséget.
Az új ASP.NET Core Webes API konfigurálása párbeszédpanelen válassza a .NET Core 3.1cél keretrendszerét.
Írja be a PushDemoApi nevet a projektnévhez , majd válassza a Létrehozás lehetőséget.
Indítsa el a hibakeresést (Command + Enter) a sablonalapú alkalmazás teszteléséhez.
Megjegyzés
A sablonalapú alkalmazás úgy van konfigurálva, hogy a WeatherForecastControllerthasználja launchUrlként. Ez a Tulajdonságok>launchSettings.json van beállítva.
Ha a rendszer érvénytelen fejlesztési tanúsítványt talált üzenettel kéri:
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 adja meg a tanúsítvány jelszavát és a kulcskarika jelszavát.
Kattintson az Igen gombra, amikor a rendszer az új tanúsítvány telepítésére és megbízhatóságára kéri, majd adja meg a kulcskarika jelszavát.
Bontsa ki a Controllers mappát, majd törölje WeatherForecastController.cs.
Törölje WeatherForecast.cs.
Állítson be helyi konfigurációs értékeket a Secret Manager eszközzel. A titkos kódok megoldástól való leválasztása biztosítja, hogy ne kerülnek a forráskontrollba. Nyissa meg a Terminált , 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 karakterlánc értékeire. Ezeket az értesítési központ létrehozása szakaszban jegyezte fel. Ellenkező esetben megkeresheti őket az Azure-ban.
NotificationHub:Name:
Lásd: Név az Áttekintés tetején található Essentials-összefoglalásban.NotificationHub:ConnectionString:
Lásd: DefaultFullSharedAccessSignature in Access PoliciesMegjegyzés
Éles forgatókönyvek esetén olyan lehetőségeket tekinthet meg, mint az Azure KeyVault a kapcsolati karakterlánc biztonságos tárolásához. Az egyszerűség kedvéért a titkos kulcsok hozzá lesznek adva a 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 tokenek, de elegendőek az oktatóanyag céljaira. Az API-kulcsok egyszerűen konfigurálhatók a ASP.NET Köztes szoftveren keresztül.
Adja hozzá az API-kulcsot a helyi konfigurációs értékekhez.
dotnet user-secrets set "Authentication:ApiKey" <value>
Megjegyzés
Cserélje le a helyőrző értékét a sajátjára, és jegyezze fel.
Ellenőrzés + Kattintson a PushDemoApi projektre, válassza az Új mappa lehetőséget a Hozzáadás menüben, majd kattintson a Hozzáadás hitelesítésselmappanévként elemre.
Ellenőrzés + Kattintson a Hitelesítés mappára, majd válassza az Új fájl... lehetőséget a Hozzáadás menüben.
Válassza az Általános>üres osztály lehetőséget , írja be ApiKeyAuthOptions.cs a Név mezőbe, majd kattintson az Új gombra, és adja hozzá a következő implementációt.
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; } } }
Adjon hozzá egy másik üres osztályt a ApiKeyAuthHandler.cs nevű hitelesítési mappához, 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)); } } }
Megjegyzés
A Hitelesítési kezelő egy olyan típus, amely implementálja egy séma viselkedését, ebben az esetben egy egyéni API-kulcsséma.
Adjon hozzá egy másik üres osztályt a ApiKeyAuthenticationBuilderExtensions.cs nevű hitelesítési mappához, 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); } } }
Megjegyzés
Ez a bővítménymetódus leegyszerűsíti a köztes szoftver konfigurációs kódját a Startup.cs így olvashatóbbá és általában könnyebben követhetővé teszi.
A Startup.cs frissítse a ConfigureServices metódust, hogy konfigurálja az API-kulcs hitelesítését 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); }
Továbbra is Startup.cs frissítse a Configure metódust, hogy meghívja a UseAuthentication és a UseAuthorization bővítmény metódust az alkalmazás IApplicationBuilderjén. Győződjön meg arról, hogy ezek a metódusok a UseRouting és az 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(); }); }
Megjegyzés
A UseAuthentication hívása regisztrálja a korábban regisztrált hitelesítési sémákat használó köztes szoftvereket (a ConfigureServicesből). 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ási (DI) szoftvertervezési mintát, amely az osztályok és függőségeik közötti vezérlés inverziójának (IoC) elérésére szolgáló technika.
Az értesítési központ és a Notification Hubs SDK háttérműveletekhez való használata egy szolgáltatásba van beágyazva. A szolgáltatás regisztrálva van, és megfelelő absztrakción keresztül érhető el.
Ellenőrzés + Kattintson a Függőségek mappára, majd válassza a NuGet-csomagok kezelése... lehetőséget.
Keressen rá a Microsoft.Azure.NotificationHubs kifejezésre , és győződjön meg arról, hogy ellenőrizve van.
Kattintson a Csomagok hozzáadása, majd az Elfogadás gombra, amikor a rendszer a licencfeltételek elfogadására kéri.
Ellenőrzés + Kattintson a PushDemoApi projektre, válassza az Új mappa lehetőséget a Hozzáadás menüben, majd kattintson a Hozzáadásmodellek használatával mappanévként elemre.
Ellenőrzés + Kattintson a Modellek mappára, majd válassza az Új fájl... lehetőséget a Hozzáadás menüben.
Válassza az Általános>üres osztály lehetőséget, adja meg a név PushTemplates.cs, majd kattintson az Új gombra az alábbi implementáció hozzáadása gombra.
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)\" }"; } } }
Megjegyzés
Ez az osztály az ebben a forgatókönyvben megkövetelt általános és csendes értesítések jogkivonatos értesítési hasznos adatait tartalmazza. A hasznos adatok a telepítésen kívül vannak definiálva, hogy lehetővé tegyék a kísérletezést anélkül, hogy a szolgáltatáson keresztül frissíteni kellene a meglévő telepítéseket. 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 az egyéni sablonokat.
Vegyen fel egy másik Üres osztályt a Modellek mappába 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>(); } }
Vegyen fel egy másik Üres osztályt a Models (Modellek ) mappába 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; } } }
Vegyen fel egy másik Üres osztályt a Models (Modellek ) 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; } } }
Adjon hozzá egy új mappát a Szolgáltatások nevű PushDemoApi projekthez.
Adjon hozzá egy üres felületet a INotificationService.cs nevű Services mappához, 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); } }
Adjon hozzá egy üres osztályt a NotificationHubsService.cs nevű 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); } } }
Megjegyzés
A SendTemplateNotificationAsync számára megadott címkekifejezés legfeljebb 20 címke lehet. A legtöbb operátor esetében 6-ra van korlátozva, de a kifejezés ebben az esetben csak ARS-eket (||) tartalmaz. 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.
A Startup.cs frissítse a ConfigureServices metódust, hogy az INotificationService egyetlentonos implementációjaként adja hozzá a NotificationHubsService-t.
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ések API létrehozása
Ellenőrzés + Kattintson a Vezérlők mappára, majd válassza az Új fájl... lehetőséget a Hozzáadás menüben.
Válassza a ASP.NET Core>Web API Controller Class (Api-vezérlőosztály) lehetőséget, írja be a Név mezőben a NotificationsController kifejezést, majd kattintson az Új gombra.
Megjegyzés
Ha a Visual Studio 2019-et használja, válassza ki az OLVASÁSI/írási műveleteket tartalmazó API-vezérlőt .
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;
Frissítse a sablonos vezérlőt úgy, hogy a ControllerBase-ből származik, és az ApiController attribútummal van díszítve.
[ApiController] [Route("api/[controller]")] public class NotificationsController : ControllerBase { // Templated methods here }
Megjegyzés
A Controller alaposztály támogatja a nézeteket, de erre ebben az esetben nincs szükség, ezért a ControllerBase használható helyette. Ha a Visual Studio 2019-et követi, kihagyhatja ezt a lépést.
Ha úgy döntött, hogy befejezi az ügyfelek hitelesítése API-kulcs használatával szakaszt , akkor az NotificationsControllert is az Engedélyezés attribútummal kell díszítenie.
[Authorize]
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; }
A launchSettings.json -ben (a Tulajdonságok mappában) módosítsa a launchUrl értéket api/notifications értékre
weatherforecast
, hogy megfeleljen a RegistrationsControllerRoute attribútumban megadott URL-címnek.Indítsa el a hibakeresést (Command + Enter) annak ellenőrzéséhez, hogy az alkalmazás működik-e az új NotificationsControllerrel , és 401 Jogosulatlan állapotot ad vissza.
Megjegyzés
Előfordulhat, hogy a Visual Studio nem indítja el automatikusan az alkalmazást a böngészőben. Mostantól a Postman használatával tesztelheti az API-t.
Egy új Postman lapon állítsa a kérést GET értékre. Írja be az alábbi címet a helyőrző <applicationUrl> helyett a Tulajdonságok>launchSettings.json található https applicationUrl értékre.
<applicationUrl>/api/notifications
Megjegyzés
Az applicationUrl értékének az alapértelmezett profilhoz "https://localhost:5001" értéknek kell lennie. Ha IIS-t használ (windowsos Visual Studio 2019-ben alapértelmezés szerint), az iisSettings elemben megadott applicationUrl parancsot kell használnia. Ha a cím helytelen, 404-et kap.
Ha úgy döntött, hogy befejezi az ügyfelek hitelesítése API-kulcs használatával szakaszt , mindenképpen konfigurálja a kérésfejléceket úgy, hogy az tartalmazza az apikey értékét.
Kulcs Value apikey <your_api_key> Kattintson a Küldés gombra.
Megjegyzés
200 OK állapotúnak kell lennie néhány JSON-tartalommal.
Ha SSL-tanúsítvány-ellenőrzési figyelmeztetést kap, a beállítások között kikapcsolhatja az SSL-tanúsítvány-ellenőrzés Postman kérését.
Cserélje le a NotificationsController.cs sablonalapú osztálymetszeté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ásta Azure App Service a háttérszolgáltatás üzemeltetéséhez.
Jelentkezzen be az Azure Portalra.
Kattintson az Erőforrás létrehozása elemre, keresse meg és válassza az API-alkalmazás lehetőséget, majd kattintson a Létrehozás gombra.
Frissítse a következő mezőket, majd kattintson a Létrehozás gombra.
Alkalmazás neve:
Adja meg az API-alkalmazás globálisan egyedi nevétElőfizetés:
Válassza ki ugyanazt a cél-előfizetést , amelyben létrehozta az értesítési központot.Erőforráscsoport:
Válassza ki ugyanazt az erőforráscsoportot , amelyben létrehozta az értesítési központot.App Service csomag/hely:
Új App Service-csomag létrehozásaMegjegyzés
Váltson az alapértelmezett beállításról az SSL-támogatást tartalmazó csomagra. Ellenkező esetben meg kell tennie a megfelelő lépéseket, amikor a mobilalkalmazással dolgozik, hogy megakadályozza a HTTP-kérések 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 ki egy meglévő erőforrást.Az API-alkalmazás kiépítése után keresse meg az erőforrást.
Jegyezze fel az URL-tulajdonságot az Áttekintés tetején található Essentials-összefoglalásban. Ez az URL-cím a háttérbeli végpont , amelyet az oktatóanyag későbbi részében fogunk használni.
Megjegyzés
Az URL-cím a korábban megadott API-alkalmazásnevet használja a formátummal
https://<app_name>.azurewebsites.net
.Válassza a Konfiguráció lehetőséget a listából (a Beállítások területen).
Az alábbi beállítások mindegyikéhez kattintson az Új alkalmazásbeállítás elemre a Név és az Érték megadásához, majd kattintson az OK gombra.
Name (Név) Value Authentication:ApiKey
<api_key_value> NotificationHub:Name
<hub_name_value> NotificationHub:ConnectionString
<hub_connection_string_value> Megjegyzés
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 használatával szakaszt választotta. Éles forgatókönyvek esetén olyan lehetőségeket tekinthet meg, mint az Azure KeyVault. Ezek az egyszerűség kedvéért alkalmazásbeállításokként lettek hozzáadva ebben az esetben.
Az összes alkalmazásbeállítás hozzáadása után kattintson a Mentés, majd a Folytatás gombra.
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.
Megjegyzés
Az alábbi lépések a Visual Studio for Mac vonatkoznak. Ha windowsos Visual Studio 2019-et követ, a közzétételi folyamat eltérő lesz. Lásd: Közzététel Azure App Service Windows rendszeren.
Ha még nem tette meg, módosítsa a konfigurációt HibakeresésrőlKiadásra .
Ellenőrzés + Kattintson a PushDemoApi projektre, majd válassza a Közzététel az Azure-ban... lehetőséget a Közzététel menüben.
Kövesse a hitelesítési folyamatot, ha a rendszer erre kéri. Használja az előző létrehozási API-alkalmazás szakaszban használt fiókot.
Jelölje ki a közzétételi célként korábban létrehozott Azure App Service API-alkalmazást a listából, majd kattintson a Közzététel gombra.
A varázsló befejezése után közzéteszi az alkalmazást az Azure-ban, majd megnyitja az alkalmazást. Jegyezze fel az URL-címet , ha még nem tette meg. Ez az URL-cím az oktatóanyag későbbi részében használt háttérbeli végpont .
A közzétett API ellenőrzése
A Postmanben nyisson meg egy új lapot, állítsa a kérést PUT értékre , és adja meg az alábbi címet. Cserélje le a helyőrzőt az előző közzétételi háttérszolgáltatás szakaszában jegyzett alapcímre.
https://<app_name>.azurewebsites.net/api/notifications/installations
Megjegyzés
Az alapcím formátuma
https://<app_name>.azurewebsites.net/
Ha úgy döntött, hogy befejezi az ügyfelek hitelesítése API-kulcs használatával szakaszt , mindenképpen konfigurálja a kérésfejléceket úgy, hogy az tartalmazza az apikey értékét.
Kulcs Value apikey <your_api_key> Válassza ki a törzs nyers beállítását, majd a formátumbeállítások listájában válassza a JSON lehetőséget, majd adjon meg néhány helyőrző JSON-tartalmat:
{}
Kattintson a küldése.
Megjegyzés
422 UnprocessableEntity állapotot kell kapnia a szolgáltatástól.
Végezze el ismét az 1–4. lépést, de ezúttal adja meg a kérések végpontot annak ellenőrzéséhez, hogy 400 hibás kérésre adott válasz érkezik-e.
https://<app_name>.azurewebsites.net/api/notifications/requests
Megjegyzés
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, ha egy művelet meg van adva, és az alkalmazás az előtérben van. Ellenkező esetben az értesítések megjelennek az Értesítési központban.
Megjegyzés
A regisztrációs (és deregisztrációs) műveleteket általában az alkalmazás életciklusának megfelelő pontján (vagy az első futtatási folyamat részeként) 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 megvizsgálható és tesztelhető legyen.
A Flutter-megoldás létrehozása
Nyisson meg egy új Visual Studio Code-példányt.
Nyissa meg a parancskatalógust (Shift + Command + P).
Válassza a Flutter: New Project parancsot, majd nyomja le az Enter billentyűt.
Adja meg push_demo a Projekt neve mezőben, majd válasszon ki egy projekthelyet.
Amikor a rendszer erre kéri, válassza a Csomagok lekérése lehetőséget.
Ellenőrzés + Kattintson a kotlin mappára (az app>src>main területén), majd válassza a Feltárás a Finderben lehetőséget. Ezután nevezze át a gyermekmappát (a kotlin mappa alatt) a következőre:
com
,<your_organization>
, éspushdemo
.Megjegyzés
A Visual Studio Code sablon használatakor ezek a mappák alapértelmezés szerint com-ra vannak kapcsolva, <például project_name>. Feltételezve, hogy a mobcat a szervezethez van használva, a mappastruktúra indikatív módon jelenik meg:
- kotlin
- Com
- mobcat
- pushdemo
- mobcat
- Com
- kotlin
A Visual Studio Code-ban frissítse az applicationId értéket az androidos>alkalmazás>build.gradle fájljában a következőre:
com.<your_organization>.pushdemo
.Megjegyzés
A your_organization> helyőrzőhöz< saját szervezetnevet kell használnia. Ha például a mobcatet használja a szervezetként, az a com.mobcat.pushdemocsomagnév-értékét eredményezi.
Frissítse a csomagattribútumot a AndroidManifest.xml fájlokban, az src>hibakeresés, az src>main és az src>profil alatt. Győződjön meg arról, hogy az értékek megegyeznek az előző lépésben használt applicationId azonosítóval .
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.<your_organization>.pushdemo>"> ... </manifest>
Frissítse az attribútumot a
android:label
AndroidManifest.xmlfájlban az src>main alatt a PushDemo fájlra. Ezután adja hozzá az attribútumot közvetlenül aandroid:allowBackup
alattandroid:label
, és állítsa az értékét hamis értékre.<application android:name="io.flutter.app.FlutterApplication" android:label="PushDemo" android:allowBackup="false" android:icon="@mipmap/ic_launcher"> ... </application>
Nyissa meg az alkalmazásszintű build.gradle fájlt (android>app>build.gradle), majd frissítse a compileSdkVersion fájlt (az android szakaszból) az API 29 használatára. Ezután frissítse a minSdkVersion és a targetSdkVersion értékeket (a defaultConfig szakaszból) a 26-os és a 29-es értékre.
Megjegyzés
Ebben az oktatóanyagban csak a 26. és újabb SZINTŰ API-t futtató eszközök támogatottak, de kiterjesztheti a régebbi verziókat futtató eszközökre.
Ellenőrzés + Kattintson az ios mappára, majd válassza a Megnyitás Xcode-ban lehetőséget.
Az Xcode-ban kattintson a Runner (a felső xcodeproj elemre, nem a mappára). Ezután válassza ki a Futó célt, és válassza az Általános lapot. Ha a Minden build konfiguráció van kiválasztva, frissítse a Csomagazonosítót a értékre
com.<your_organization>.PushDemo
.Megjegyzés
A your_organization> helyőrzőhöz< saját szervezetnevet kell használnia. Ha például a mobcatet használja a szervezetként, az a com.mobcat.PushDemocsomagazonosító-értékét eredményezi.
Kattintson az Info.plist elemre, majd frissítse a Csomagnév értékét PushDemo értékre
Zárja be az Xcode-ot , és térjen vissza a Visual Studio Code-hoz.
A Visual Studio Code-ban nyissa meg a pubspec.yaml fájlt, és 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 elemre, amikor a rendszer erre kéri.
dependencies: flutter: sdk: flutter http: ^0.12.1 flutter_secure_storage: ^3.3.3
A Terminálban módosítsa a könyvtárat az ios mappára (a Flutter-projekthez). Ezután futtassa a pod telepítési parancsát az új podok telepítéséhez (amelyet a flutter_secure_storage csomag igényel).
Ellenőrzés + Kattintson a lib mappára, majd válassza az Új fájl lehetőséget a menüben a main_page.dart fájlnévvel. 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>[], ) ) ); } }
A main.dart fájlban cserélje le a sablonozott kó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));
A Terminálban hozza létre és futtassa az alkalmazást az egyes célplatformokon a sablonalapú alkalmazás futtatásának teszteléséhez az eszközön(ok)on. 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
Ellenőrzés + Kattintson a lib mappára, majd válassza az Új mappa lehetőséget a menüben , és használja a modelleketmappanévként.
Ellenőrzés + Kattintson a Models (Modellek ) mappára, majd válassza az Új fájl lehetőséget a menüben a device_installation.dart fájlnévvel. 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, }; }
Adjon hozzá egy új fájlt a push_demo_action.dart nevű modellmappához, amely meghatározza az ebben a példában támogatott műveletek felsorolását.
enum PushDemoAction { actionA, actionB, }
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); } }
Megjegyzés
A your_organization> helyőrzőhöz< saját szervezetnevet kell használnia. Ha például a mobcatet használja a szervezetként, az a com.mobcat.pushdemo/deviceinstallationMethodChannel nevé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 részleteket. A MethodChannel kétirányú aszinkron kommunikációt tesz lehetővé a mögöttes natív platformokkal. A csatorna platformspecifikus megfelelője a későbbi lépésekben jön létre.
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; } } }
Megjegyzés
Ez egy egyszerű mechanizmus, amellyel központosíthatja az értesítési műveletek kezelését, így azok platformfüggetlen módon kezelhetők egy erősen gépelt enumerálással. A szolgáltatás lehetővé teszi, hogy a mögöttes natív platform aktiváljon egy műveletet, ha meg van adva az értesítés hasznos adatai között. Emellett lehetővé teszi, hogy a közös kód visszamenőlegesen ellenőrizze, hogy egy művelet meg lett-e adva az alkalmazás indításakor, amint a Flutter készen áll a feldolgozásra. Ha például az alkalmazást az értesítési központ értesítésére koppintva indítja el.
Adjon hozzá egy új fájlt a notification_registration_service.dart nevű szolgáltatási 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; } } }
Megjegyzés
Ez az osztály a DeviceInstallationService használatát és a háttérszolgáltatásnak küldött 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 az Ügyfelek hitelesítése API-kulcs használatával szakaszt választotta.
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"; }
Megjegyzés
Ez egy egyszerű módszer az alkalmazás titkos kulcsának meghatározására. Cserélje le a helyőrző értékeket a saját értékére. Ezeket fel kellett volna jegyeznie a háttérszolgáltatás létrehozásakor. Az API-alkalmazás URL-címének a következőnek kell lennie
https://<api_app_name>.azurewebsites.net/
: . Az apiKey-tag csak akkor szükséges, ha az Ügyfelek hitelesítése API-kulcs használatával szakaszt választotta.Ügyeljen arra, hogy ezt hozzáadja a gitignore-fájlhoz, hogy ne véglegesítse ezeket a titkos kódokat a verziókövetésben.
A platformfüggetlen felhasználói felület implementálása
A main_page.dart fájlban cserélje le a buildfü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, ), ], ), ), ); }
Adja hozzá a szükséges importálásokat a main_page.dart fájl elejéhez .
import 'package:push_demo/services/notification_registration_service.dart'; import 'config.dart';
Adjon hozzá egy mezőt a _MainPageState osztályhoz a NotificationRegistrationService hivatkozásának tárolásához.
final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
A _MainPageState osztályban implementálja a Regisztráció és regisztráció törlése gomb eseménykezelőit a Megnyomott eseményeken . Hívja meg a megfelelő Register/Deregister metódusokat, majd jelenítsen meg egy riasztást az eredmény jelzéséhez.
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(); }, ), ], ); }, ); }
Most a main.dart fájlban 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';
Deklaráljon egy változót a NotificationActionService egy példányára való hivatkozás tárolásához és inicializálásához.
final notificationActionService = NotificationActionService();
Függvények hozzáadása egy művelet aktiválásakor megjelenő riasztások megjeleníté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(); }, ), ], ); }, ); }
Frissítse a fő függvényt a NotificationActionServiceactionTriggered stream figyeléséhez, és ellenőrizze, hogy vannak-e az alkalmazás indításakor rögzített műveletek.
void main() async { runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey,)); notificationActionService.actionTriggered.listen((event) { notificationActionTriggered(event as PushDemoAction); }); await notificationActionService.checkLaunchAction(); }
Megjegyzés
Ez egyszerűen a leküldéses értesítési műveletek fogadásának és propagálásának szemléltetésére való. Ezeket általában csendesen kezelik, például egy adott nézetre navigálnak, vagy bizonyos adatokat frissítenek, nem pedig riasztást jelenítenek 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
Ellenőrzés + Kattintson az android mappára, majd válassza a Megnyitás az Android Studióban lehetőséget. Ezután váltson a Project nézetre (ha még nem tette meg).
Keresse meg azt a google-services.json fájlt, amely a PushDemo-projektFirebase-konzolon való beállításakor korábban letöltött. Ezután húzza az alkalmazásmodul gyökérkönyvtárába (androidos>androidos>alkalmazás).
Összeállítási beállítások és engedélyek konfigurálása
Váltson a Project nézetre Androidra.
Nyissa meg AndroidManifest.xml, majd adja hozzá az INTERNET és READ_PHONE_STATE engedélyeket az alkalmazáselem 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
Az Android Studióban nyissa meg a projektszintű build.gradle fájlt (Gradle Scripts>build.gradle (Project: android)). és győződjön meg arról, hogy a "com.google.gms:google-services" osztályútvonal szerepel 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 // ... } }
Megjegyzés
Győződjön meg arról, hogy az Android-projekt létrehozásakor a Firebase-konzol utasításainak megfelelően a legújabb verzióra hivatkozik.
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 android-csomópont felett.
// ... // Add the following line: apply plugin: 'com.google.gms.google-services' // Google Services plugin android { // ... }
Ugyanebben a fájlban, a dependencies 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' }
Megjegyzés
Győződjön meg arról, hogy a Cloud Messaging Android ügyféldokumentációjának megfelelően a legújabb verzióra hivatkozik.
Mentse a módosításokat, majd kattintson a Szinkronizálás most gombra (az eszköztár parancssorából) vagy a Projekt szinkronizálása Gradle-fájlokkal lehetőségre.
Leküldéses értesítések kezelése Android rendszeren
Az Android Studióban a Control + Kattintson a com.your_organization.pushdemo<> csomag mappára (app>src>main>kotlin), és válassza a Csomag lehetőséget az Új menüben. Adja meg a szolgáltatások nevet, majd nyomja le a Return billentyűt.
Ellenőrzés + Kattintson a szolgáltatások mappára, majd az Új menüben válassza a Kotlin-fájl/osztály lehetőséget. Adja meg a DeviceInstallationService nevet, majd nyomja le a Return billentyűt.
Implementálja a DeviceInstallationService szolgáltatást 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" } }
Megjegyzés
Ez az osztály implementálja a csatorna platformspecifikus megfelelőjét
com.<your_organization>.pushdemo/deviceinstallation
. Ezt az alkalmazás Flutter részében definiálták a DeviceInstallationService.dartban. 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, bárhol is használják.Ez az osztály egyedi azonosítót biztosít ( Secure.AndroidId használatával) az értesítési központ regisztrációs hasznos adatainak részeként.
Adjon hozzá egy másik Kotlin-fájlt/osztályt a NotificationRegistrationService nevű szolgáltatási mappához, 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) } }
Megjegyzés
Ez az osztály implementálja a csatorna platformspecifikus megfelelőjét
com.<your_organization>.pushdemo/notificationregistration
. Ezt az alkalmazás Flutter részében definiálták a NotificationRegistrationService.dartban. Ebben az esetben a hívások a natív gazdagépről a közös kódba kerülnek. Itt is ügyeljen arra, hogy a your_organization> a saját szervezetére cserélje<, bárhol is használják.Adjon hozzá egy másik Kotlin-fájlt/osztályt a NotificationActionService nevű szolgáltatási mappához, 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() } } } }
Megjegyzés
Ez az osztály implementálja a csatorna platformspecifikus megfelelőjét
com.<your_organization>.pushdemo/notificationaction
. Ez az alkalmazás Flutter részében volt definiálva a NotificationActionService.dartban. Ebben az esetben mindkét irányban indíthatók hívások. Mindenképpen cserélje le <a your_organization> a saját szervezetére, bárhol is használják.Adjon hozzá egy új Kotlin-fájlt/-osztályt a com.your_organization.pushdemo<> csomaghoz PushNotificationsFirebaseMessagingService néven, 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)) } } } }
Megjegyzés
Ez az osztály felelős az értesítések kezeléséért, amikor az alkalmazás az előtérben fut. Feltételesen meghívja a triggerAction függvényt a NotificationActionService szolgáltatásban, ha az onMessageReceived szolgáltatásban kapott értesítési hasznos adat tartalmaz egy műveletet. Ez meghívja a refreshRegistration függvényt is a NotificationRegistrationService szolgáltatásban, amikor a Firebase-jogkivonat újra létrejön az onNewToken függvény felülírásával.
Még egyszer, vigyázzon, hogy cserélje le <a your_organization> a saját szervezetére, bárhol is használják.
A AndroidManifest.xml (app>src>main) területen adja hozzá a PushNotificationsFirebaseMessagingService elemet az alkalmazáselem aljára 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>
A DeviceInstallationService szolgáltatásba visszatérve győződjön meg arról, hogy a következő importálások vannak jelen a fájl tetején.
package com.<your_organization>.pushdemo import com.<your_organization>.pushdemo.services.PushNotificationsFirebaseMessagingService
Megjegyzés
Cserélje le <a your_organization> a saját szervezeti értékére.
Frissítse a helyőrző szöveg Placeholder_Get_Value_From_FirebaseMessagingService_Implementation , hogy lekérje a token értékét a PushNotificationFirebaseMessagingService szolgáltatásból.
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 }
A MainActivity területen győződjön meg arról, hogy a következő importálások vannak jelen 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
Megjegyzés
Cserélje le <a your_organization> a saját szervezeti értékére.
Adjon hozzá egy változót a DeviceInstallationService hivatkozásának tárolásához.
private lateinit var deviceInstallationService: DeviceInstallationService
Adjon hozzá egy processNotificationActions nevű függvényt annak ellenőrzéséhez, hogy egy szándék rendelkezik-e egy művelet nevű 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) } } } }
Bírálja felül az onNewIntent függvényt a processNotificationActions meghívásához.
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) processNotificationActions(intent) }
Megjegyzés
Mivel a MainActivity LaunchMode tulajdonsága SingleTop értékre van állítva, a rendszer az onNewIntent függvény helyett az onNewIntent függvényen keresztül küld egy szándékota meglévőtevékenységpéldánynak, így a bejövő szándékot a Létrehozás és az OnNewIntent függvényben is kezelnie kell.
Bírálja felül az onCreate függvényt , állítsa a deviceInstallationService elemet a DeviceInstallationService új példányára.
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) flutterEngine?.let { deviceInstallationService = DeviceInstallationService(context, it) } }
Állítsa be a notificationActionService és notificationRegistrationService tulajdonságokat a PushNotificationFirebaseMessagingServices elemen.
flutterEngine?.let { deviceInstallationService = DeviceInstallationService(context, it) PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it) PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it) }
Ugyanebben a függvényben hívja meg feltételesen a FirebaseInstanceId.getInstance().instanceId parancsot. Az OnCompleteListener implementálásával állítsa be az eredményül kapott tokenértéket a PushNotificationFirebaseMessagingService paraméteren, mielőtt meghívja a refreshRegistration parancsot.
if(deviceInstallationService?.playServicesAvailable) { FirebaseInstanceId.getInstance().instanceId .addOnCompleteListener(OnCompleteListener { task -> if (!task.isSuccessful) return@OnCompleteListener PushNotificationsFirebaseMessagingService.token = task.result?.token PushNotificationsFirebaseMessagingService.notificationRegistrationService?.refreshRegistration() }) }
Továbbra is a Létrehozás területen hívja meg a processNotificationActions metódust a függvény végén. A launchAction argumentumnál használja a true (igaz) értéket, ha azt jelzi, hogy a művelet feldolgozása folyamatban van az alkalmazás indításakor.
processNotificationActions(this.intent, true)
Megjegyzés
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
A Visual StudioCode-ban a Control + Kattintson az ios mappára, majd válassza a Megnyitás Xcode-ban lehetőséget.
Az Xcode-ban kattintson a Runner (az xcodeproj elemre a tetején, nem a mappára), majd válassza ki a Futó célt, majd az Aláírás & képességek lehetőséget. Ha a Minden build konfiguráció van kiválasztva, válassza ki a fejlesztői fiókját a csapat számára. 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.
Megjegyzés
Ha nem látja az új Kiépítési profil értéket, próbálja meg frissíteni az aláíró identitás profiljait az XcodePreferences> Account (Xcode-beállítások>fiókja) lehetőség kiválasztásával, majd válassza a Manuális profilok letöltése gombot a profilok letöltéséhez.
Kattintson a + Képesség elemre, majd keresse meg a leküldéses értesítéseket. Kattintson duplán a leküldéses értesítésekre a funkció hozzáadásához.
Nyissa meg az Info.plist fájlt , és állítsa a Minimális rendszerverzió13.0 értékre.
Megjegyzés
Ebben az oktatóanyagban csak az iOS 13.0-s vagy újabb verzióját futtató eszközök támogatottak, de kiterjesztheti a régebbi verziókat futtató eszközökre.
Nyissa meg a Runner.entitlements fájlt, és győződjön meg arról, hogy az APS-környezet beállítása fejlesztésre van állítva.
Leküldéses értesítések kezelése iOS rendszeren
Ellenőrzés + Kattintson a Runner mappára (a Runner projekten belül), majd válassza az Új csoporta Szolgáltatások használatával nevet.
Ellenőrzés + Kattintson a Szolgáltatások mappára, majd válassza az Új fájl... lehetőséget. Ezután válassza a Swift-fájl lehetőséget, és kattintson a Tovább gombra. Adja meg a DeviceInstallationService nevet, majd kattintson a Létrehozás gombra.
Implementálja a DeviceInstallationService.swift eszközt 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." } }
Megjegyzés
Ez az osztály implementálja a csatorna platformspecifikus megfelelőjét
com.<your_organization>.pushdemo/deviceinstallation
. Ezt az alkalmazás Flutter részében definiálták a DeviceInstallationService.dartban. 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, bárhol is használják.Ez az osztály egyedi azonosítót biztosít (az UIDevice.identifierForVendor érték használatával) az értesítési központ regisztrációs hasznos adatainak részeként.
Adjon hozzá egy másik Swift-fájlt a NotificationRegistrationService nevű Services mappához, 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) } }
Megjegyzés
Ez az osztály implementálja a csatorna platformspecifikus megfelelőjét
com.<your_organization>.pushdemo/notificationregistration
. Ezt az alkalmazás Flutter részében definiálták a NotificationRegistrationService.dartban. Ebben az esetben a hívások a natív gazdagépről a közös kódba kerülnek. Itt is ügyeljen arra, hogy a your_organization> a saját szervezetére cserélje<, bárhol is használják.Adjon hozzá egy másik Swift-fájlt a NotificationActionService nevű Services mappához, 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) } } }
Megjegyzés
Ez az osztály implementálja a csatorna platformspecifikus megfelelőjét
com.<your_organization>.pushdemo/notificationaction
. Ez az alkalmazás Flutter részében volt definiálva a NotificationActionService.dartban. Ebben az esetben mindkét irányban indíthatók hívások. Mindenképpen cserélje le <a your_organization> a saját szervezetére, bárhol is használják.Az AppDelegate.swift fájlban adjon 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?
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) } } }
Felülbírálja a didRegisterForRemoteNotificationsWithDeviceTokenfüggvényt a DeviceInstallationService tokenértékének beállításával. Ezután hívja meg a refreshRegistration parancsot a NotificationRegistrationService szolgáltatásban.
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { deviceInstallationService?.token = deviceToken notificationRegistrationService?.refreshRegistration() }
Bírálja felül 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) }
Írja felül a didFailToRegisterForRemoteNotificationsWithError függvényt a hiba naplózásához.
override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print(error); }
Megjegyzés
Ez nagyon sok helyőrző. Az éles forgatókönyvekhez megfelelő naplózást és hibakezelést kell implementálnia.
A didFinishLaunchingWithOptions fá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)
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() } } } }
Ha a launchOptions tartalmazza a remoteNotification kulcsot, hívja meg a processNotificationActions parancsot a didFinishLaunchingWithOptions függvény végén. Adja meg az eredményül kapott userInfo objektumot, és használja a true (igaz ) értéket a launchAction argumentumhoz. A valódi érték azt jelzi, hogy a műveletet az alkalmazás indításakor dolgozzák fel.
if let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable : Any] { processNotificationActions(userInfo: userInfo, launchAction: true) }
A megoldás teszteléséhez
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
Nyisson meg egy új lapon Postman.
A kérelem beállítása POST, és adja meg a következő címre:
https://<app_name>.azurewebsites.net/api/notifications/requests
Ha az ügyfelek hitelesítése API-kulcs használatával szakaszt választotta, mindenképpen konfigurálja úgy a kérésfejléceket, hogy tartalmazzák az apikey értékét.
Kulcs Value apikey <your_api_key> Válassza ki a törzs nyers beállítását, majd a formátumbeállítások listájában válassza a JSON lehetőséget, majd adjon meg néhány helyőrző JSON-tartalmat:
{ "text": "Message from Postman!", "action": "action_a" }
Válassza a Kód gombot, amely az ablak jobb felső sarkában található Mentés gomb alatt található. A kérésnek az alábbi példához hasonlóan kell kinéznie a HTML-hez való megjelenítéskor (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" }
Futtassa a PushDemo alkalmazást az egyik vagy mindkét célplatformon (Android és iOS).
Megjegyzés
Ha Androidon tesztel, győződjön meg arról, hogy nem a Hibakeresésben fut, vagy ha az alkalmazást az alkalmazás futtatásával telepítette, kényszerítse az alkalmazás bezárását, és indítsa újra a indítóból.
A PushDemo alkalmazásban koppintson a Regisztráció gombra.
A Postmanbe visszatérve zárja be a Kódrészletek létrehozása ablakot (ha még nem tette meg), majd kattintson a Küldés gombra.
Ellenőrizze, hogy kap-e 200 OK választ a Postmanben , és a riasztás megjelenik az alkalmazásban, amelyen az ActionA művelet érkezett.
Zárja be a PushDemo alkalmazást, majd kattintson ismét a Küldés gombra a Postmanben.
Ellenőrizze, hogy ismét 200 OK választ kap-e a Postmanben . Ellenőrizze, hogy megjelenik-e értesítés a PushDemo alkalmazás értesítési területén a megfelelő üzenettel.
Koppintson az értesítésre annak megerősítéséhez, hogy megnyitja az alkalmazást, és megjeleníti a kapott ActionA művelet riasztását.
A Postmanben módosítsa az előző kérelemtörzset úgy, hogy csendes értesítést küldjön, amely action_b a műveletértékaction_a helyett.
{ "action": "action_b", "silent": true }
Ha az alkalmazás továbbra is nyitva van, kattintson a Küldés gombra a Postmanben.
Ellenőrizze, hogy 200 OK választ kap-e a Postmanben, és hogy a riasztás megjelenik-e az alkalmazásban, amely a kapott ActionA művelet helyett az ActionB műveletet jeleníti meg.
Zárja be a PushDemo alkalmazást, majd kattintson ismét a Küldés gombra a Postmanben.
Ellenőrizze, hogy 200 OK választ kap-e a Postmanben , és hogy a csendes értesítés nem jelenik-e 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-alkalmazáson tesztel, ellenőrizze, hogy fut-e a szolgáltatás, és üzembe lett-e helyezve, és hiba nélkül elindult-e.
Győződjön meg arról, hogy helyesen adta meg az alapcímet a Postmanben vagy a mobilalkalmazás konfigurációjában az ügyfélen keresztüli teszteléskor. Az alapcímnek indikatív módon vagy https://localhost:5001/
helyi teszteléskor kell lenniehttps://<api_name>.azurewebsites.net/
.
Nem érkeznek értesítések Androidon a hibakeresési munkamenet elindítása vagy leállítása után
Győződjön meg arról, hogy újra regisztrál egy hibakeresési munkamenet elindítása vagy leállítása után. A hibakereső új Firebase-jogkivonatot hoz létre. Az értesítési központ telepítését is frissíteni kell.
401-alapú állapotkód fogadása a háttérszolgáltatástól
Ellenőrizze, hogy az apikey kérelemfejlécét á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 a helyi tesztelés során kapja, győződjön meg arról, hogy az ügyfélkonfigurálásban megadott kulcsérték megegyezik az API által használt Authentication:ApiKey felhasználói beállítás értékkel.
Ha API-alkalmazással tesztel, győződjön meg arról, hogy az ügyfél konfigurációs fájljának kulcsértéke megegyezik az API-alkalmazásban használt Authentication:ApiKey alkalmazásbeállítással.
Megjegyzés
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 az Ügyfelek hitelesítése API-kulcs használatával szakaszt , győződjön meg arról, hogy nem alkalmazta az Authorize attribútumot a NotificationsController osztályra.
404-es állapotkód fogadása a háttérszolgáltatástól
Ellenőrizze, hogy a végpont és a HTTP-kérelem metódusa helyes-e. A végpontoknak például a következőnek kell lenniük:
- [PUT]
https://<api_name>.azurewebsites.net/api/notifications/installations
- [TÖRLÉS]
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
- [TÖRLÉS]
https://localhost:5001/api/notifications/installations/<installation_id>
- [POST]
https://localhost:5001/api/notifications/requests
Amikor megadja az alapcímet az ügyfélalkalmazásban, győződjön meg arról, hogy a végződése egy /
. Az alapcímnek indikatív módon vagy https://localhost:5001/
helyi teszteléskor kell lenniehttps://<api_name>.azurewebsites.net/
.
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 határozza meg a Http-válasz állapotkódját úgy, hogy beállít egy töréspontot a HttpResponseStatusCode tulajdonságértékének vizsgálatához.
Ha lehetséges, tekintse át az előző hibaelhárítási javaslatokat az állapotkód alapján.
Állítson be egy töréspontot azokra a sorokra, amelyek ezeket a konkrét állapotkódokat adják vissza a megfelelő API-hoz. 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 a Postmanen keresztül a megfelelő hasznos adatok használatával. 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 biztosan ne maradjon le a lépésekről. Ellenőrizze, hogy a megfelelő értékek és token
változók feloldása installation id
folyamatban van-e a megfelelő platformon.
Nem sikerült feloldani az eszköz azonosítóját hibaüzenet jelenik meg
Tekintse át a platformspecifikus konfigurációs szakaszokat, hogy biztosan ne maradjon le a lépésekről.
Kapcsolódó hivatkozások
- Az Azure Notification Hubs – áttekintés
- A Flutter telepítése macOS rendszeren
- A Flutter telepítése Windows rendszeren
- Notification Hubs SDK háttér-műveletek
- A Notification Hubs SDK a Githubon
- Regisztráció az alkalmazás háttérrendszerével
- Regisztrációkezelés
- Címkék használata
- Egyéni sablonok használata
További 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 képes értesítéseket küldeni és fogadni.
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.
A Visual Studio App Center gyorsan beépíthető mobilalkalmazásokba , amelyek elemzéseket és diagnosztikát biztosítanak a hibaelhárítás elősegítéséhez.