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.
Megjegyzés
Győződjön meg arról, hogy telepítette a Visual Studio Azure SDK-t a webhely üzembe helyezéséhez.
Indítsa el a Visual Studiót vagy a Visual Studio Expresst.
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.
A Visual Studio Fájl menüjében válassza az Új>projekt lehetőséget.
Írja be a Web API kifejezést a keresőmezőbe.
Válassza ki a ASP.NET Core Webes API-projektsablont, és válassza a Tovább gombot.
Az Új projekt konfigurálása párbeszédpanelen nevezze el a projektet AppBackend néven, és válassza a Tovább gombot.
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
- Távolítsa el a WeatherForecast.cs és a Controllers/WeatherForecastController.cs példafájlokat az új AppBackend projektből.
- Nyissa meg a Properties\launchSettings.json fájlt.
- 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.
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.
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.
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.
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;
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.Az üzenetkezelő regisztrálásához adja hozzá az alábbi kódot a metódus végén a
Register
Program.cs fájlban:config.MessageHandlers.Add(new AuthenticationTestHandler());
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.
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.
A bal oldali ablaktáblán válassza az Online elemet, majd a keresőmezőbe írja be a Microsoft.Azure.NotificationHubs kifejezést.
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.
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.
Adja hozzá a következő
using
-utasítást a Notifications.cs fájl elejéhez:using Microsoft.Azure.NotificationHubs;
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.
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.
Válassza az API-vezérlő – Üres lehetőséget, majd válassza a Hozzáadás lehetőséget.
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.
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;
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()); } }
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.
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.
Adja hozzá a következő
using
-utasításokat a NotificationsController.cs fájlhoz:using AppBackend.Models; using System.Threading.Tasks; using System.Web;
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); }
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.
Kattintson a jobb gombbal az AppBackend projektre, és válassza a Publish (Közzététel) lehetőséget.
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 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.
Válassza a Létrehozás lehetőséget.
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.
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
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.
A fájlban
Main.storyboard
adja hozzá a képernyőképen látható összetevőket az objektumtárból.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.
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;
A fájlban
ViewController.h
adja 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áulhttp://your_backend.azurewebsites.net
:#define BACKEND_ENDPOINT @"<Your backend endpoint>"
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őlNSObject
öröklő osztályt: . Ezután adja hozzá a következő kódot a következőhözRegisterClient.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
A fájlban
RegisterClient.m
frissí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
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 azViewController
osztály állítja be a bejelentkezés után.A fájlban
ViewController.h
adjon hozzá egy utasítást#import
a következőhözRegisterClient.h
: . Ezután adjon hozzá egy deklarációt az eszköz jogkivonatához, és hivatkozzon egyRegisterClient
példányra a@interface
szakaszban:#import "RegisterClient.h" @property (strong, nonatomic) NSData* deviceToken; @property (strong, nonatomic) RegisterClient* registerClient;
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.Ezután a
@implementation
szakaszábanViewController.m
adja 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.
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]; }
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]; }
A függvényben
ViewDidLoad
adja hozzá a következőket a példány példányánakRegisterClient
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];
Most a fájlban
AppDelegate.m
távolítsa el a metódusapplication: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; }
Végül a -ben
AppDelegate.m
győ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
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).
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.
Megjelenik egy előugró ablak, amely tájékoztatja a regisztráció sikerességéről. Kattintson az OK gombra.
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.
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.
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: