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 való 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ű szakaszban leírtak szerint. Ez az oktatóanyag a Biztonságos leküldés (iOS) oktatóanyag előfeltétele is. Ha a Mobile Apps szolgáltatást szeretné háttérszolgáltatásként használni, tekintse meg a Mobile Apps Első lépések a Leküldéses szolgáltatással.
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 webhely üzembe helyezéséhez szükséges Visual Studio Azure SDK-t.
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.
Visual Studio Fájl menüjében válassza az Új>Project lehetőséget.
Írja be a webes API-t 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 be van-e jelölve a Vezérlők használata jelölőnégyzet (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ésének 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. Ezt 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á a következő kódot a
Register
metódus végén a 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 Controller – Üres lehetőséget, majd 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 a 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 Change TypeWeb App (Típuswebalkalmazás>módosítása) 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ával létrehozott egyoldalas nézetalkalmazást.
Megjegyzés
Ez a szakasz feltételezi, hogy a projekt üres szervezetnévvel van konfigurálva. Ha nem, a szervezet nevét az összes osztálynévre fel kell függesztetnie.
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 rendelkező UITextField, írja be a felhasználónevet, közvetlenül az eredmények küldése címke alatt, a bal és jobb margókra korlátozva, valamint a küldési eredmények címkéje alatt.
Jelszó: Egy helyőrző szöveggel rendelkező UITextField, írja be a jelszót, közvetlenül a felhasználónév szövegmezője alatt, a bal és jobb margókra korlátozva, valamint a felhasználónév szövegmezője alatt. 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 felcímkézett UIButton, és törölje az Attribútumfelügyelő Engedélyezett jelölőnégyzetének jelölését a Control-Content területen.
WNS: Címkézzen és váltson úgy, hogy engedélyezze az értesítés küldését Windows értesítési szolgáltatásnak, 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 Messaging szolgáltatásba való küldésének engedélyezéséhez, ha az már be van állítva a központban. Tekintse meg az Android Első lépések oktatóanyagát.
APNS: Címke és váltás az értesítés Apple Platform Notification Service-nek való küldéséhez.
Címzett felhasználóneve:Egy helyőrző szöveggel ellátott UITextField mező, a címzett felhasználónév címkéje, közvetlenül a GCM-címke alatt, a bal és jobb margókra korlátozva, valamint a GCM-címke alatt.
Az Azure Notification Hubs oktatóanyaga néhány összetevőt tartalmazott a Leküldéses értesítések küldése iOS-alkalmazásokba című oktatóanyagban.
A nézetben
ViewController.h
lévő összetevőkből a Ctrl billentyű lenyomásával felveheti az alábbi új aljzatokat:@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;
Adja
ViewController.h
hozzá a következőt#define
az importálási utasítások után. Helyettesítse be a<Your backend endpoint>
helyőrzőt az előző szakaszban az alkalmazás háttérrendszerének üzembe helyezéséhez használt cél URL-címmel. Példáulhttp://your_backend.azurewebsites.net
:#define BACKEND_ENDPOINT @"<Your backend endpoint>"
A projektben hozzon létre egy új Cocoa Touch-osztályt, amely a létrehozott ASP.NET háttérrendszerrel való interfészhez van elnevezve
RegisterClient
. Hozza létre a következőtőlNSObject
öröklő osztályt: . Ezután adja hozzá a következő kódot a következőhezRegisterClient.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
RegisterClient.m
A szakaszban 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 implementálja az útmutatóban ismertetett logikát, amely az alkalmazás háttérrendszeréből történő regisztrációt az NSURLSession használatával hajtja végre az alkalmazás háttérrendszeréhez irányuló REST-hívások végrehajtásához, az NSUserDefaults pedig helyileg tárolja az értesítési központ által visszaadott regisztrációs azonosítót.
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.In
ViewController.h
, add a#import
statement forRegisterClient.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átmetódus-deklarációt a
@interface
szakaszhoz:@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
Az alábbi 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 (pl. OAuth, Active Directory) használ fel.Ezután a szakaszba
ViewController.m
írja be a@implementation
következő kódot, amely hozzáadja az eszközjogkivonat és a hitelesítési fejléc beállításának implementációjá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 engedélyezi 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ési művelet elérhető legyen, amíg az eszköz jogkivonata nincs megfelelően beá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-ben az alábbi kódrészletekkel implementálhatja a Bejelentkezési gomb műveletmetódusát, és 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];
AppDelegate.m
Most távolítsa el a metódusapplication:didRegisterForPushNotificationWithDeviceToken:
összes tartalmát, és cserélje le a következőre (győződjön meg arról, hogy a nézetvezérlő tartalmazza az APN-ekből lekért legújabb eszközjogkivonatot):// 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; }
AppDelegate.m
Végül győződjön meg arról, hogy rendelkezik a következő módszerrel:- (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évhez és a jelszóhoz 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óneve címkével rendelkező regisztrációval. A rendszer csak ezeknek 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: