Share via


Oktatóanyag: Leküldéses értesítések küldése adott felhasználóknak az Azure Notification Hubs használatával

Az oktatóanyag bemutatja, hogy hogyan küldhetők leküldéses értesítések adott alkalmazásfelhasználónak, adott eszközre az Azure Notification Hubs használatával. A ASP.NET WebAPI-háttérrendszer az ügyfelek hitelesítésére és értesítések létrehozására szolgál, ahogyan az alkalmazás háttérrendszeréből történő regisztráció című útmutatóban látható.

Ebben az oktatóanyagban a következő lépéseket hajtja végre:

  • A WebAPI-projekt létrehozása
  • Ügyfelek hitelesítése a WebAPI háttérrendszeren
  • Regisztráció értesítésekre a WebAPI háttérrendszer használatával
  • Értesítések küldése a WebAPI háttérrendszerről
  • Az új WebAPI háttérrendszer közzététele
  • Az iOS-alkalmazás módosítása
  • Az alkalmazás tesztelése

Előfeltételek

Ez az oktatóanyag feltételezi, hogy létrehozta és konfigurálta az értesítési központot az Azure Notification Hubs használatával leküldéses értesítések küldése iOS-alkalmazásokba című cikkben leírtak szerint. Ez az oktatóanyag a Biztonságos leküldéses (iOS) oktatóanyag előfeltétele is. Ha háttérszolgáltatásként a Mobile Apps szolgáltatást szeretné használni, tekintse meg a Mobile Apps – Első lépések a leküldéses szolgáltatással című témakört.

A WebAPI-projekt létrehozása

Az alábbi szakaszok az új ASP.NET WebAPI hátterrendszer létrehozását ismertetik. E folyamat három fő célja:

  • Ügyfelek hitelesítése: Az ügyfélkérések hitelesítéséhez és a kérés adott felhasználóhoz való hozzárendeléséhez egy üzenetkezelőt fog hozzáadni a rendszerhez.
  • Regisztrálás értesítésekre a WebAPI háttérrendszer használatával: Annak érdekében, hogy az ügyféleszközön értesítéseket lehessen fogadni, egy vezérlőt fog hozzáadni az új regisztrációk kezeléséhez. A rendszer címke formájában automatikusan hozzáadja a hitelesített felhasználó nevét a regisztrációhoz.
  • Értesítések küldése az ügyfeleknek: Egy vezérlőt is hozzá fog adni annak érdekében, hogy a felhasználók biztonságos leküldést indíthassanak az eszközökre és a címkéhez társított ügyfelek számára.

Hozza létre az új ASP.NET Core 6.0 webes API-háttérrendszert a következő műveletek végrehajtásával:

Az ellenőrzéshez indítsa el a Visual Studiót. Az Eszközök menüben válassza a Bővítmények és frissítések pontot. Keresse meg az Ön által használt Visual Studio-verzióhoz tartozó NuGet-csomagkezelőt, és ellenőrizze, hogy a legfrissebb verzió van-e telepítve a gépén. Ha nem a legfrissebb verzió van telepítve a gépén, távolítsa el, és telepítse újra a NuGet-csomagkezelőt.

Képernyőkép a Bővítmények és Frissítések párbeszédpanelről, amelyen a NuGet Package manage for Visual Studios csomag ki van emelve.

Megjegyzés

Győződjön meg arról, hogy telepítette a Visual Studio Azure SDK-t a webhely üzembe helyezéséhez.

  1. Indítsa el a Visual Studiót vagy a Visual Studio Expresst.

  2. Kattintson a Server Explorer (Kiszolgálókezelő) elemre, és jelentkezzen be az Azure-fiókjába. Be kell jelentkeznie ahhoz, hogy a fiókban létrehozhassa a webhelyerőforrásokat.

  3. A Visual Studio Fájl menüjében válassza az Új>projekt lehetőséget.

  4. Írja be a Web API kifejezést a keresőmezőbe.

  5. Válassza ki a ASP.NET Core Webes API-projektsablont, és válassza a Tovább gombot.

  6. Az Új projekt konfigurálása párbeszédpanelen nevezze el a projektet AppBackend néven, és válassza a Tovább gombot.

  7. A További információk párbeszédpanelen:

    • Győződjön meg arról, hogy a keretrendszer.NET 6.0 (hosszú távú támogatás).
    • Ellenőrizze, hogy a Vezérlők használata jelölőnégyzet be van-e jelölve (törölje a jelölést a minimális API-k használatához).
    • Törölje az OpenAPI-támogatás engedélyezése jelölőnégyzet jelölését.
    • Válassza a Létrehozás lehetőséget.

A WeatherForecast sablonfájljainak eltávolítása

  1. Távolítsa el a WeatherForecast.cs és a Controllers/WeatherForecastController.cs példafájlokat az új AppBackend projektből.
  2. Nyissa meg a Properties\launchSettings.json fájlt.
  3. A launchUrl tulajdonságainak módosítása weatherforcastrólappbackendre.

A Configure Microsoft Azure Web App (Microsoft Azure-webalkalmazás konfigurálása) ablakban válasszon ki egy előfizetést, majd az App Service plan (App Service-csomag) listában végezze el az alábbi műveletek valamelyikét:

  • Válasszon ki egy már létrehozott Azure App Service csomagot.
  • Válassza a Create a new app service plan (Új App Service-csomag létrehozása) lehetőséget is, és hozzon létre egy új csomagot.

Az oktatóanyag elvégzéséhez nincs szükség adatbázisra. Az App Service-csomag kiválasztása után kattintson az OK gombra a projekt létrehozásához.

A Configure Microsoft Azure Web App (Microsoft Azure-webalkalmazás konfigurálása) ablak

Ha nem látja ezt a lapot az App Service-csomag konfigurálásához, folytassa az oktatóanyaggal. Az alkalmazást később is konfigurálhatja az alkalmazás közzétételekor.

Ügyfelek hitelesítése a WebAPI háttérrendszeren

Ebben a szakaszban egy új, AuthenticationTestHandler nevű üzenetkezelő-osztályt fog létrehozni az új háttérrendszer számára. A rendszer ezt az osztályt a DelegatingHandler kezelőből származtatja, és üzenetkezelőként adja hozzá, így az képes a háttérrendszerhez beérkező összes kérés feldolgozására.

  1. A Solution Explorer (Megoldáskezelő) ablakában kattintson a jobb gombbal az AppBackend projektre, válassza az Add (Hozzáadás) parancsot, majd a Class (Osztály) elemet.

  2. Nevezze el az új osztályt AuthenticationTestHandler.cs néven, majd kattintson az Add (Hozzáadás) gombra az osztály létrehozásához. Az egyszerűség kedvéért a rendszer ezt az osztályt fogja használni a felhasználók alapszintű hitelesítéséhez. Az alkalmazás bármilyen hitelesítési séma használatára képes.

  3. Az AuthenticationTestHandler.cs osztályban adja hozzá a következő using-utasításokat:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. Az AuthenticationTestHandler.cs osztályban cserélje le az AuthenticationTestHandler osztálydefiníciót az alábbi kódra:

    A kezelő akkor engedélyezi a kérést, ha teljesül a következő három feltétel:

    • A kérés tartalmaz engedélyezési fejlécet.
    • A kérés alapszintű hitelesítést használ.
    • A felhasználónév és a jelszó sztring azonos.

    Ellenkező esetben a kérést a rendszer elutasítja. Ez nem egy valós hitelesítési és engedélyezési megközelítés, csak egy egyszerű példa ehhez az oktatóanyaghoz.

    Ha az AuthenticationTestHandler hitelesíti és engedélyezi a kérésüzenetet, az alapszintű hitelesítést használó felhasználót a rendszer hozzákapcsolja az aktuális kéréshez a HttpContext felületén. A HttpContext felhasználói adatait a későbbiekben egy másik vezérlő (RegisterController) fogja használni egy címke az értesítésregisztrációs kéréshez való hozzáadásához.

    public class AuthenticationTestHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var authorizationHeader = request.Headers.GetValues("Authorization").First();
    
            if (authorizationHeader != null && authorizationHeader
                .StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase))
            {
                string authorizationUserAndPwdBase64 =
                    authorizationHeader.Substring("Basic ".Length);
                string authorizationUserAndPwd = Encoding.Default
                    .GetString(Convert.FromBase64String(authorizationUserAndPwdBase64));
                string user = authorizationUserAndPwd.Split(':')[0];
                string password = authorizationUserAndPwd.Split(':')[1];
    
                if (VerifyUserAndPwd(user, password))
                {
                    // Attach the new principal object to the current HttpContext object
                    HttpContext.Current.User =
                        new GenericPrincipal(new GenericIdentity(user), new string[0]);
                    System.Threading.Thread.CurrentPrincipal =
                        System.Web.HttpContext.Current.User;
                }
                else return Unauthorized();
            }
            else return Unauthorized();
    
            return base.SendAsync(request, cancellationToken);
        }
    
        private bool VerifyUserAndPwd(string user, string password)
        {
            // This is not a real authentication scheme.
            return user == password;
        }
    
        private Task<HttpResponseMessage> Unauthorized()
        {
            var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
            var tsc = new TaskCompletionSource<HttpResponseMessage>();
            tsc.SetResult(response);
            return tsc.Task;
        }
    }
    

    Megjegyzés

    Biztonsági megjegyzés: Az AuthenticationTestHandler osztály nem biztosít valós hitelesítést. A rendszer azt csak az alapszintű hitelesítés utánzására használja, és nem tekinthető biztonságosnak. Az éles alkalmazásokban és szolgáltatásokban implementálnia kell egy biztonságos hitelesítési mechanizmust.

  5. Az üzenetkezelő regisztrálásához adja hozzá az alábbi kódot a metódus végén a RegisterProgram.cs fájlban:

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Mentse a módosításokat.

Regisztráció értesítésekre a WebAPI háttérrendszer használatával

Ebben a szakaszban egy új vezérlőt fog hozzáadni a WebAPI háttérrendszerhez a felhasználók és az eszközök értesítés-regisztrációs kéréseinek kezeléséhez az értesítési központ ügyfélkönyvtárával. A vezérlő hozzáad egy felhasználói címkét a hitelesített és az AuthenticationTestHandler által a HttpContext elemhez kapcsolt felhasználóhoz. A címke "username:<actual username>" sztringformátumú lesz.

  1. A Solution Explorer (Megoldáskezelő) ablakában kattintson a jobb gombbal az AppBackend projektre, majd kattintson a Manage NuGet Packages (NuGet-csomagok kezelése) parancsra.

  2. A bal oldali ablaktáblán válassza az Online elemet, majd a keresőmezőbe írja be a Microsoft.Azure.NotificationHubs kifejezést.

  3. Az eredmények listájából válassza ki a Microsoft Azure Notification Hubs elemet, majd az Install (Telepítés) lehetőséget. Fejezze be a telepítést, majd zárja be a NuGet-csomagkezelő ablakát.

    Ez a művelet hozzáad egy, az Azure Notification Hubs SDK-ra mutató hivatkozást a Microsoft.Azure.Notification Hubs NuGet-csomag használatával.

  4. Hozzon létre egy új osztályfájlt, amely az értesítések küldésére használt értesítési központtal való kapcsolatot jelöli. A Solution Explorer (Megoldáskezelő) ablakában kattintson a jobb gombbal a Models (Modellek) mappára, kattintson az Add (Hozzáadás) parancsra, majd kattintson a Class (Osztály) gombra. Nevezze el az új osztályt Notifications.cs néven, majd kattintson az Add (Hozzáadás) gombra az osztály létrehozásához.

    Az Add New Item (Új elem hozzáadása) ablak

  5. Adja hozzá a következő using-utasítást a Notifications.cs fájl elejéhez:

    using Microsoft.Azure.NotificationHubs;
    
  6. Cserélje le a Notifications osztálydefiníciót a következő kódra, a két helyőrzőt pedig az értesítési központ kapcsolati sztringjére (teljes hozzáféréssel) és a központ nevére (az Azure Portalon érhető el):

    public class Notifications
    {
        public static Notifications Instance = new Notifications();
    
        public NotificationHubClient Hub { get; set; }
    
        private Notifications() {
            Hub = NotificationHubClient.CreateClientFromConnectionString("<your hub's DefaultFullSharedAccessSignature>",
                                                                            "<hub name>");
        }
    }
    

    Fontos

    A továbblépés előtt adja meg a központ nevét és DefaultFullSharedAccessSignature értékét.

  7. A következő lépésben hozzon létre egy új vezérlőt RegisterController néven. A Solution Explorer (Megoldáskezelő) ablakában kattintson a jobb gombbal a Controllers (Vezérlők) mappára, kattintson az Add (Hozzáadás) parancsra, majd kattintson a Controller (Vezérlő) gombra.

  8. Válassza az API-vezérlő – Üres lehetőséget, majd válassza a Hozzáadás lehetőséget.

  9. A Controller name (Vezérlő neve) mezőben nevezze el az új osztályt RegisterController néven, majd kattintson az Add (Hozzáadás) gombra.

    A Vezérlő hozzáadása ablak.

  10. Adja hozzá a következő using-utasításokat a RegisterController.cs fájlhoz:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Adja hozzá a következő kódot a(z) RegisterController osztálydefiníciójához: Ebben a kódban felhasználói címkét fog hozzáadni a HttpContexthez csatolt felhasználóhoz. A felhasználó hitelesítését és a HttpContexthez való csatolását az Ön által hozzáadott üzenetszűrő (AuthenticationTestHandler) végezte. További választható ellenőrzéseket is hozzáadhat, amelyekkel ellenőrizheti, hogy a felhasználó jogosult-e a kért címkékre történő regisztráláshoz.

    private NotificationHubClient hub;
    
    public RegisterController()
    {
        hub = Notifications.Instance.Hub;
    }
    
    public class DeviceRegistration
    {
        public string Platform { get; set; }
        public string Handle { get; set; }
        public string[] Tags { get; set; }
    }
    
    // POST api/register
    // This creates a registration id
    public async Task<string> Post(string handle = null)
    {
        string newRegistrationId = null;
    
        // make sure there are no existing registrations for this push handle (used for iOS and Android)
        if (handle != null)
        {
            var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100);
    
            foreach (RegistrationDescription registration in registrations)
            {
                if (newRegistrationId == null)
                {
                    newRegistrationId = registration.RegistrationId;
                }
                else
                {
                    await hub.DeleteRegistrationAsync(registration);
                }
            }
        }
    
        if (newRegistrationId == null) 
            newRegistrationId = await hub.CreateRegistrationIdAsync();
    
        return newRegistrationId;
    }
    
    // PUT api/register/5
    // This creates or updates a registration (with provided channelURI) at the specified id
    public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate)
    {
        RegistrationDescription registration = null;
        switch (deviceUpdate.Platform)
        {
            case "mpns":
                registration = new MpnsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "wns":
                registration = new WindowsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "apns":
                registration = new AppleRegistrationDescription(deviceUpdate.Handle);
                break;
            case "fcm":
                registration = new FcmRegistrationDescription(deviceUpdate.Handle);
                break;
            default:
                throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
    
        registration.RegistrationId = id;
        var username = HttpContext.Current.User.Identity.Name;
    
        // add check if user is allowed to add these tags
        registration.Tags = new HashSet<string>(deviceUpdate.Tags);
        registration.Tags.Add("username:" + username);
    
        try
        {
            await hub.CreateOrUpdateRegistrationAsync(registration);
        }
        catch (MessagingException e)
        {
            ReturnGoneIfHubResponseIsGone(e);
        }
    
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    // DELETE api/register/5
    public async Task<HttpResponseMessage> Delete(string id)
    {
        await hub.DeleteRegistrationAsync(id);
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    private static void ReturnGoneIfHubResponseIsGone(MessagingException e)
    {
        var webex = e.InnerException as WebException;
        if (webex.Status == WebExceptionStatus.ProtocolError)
        {
            var response = (HttpWebResponse)webex.Response;
            if (response.StatusCode == HttpStatusCode.Gone)
                throw new HttpRequestException(HttpStatusCode.Gone.ToString());
        }
    }
    
  12. Mentse a módosításokat.

Értesítések küldése a WebAPI háttérrendszerről

Ebben a szakaszban egy új vezérlőt ad hozzá, amely értesítés küldését teszi lehetővé az ügyféleszközök számára. A rendszer az értesítést az ASP.NET WebAPI-háttérrendszeren lévő Azure Notification Hubs .NET Libraryt használó felhasználónév-címke alapján hozza létre.

  1. Hozzon létre egy másik új, NotificationsController nevű vezérlőt. Ennek során ugyanúgy járjon el, mint az előző szakaszban a RegisterController vezérlő esetében.

  2. Adja hozzá a következő using-utasításokat a NotificationsController.cs fájlhoz:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Adja hozzá a következő metódust az NotificationsController osztályhoz:

    Ez a kód egy értesítéstípust fog küldeni a platformértesítési szolgáltatás (PNS) pns paramétere alapján. A(z) to_tag értékét a rendszer az üzenet felhasználónév-címkéjének beállítására használja. A címkének egyeznie kell egy aktív értesítésiközpont-regisztráció felhasználónév-címkéjével. Az értesítési üzenetet a rendszer a POST-kérés törzséből nyeri ki, és a cél PNS-nek megfelelően formázza.

    A támogatott eszközök által az értesítések fogadására használt PNS-től függően az értesítések különböző formátumok használatával támogatottak. Windows rendszerű eszközökön például használhat bejelentési értesítéseket a WNS formátummal, amelyet egy másik PNS nem támogat közvetlenül. Ebben az esetben a háttérrendszernek a támogatni kívánt eszközök PNS-e által támogatott formátum szerint kell formáznia az értesítést. Ezt követően használja a megfelelő küldési API-t a NotificationHubClient osztályon.

    public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag)
    {
        var user = HttpContext.Current.User.Identity.Name;
        string[] userTag = new string[2];
        userTag[0] = "username:" + to_tag;
        userTag[1] = "from:" + user;
    
        Microsoft.Azure.NotificationHubs.NotificationOutcome outcome = null;
        HttpStatusCode ret = HttpStatusCode.InternalServerError;
    
        switch (pns.ToLower())
        {
            case "wns":
                // Windows 8.1 / Windows Phone 8.1
                var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + 
                            "From " + user + ": " + message + "</text></binding></visual></toast>";
                outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag);
                break;
            case "apns":
                // iOS
                var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, userTag);
                break;
            case "fcm":
                // Android
                var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendFcmNativeNotificationAsync(notif, userTag);
                break;
        }
    
        if (outcome != null)
        {
            if (!((outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Abandoned) ||
                (outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Unknown)))
            {
                ret = HttpStatusCode.OK;
            }
        }
    
        return Request.CreateResponse(ret);
    }
    
  4. Nyomja le az F5 billentyűt az alkalmazás futtatásához, valamint eddigi munkája pontosságának ellenőrzéséhez. Az alkalmazás megnyit egy webböngészőt, amelyen az ASP.NET kezdőlapja jelenik meg.

Az új WebAPI háttérrendszer közzététele

A következőkben üzembe fogja helyezni ezt az alkalmazást egy Azure-webhelyen, hogy minden eszközről elérhető legyen.

  1. Kattintson a jobb gombbal az AppBackend projektre, és válassza a Publish (Közzététel) lehetőséget.

  2. Közzétételi célként válassza a Microsoft Azure App Service lehetőséget, majd kattintson a \*\*Publish (Közzététel) gombra. Ekkor megnyílik a Create App Service (App Service létrehozása) ablak. Itt létrehozhatja az összes, az ASP.NET-webalkalmazás Azure-ban való futtatásához szükséges Azure-erőforrást.

    A Microsoft Azure App Service (Microsoft Azure App Service) csempe

  3. A Create App Service (App Service létrehozása) ablakban válassza ki az Azure-fiókját. Válassza a Típus> módosításawebalkalmazás lehetőséget. Tartsa meg az alapértelmezett webalkalmazásnevet, majd válassza a Subscription (Előfizetés), Resource Group (Erőforráscsoport) és App Service Plan (App Service-csomag) elemeket.

  4. Válassza a Létrehozás lehetőséget.

  5. Jegyezze fel a Summary (Összegzés) szakaszban lévő Site URL (Webhely URL-címe) tulajdonságot. Ezt az URL-címet az oktatóanyag későbbi részében fogja használni háttérvégpontként.

  6. Válassza a Közzététel lehetőséget.

Miután a varázsló befejeződött, közzéteszi az ASP.NET-webalkalmazást az Azure-on, majd megnyitja azt az alapértelmezett böngészőben. Az alkalmazását az Azure App Servicesben tekintheti meg.

Az URL-cím a korábban megadott webalkalmazás-nevet használja http:// app_name.azurewebsites.net> formátumban<.

Az iOS-alkalmazás módosítása

  1. Nyissa meg a Leküldéses értesítések küldése iOS-alkalmazásokba az Azure Notification Hubs-oktatóanyag használatával című oktatóanyagban létrehozott egyoldalas nézetet.

    Megjegyzés

    Ez a szakasz feltételezi, hogy a projekt üres szervezetnévvel van konfigurálva. Ha nem, akkor a szervezet nevét az összes osztálynévre előre írja.

  2. A fájlban Main.storyboard adja hozzá a képernyőképen látható összetevőket az objektumtárból.

    Storyboard szerkesztése az Xcode interface builderben

    • Felhasználónév: Egy helyőrző szöveggel ellátott UITextField ( Felhasználónév megadása) a küldési eredmények címkéje alatt, a bal és a jobb margóra korlátozva, valamint a küldési eredmények címkéje alatt.

    • Jelszó: Egy helyőrző szöveggel ellátott UITextField( Jelszó megadása) mező, amely közvetlenül a felhasználónév szövegmezője alatt található, és a bal és a jobb margóra, valamint a felhasználónév szövegmezője alá van korlátozva. Ellenőrizze a Biztonságos szövegbevitel lehetőséget az Attribútumfelügyelő Visszatérési kulcs területén.

    • Bejelentkezés: A jelszó szövegmezője alatt közvetlenül címkézett UIButton, és törölje a jelölést az AttribútumfelügyelőBen a Control-Content területen található Engedélyezve lehetőségből.

    • WNS: Címkézzen és váltson az értesítés küldésének engedélyezésére a Windows Értesítési szolgáltatásban, ha az a központban van beállítva. Tekintse meg a Windows Első lépések oktatóanyagot.

    • GCM: Címkézés és váltás az értesítés Google Cloud Messagingbe való küldésének engedélyezéséhez, ha az a központban van beállítva. Lásd: Android Első lépések oktatóanyag.

    • APNS: Címkézés és váltás az értesítés Apple Platform Notification Service-nek való küldésének engedélyezéséhez.

    • Címzett felhasználóneve:Egy helyőrző szöveggel ellátott UITextField, Címzett felhasználónév címkéje, közvetlenül a GCM címke alatt, a bal és a jobb margóra korlátozva, valamint a GCM-címke alatt.

      A leküldéses értesítések küldése iOS-alkalmazásokba az Azure Notification Hubs használatával című oktatóanyag tartalmaz néhány összetevőt.

  3. Húzza a Ctrl billentyűt a nézet összetevői közül a következő ViewController.h új aljzatokhoz:

    @property (weak, nonatomic) IBOutlet UITextField *UsernameField;
    @property (weak, nonatomic) IBOutlet UITextField *PasswordField;
    @property (weak, nonatomic) IBOutlet UITextField *RecipientField;
    @property (weak, nonatomic) IBOutlet UITextField *NotificationField;
    
    // Used to enable the buttons on the UI
    @property (weak, nonatomic) IBOutlet UIButton *LogInButton;
    @property (weak, nonatomic) IBOutlet UIButton *SendNotificationButton;
    
    // Used to enabled sending notifications across platforms
    @property (weak, nonatomic) IBOutlet UISwitch *WNSSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *GCMSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *APNSSwitch;
    
    - (IBAction)LogInAction:(id)sender;
    
  4. A fájlban ViewController.hadja hozzá a következőt #define az importálási utasítások után. Cserélje le a <Your backend endpoint> helyőrzőt az alkalmazás háttérrendszerének üzembe helyezéséhez használt Cél URL-címmel az előző szakaszban. Például http://your_backend.azurewebsites.net:

    #define BACKEND_ENDPOINT @"<Your backend endpoint>"
    
  5. A projektben hozzon létre egy új Cocoa Touch-osztályt a RegisterClient létrehozott ASP.NET háttérrendszerrel való kapcsolódáshoz. Hozza létre a következőtől NSObjectöröklő osztályt: . Ezután adja hozzá a következő kódot a következőhöz RegisterClient.h:

    @interface RegisterClient : NSObject
    
    @property (strong, nonatomic) NSString* authenticationHeader;
    
    -(void) registerWithDeviceToken:(NSData*)token tags:(NSSet*)tags
        andCompletion:(void(^)(NSError*))completion;
    
    -(instancetype) initWithEndpoint:(NSString*)Endpoint;
    
    @end
    
  6. A fájlban RegisterClient.mfrissítse a szakaszt @interface :

    @interface RegisterClient ()
    
    @property (strong, nonatomic) NSURLSession* session;
    @property (strong, nonatomic) NSURLSession* endpoint;
    
    -(void) tryToRegisterWithDeviceToken:(NSData*)token tags:(NSSet*)tags retry:(BOOL)retry
                andCompletion:(void(^)(NSError*))completion;
    -(void) retrieveOrRequestRegistrationIdWithDeviceToken:(NSString*)token
                completion:(void(^)(NSString*, NSError*))completion;
    -(void) upsertRegistrationWithRegistrationId:(NSString*)registrationId deviceToken:(NSString*)token
                tags:(NSSet*)tags andCompletion:(void(^)(NSURLResponse*, NSError*))completion;
    
    @end
    
  7. Cserélje le a @implementation RegisterClient.m szakaszt a következő kódra:

    @implementation RegisterClient
    
    // Globals used by RegisterClient
    NSString *const RegistrationIdLocalStorageKey = @"RegistrationId";
    
    -(instancetype) initWithEndpoint:(NSString*)Endpoint
    {
        self = [super init];
        if (self) {
            NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
            _session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil];
            _endpoint = Endpoint;
        }
        return self;
    }
    
    -(void) registerWithDeviceToken:(NSData*)token tags:(NSSet*)tags
                andCompletion:(void(^)(NSError*))completion
    {
        [self tryToRegisterWithDeviceToken:token tags:tags retry:YES andCompletion:completion];
    }
    
    -(void) tryToRegisterWithDeviceToken:(NSData*)token tags:(NSSet*)tags retry:(BOOL)retry
                andCompletion:(void(^)(NSError*))completion
    {
        NSSet* tagsSet = tags?tags:[[NSSet alloc] init];
    
        NSString *deviceTokenString = [[token description]
            stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
        deviceTokenString = [[deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""]
                                uppercaseString];
    
        [self retrieveOrRequestRegistrationIdWithDeviceToken: deviceTokenString
            completion:^(NSString* registrationId, NSError *error) {
            NSLog(@"regId: %@", registrationId);
            if (error) {
                completion(error);
                return;
            }
    
            [self upsertRegistrationWithRegistrationId:registrationId deviceToken:deviceTokenString
                tags:tagsSet andCompletion:^(NSURLResponse * response, NSError *error) {
                if (error) {
                    completion(error);
                    return;
                }
    
                NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
                if (httpResponse.statusCode == 200) {
                    completion(nil);
                } else if (httpResponse.statusCode == 410 && retry) {
                    [self tryToRegisterWithDeviceToken:token tags:tags retry:NO andCompletion:completion];
                } else {
                    NSLog(@"Registration error with response status: %ld", (long)httpResponse.statusCode);
    
                    completion([NSError errorWithDomain:@"Registration" code:httpResponse.statusCode
                                userInfo:nil]);
                }
    
            }];
        }];
    }
    
    -(void) upsertRegistrationWithRegistrationId:(NSString*)registrationId deviceToken:(NSData*)token
                tags:(NSSet*)tags andCompletion:(void(^)(NSURLResponse*, NSError*))completion
    {
        NSDictionary* deviceRegistration = @{@"Platform" : @"apns", @"Handle": token,
                                                @"Tags": [tags allObjects]};
        NSData* jsonData = [NSJSONSerialization dataWithJSONObject:deviceRegistration
                            options:NSJSONWritingPrettyPrinted error:nil];
    
        NSLog(@"JSON registration: %@", [[NSString alloc] initWithData:jsonData
                                            encoding:NSUTF8StringEncoding]);
    
        NSString* endpoint = [NSString stringWithFormat:@"%@/api/register/%@", _endpoint,
                                registrationId];
        NSURL* requestURL = [NSURL URLWithString:endpoint];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"PUT"];
        [request setHTTPBody:jsonData];
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
                                                self.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
        [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    
        NSURLSessionDataTask* dataTask = [self.session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            if (!error)
            {
                completion(response, error);
            }
            else
            {
                NSLog(@"Error request: %@", error);
                completion(nil, error);
            }
        }];
        [dataTask resume];
    }
    
    -(void) retrieveOrRequestRegistrationIdWithDeviceToken:(NSString*)token
                completion:(void(^)(NSString*, NSError*))completion
    {
        NSString* registrationId = [[NSUserDefaults standardUserDefaults]
                                    objectForKey:RegistrationIdLocalStorageKey];
    
        if (registrationId)
        {
            completion(registrationId, nil);
            return;
        }
    
        // request new one & save
        NSURL* requestURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/api/register?handle=%@",
                                _endpoint, token]];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"POST"];
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
                                                self.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    
        NSURLSessionDataTask* dataTask = [self.session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (!error && httpResponse.statusCode == 200)
            {
                NSString* registrationId = [[NSString alloc] initWithData:data
                    encoding:NSUTF8StringEncoding];
    
                // remove quotes
                registrationId = [registrationId substringWithRange:NSMakeRange(1,
                                    [registrationId length]-2)];
    
                [[NSUserDefaults standardUserDefaults] setObject:registrationId
                    forKey:RegistrationIdLocalStorageKey];
                [[NSUserDefaults standardUserDefaults] synchronize];
    
                completion(registrationId, nil);
            }
            else
            {
                NSLog(@"Error status: %ld, request: %@", (long)httpResponse.statusCode, error);
                if (error)
                    completion(nil, error);
                else {
                    completion(nil, [NSError errorWithDomain:@"Registration" code:httpResponse.statusCode
                                userInfo:nil]);
                }
            }
        }];
        [dataTask resume];
    }
    
    @end
    

    Ez a kód a regisztráció az alkalmazás háttérrendszeréből az NSURLSession használatával rest-hívások végrehajtásához az alkalmazás háttérrendszeréhez, az NSUserDefaults pedig az értesítési központ által visszaadott regisztrációs azonosító helyi tárolására szolgál.

    Ennek az osztálynak a tulajdonságát authorizationHeader be kell állítani a megfelelő működéshez. Ezt a tulajdonságot az ViewController osztály állítja be a bejelentkezés után.

  8. A fájlban ViewController.hadjon hozzá egy utasítást #import a következőhöz RegisterClient.h: . Ezután adjon hozzá egy deklarációt az eszköz jogkivonatához, és hivatkozzon egy RegisterClient példányra a @interface szakaszban:

    #import "RegisterClient.h"
    
    @property (strong, nonatomic) NSData* deviceToken;
    @property (strong, nonatomic) RegisterClient* registerClient;
    
  9. A ViewController.m fájlban adjon hozzá egy privát metódus deklarációt a @interface szakaszban:

    @interface ViewController () <UITextFieldDelegate, NSURLConnectionDataDelegate, NSXMLParserDelegate>
    
    // create the Authorization header to perform Basic authentication with your app back-end
    -(void) createAndSetAuthenticationHeaderWithUsername:(NSString*)username
                    AndPassword:(NSString*)password;
    
    @end
    

    Megjegyzés

    A következő kódrészlet nem biztonságos hitelesítési séma, a implementációt createAndSetAuthenticationHeaderWithUsername:AndPassword: az adott hitelesítési mechanizmussal kell helyettesítenie, amely létrehoz egy hitelesítési jogkivonatot, amelyet a regisztrációs ügyfélosztály (például OAuth, Active Directory) használ fel.

  10. Ezután a @implementation szakaszában ViewController.madja hozzá a következő kódot, amely hozzáadja az eszköz jogkivonatának és hitelesítési fejlécének beállításához szükséges implementációt.

    -(void) setDeviceToken: (NSData*) deviceToken
    {
        _deviceToken = deviceToken;
        self.LogInButton.enabled = YES;
    }
    
    -(void) createAndSetAuthenticationHeaderWithUsername:(NSString*)username
                    AndPassword:(NSString*)password;
    {
        NSString* headerValue = [NSString stringWithFormat:@"%@:%@", username, password];
    
        NSData* encodedData = [[headerValue dataUsingEncoding:NSUTF8StringEncoding] base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
    
        self.registerClient.authenticationHeader = [[NSString alloc] initWithData:encodedData
                                                    encoding:NSUTF8StringEncoding];
    }
    
    -(BOOL)textFieldShouldReturn:(UITextField *)textField
    {
        [textField resignFirstResponder];
        return YES;
    }
    

    Figyelje meg, hogy az eszköz jogkivonatának beállítása hogyan teszi lehetővé a Bejelentkezés gombot. Ennek az az oka, hogy a bejelentkezési művelet részeként a nézetvezérlő leküldéses értesítésekre regisztrál az alkalmazás háttérrendszerével. Nem szeretné, hogy a Bejelentkezés művelet elérhető legyen, amíg az eszköz jogkivonata megfelelően be nem van állítva. A bejelentkezést leválaszthatja a leküldéses regisztrációról, ha az előbbi az utóbbi előtt történik.

  11. A ViewController.m fájlban az alábbi kódrészletekkel implementálhatja a Bejelentkezés gomb műveletmetódusát, valamint egy metódust, a ASP.NET háttérrendszer használatával küldi el az értesítési üzenetet.

    - (IBAction)LogInAction:(id)sender {
        // create authentication header and set it in register client
        NSString* username = self.UsernameField.text;
        NSString* password = self.PasswordField.text;
    
        [self createAndSetAuthenticationHeaderWithUsername:username AndPassword:password];
    
        __weak ViewController* selfie = self;
        [self.registerClient registerWithDeviceToken:self.deviceToken tags:nil
            andCompletion:^(NSError* error) {
            if (!error) {
                dispatch_async(dispatch_get_main_queue(),
                ^{
                    selfie.SendNotificationButton.enabled = YES;
                    [self MessageBox:@"Success" message:@"Registered successfully!"];
                });
            }
        }];
    }
    
    - (void)SendNotificationASPNETBackend:(NSString*)pns UsernameTag:(NSString*)usernameTag
                Message:(NSString*)message
    {
        NSURLSession* session = [NSURLSession
            sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:nil
            delegateQueue:nil];
    
        // Pass the pns and username tag as parameters with the REST URL to the ASP.NET backend
        NSURL* requestURL = [NSURL URLWithString:[NSString
            stringWithFormat:@"%@/api/notifications?pns=%@&to_tag=%@", BACKEND_ENDPOINT, pns,
            usernameTag]];
    
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"POST"];
    
        // Get the mock authenticationheader from the register client
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
            self.registerClient.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    
        //Add the notification message body
        [request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:[message dataUsingEncoding:NSUTF8StringEncoding]];
    
        // Execute the send notification REST API on the ASP.NET Backend
        NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (error || httpResponse.statusCode != 200)
            {
                NSString* status = [NSString stringWithFormat:@"Error Status for %@: %d\nError: %@\n",
                                    pns, httpResponse.statusCode, error];
                dispatch_async(dispatch_get_main_queue(),
                ^{
                    // Append text because all 3 PNS calls may also have information to view
                    [self.sendResults setText:[self.sendResults.text stringByAppendingString:status]];
                });
                NSLog(status);
            }
    
            if (data != NULL)
            {
                xmlParser = [[NSXMLParser alloc] initWithData:data];
                [xmlParser setDelegate:self];
                [xmlParser parse];
            }
        }];
        [dataTask resume];
    }
    
  12. Frissítse az Értesítés küldése gomb műveletét a ASP.NET háttérrendszer használatához, és küldje el a kapcsoló által engedélyezett PNS-nek.

    - (IBAction)SendNotificationMessage:(id)sender
    {
        //[self SendNotificationRESTAPI];
        [self SendToEnabledPlatforms];
    }
    
    -(void)SendToEnabledPlatforms
    {
        NSString* json = [NSString stringWithFormat:@"\"%@\"",self.notificationMessage.text];
    
        [self.sendResults setText:@""];
    
        if ([self.WNSSwitch isOn])
            [self SendNotificationASPNETBackend:@"wns" UsernameTag:self.RecipientField.text Message:json];
    
        if ([self.GCMSwitch isOn])
            [self SendNotificationASPNETBackend:@"gcm" UsernameTag:self.RecipientField.text Message:json];
    
        if ([self.APNSSwitch isOn])
            [self SendNotificationASPNETBackend:@"apns" UsernameTag:self.RecipientField.text Message:json];
    }
    
  13. A függvényben ViewDidLoad adja hozzá a következőket a példány példányának RegisterClient létrehozásához, és állítsa be a delegáltat a szövegmezőkhöz.

    self.UsernameField.delegate = self;
    self.PasswordField.delegate = self;
    self.RecipientField.delegate = self;
    self.registerClient = [[RegisterClient alloc] initWithEndpoint:BACKEND_ENDPOINT];
    
  14. Most a fájlban AppDelegate.mtávolítsa el a metódus application:didRegisterForPushNotificationWithDeviceToken: összes tartalmát, és cserélje le a következőre (hogy a nézetvezérlő tartalmazza-e az APN-ekből lekért legújabb eszközkivonatot):

    // Add import to the top of the file
    #import "ViewController.h"
    
    - (void)application:(UIApplication *)application
                didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
        ViewController* rvc = (ViewController*) self.window.rootViewController;
        rvc.deviceToken = deviceToken;
    }
    
  15. Végül a -ben AppDelegate.mgyőződjön meg arról, hogy a következő metódust használja:

    - (void)application:(UIApplication *)application didReceiveRemoteNotification: (NSDictionary *)userInfo {
        NSLog(@"%@", userInfo);
        [self MessageBox:@"Notification" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"]];
    }
    

Az alkalmazás tesztelése

  1. Az XCode-ban futtassa az alkalmazást egy fizikai iOS-eszközön (a leküldéses értesítések nem működnek a szimulátorban).

  2. Az iOS-alkalmazás felhasználói felületén adja meg ugyanazt az értéket a felhasználónév és a jelszó esetében is. Ezután kattintson a Bejelentkezés gombra.

    iOS-tesztalkalmazás

  3. Megjelenik egy előugró ablak, amely tájékoztatja a regisztráció sikerességéről. Kattintson az OK gombra.

    Megjelenik az iOS-tesztértesítés

  4. A *Címzett felhasználónév címkéje szövegmezőbe írja be a regisztrációhoz használt felhasználónevet egy másik eszközről.

  5. Adjon meg egy értesítési üzenetet, és kattintson az Értesítés küldése gombra. Csak azok az eszközök kapják meg az értesítési üzenetet, amelyek rendelkeznek a címzett felhasználónév címkéjével rendelkező regisztrációval. A rendszer csak azoknak a felhasználóknak küldi el.

    iOS-teszt címkézett értesítése

Következő lépések

Ebben az oktatóanyagban elsajátította, hogy hogyan küldhet leküldéses értesítéseket olyan adott felhasználóknak, akik a regisztrációjukhoz társított címkével rendelkeznek. Ha szeretné megtudni, hogy hogyan küldhet helyalapú értesítéseket, lépjen tovább a következő oktatóanyagra: