Öğretici: Azure Notification Hubs kullanarak belirli kullanıcılara anında iletme bildirimleri gönderme
Bu öğreticide, belirli bir cihazdaki belirli bir uygulama kullanıcısına anında iletme bildirimleri göndermek için Azure Bildirim Hubs’ı nasıl kullanacağınız gösterilmektedir. ASP.NET WebAPI arka ucu, uygulama arka ucunuzdan kaydolma kılavuz konusunda gösterildiği gibi istemcilerin kimliğini doğrulamak ve bildirimler oluşturmak için kullanılır.
Bu öğreticide, aşağıdaki adımları gerçekleştireceksiniz:
- WebAPI projesi oluşturma
- WebAPI arka ucunda istemcilerin kimliğini doğrulama
- WebAPI arka ucunu kullanarak bildirimlere kaydolma
- WebAPI arka ucundan bildirim gönderme
- Yeni WebAPI arka ucunu yayımlama
- iOS uygulamanızı değiştirme
- Uygulamayı test edin
Önkoşullar
Bu öğreticide, Azure Notification Hubs kullanarak iOS uygulamalarına anında iletme bildirimleri gönderme başlığında açıklandığı gibi bildirim hub'ınızı oluşturduğunuz ve yapılandırdığınız varsayılır. Bu öğretici, Güvenli Gönderme (iOS) öğreticisinin de önkoşuludur. Arka uç hizmetiniz olarak Mobile Apps'i kullanmak istiyorsanız bkz. Mobile Apps Göndermeye Başlama.
WebAPI projesi oluşturma
Aşağıdaki bölümlerde, yeni bir ASP.NET WebAPI arka ucu oluşturma işlemi açıklanmaktadır. Bu işlemin üç ana amacı vardır:
- İstemcilerin kimliğini doğrulama: İstemci isteklerinin kimliğini doğrulamak ve kullanıcıyı istekle ilişkilendirmek üzere bir ileti işleyicisi eklersiniz.
- WebAPI arka ucunu kullanarak bildirimlere kaydolma: Bir istemci cihazının bildirimleri alması için yeni kayıtları işlemek üzere bir denetleyici eklersiniz. Kimliği doğrulanmış kullanıcı adı, otomatik olarak kayda bir etiket halinde eklenir.
- İstemcilere bildirimleri gönderme: Kullanıcıların etiketle ilişkili cihazlara ve istemcilere güvenli bir gönderimi tetiklemesi için yeni bir yol sağlamak üzere bir denetleyici de eklersiniz.
Aşağıdaki eylemleri gerçekleştirerek yeni ASP.NET Core 6.0 web API'sinin arka ucu oluşturun:
Denetlemek için Visual Studio’yu başlatın. Araçlar menüsünde Uzantılar ve Güncelleştirmeler’i seçin. Visual Studio sürümünüz için NuGet Paket Yöneticisi araması yapın ve en son sürümü kullandığınızdan emin olun. Sürümünüz en son sürüm değilse, bunu kaldırın ve NuGet Paket Yöneticisi'ni yeniden yükleyin.
Not
Web sitesi dağıtımı için Visual Studio Azure SDK'sını yüklediğinizden emin olun.
Visual Studio veya Visual Studio Express’i başlatın.
Sunucu Gezgini’ni seçip Azure hesabınızda oturum açın. Hesabınızda web sitesi kaynakları oluşturmak için oturum açmanız gerekir.
Visual Studio'nun Dosya menüsünde Yeni Proje'yi> seçin.
Arama kutusuna Web API'sini girin.
ASP.NET Core Web API proje şablonunu seçin ve İleri'yi seçin.
Yeni projenizi yapılandırın iletişim kutusunda projeyi AppBackend olarak adlandırın ve İleri'yi seçin.
Ek bilgiler iletişim kutusunda:
- Framework'ün.NET 6.0 (Uzun vadeli destek) olduğunu onaylayın.
- Denetleyicileri kullan (en az API kullanmak için işaretini kaldır) onay kutusunun işaretli olduğunu onaylayın.
- OpenAPI desteğini etkinleştir seçeneğinin işaretini kaldırın.
- Oluştur’u seçin.
WeatherForecast şablon dosyalarını kaldırma
- Yeni AppBackend projesinden WeatherForecast.cs ve Controllers/WeatherForecastController.cs örnek dosyalarını kaldırın.
- Properties\launchSettings.json dosyasını açın.
- launchUrl özelliklerini weatherforcast olan appbackend olarak değiştirin.
Microsoft Azure Web App’i yapılandırma penceresinde, bir abonelik seçin ve App Service planı listesinde aşağıdaki eylemlerden birini yapın:
- Önceden oluşturduğunuz bir Azure App Service planı seçin.
- Yeni bir App Service planı oluştur’u seçin ve yeni bir plan oluşturun.
Bu öğretici için bir veritabanı gerekmez. App Service planınızı seçtikten sonra projeyi oluşturmak için Tamam’ı seçin.
App Service planını yapılandırmak için bu sayfayı görmüyorsanız öğreticiye devam edin. Uygulamayı daha sonra yayımlarken yapılandırabilirsiniz.
WebAPI arka ucunda istemcilerin kimliğini doğrulama
Bu bölümde, yeni arka uç için AuthenticationTestHandler adlı yeni bir ileti işleyicisi oluşturacaksınız. Bu sınıf DelegatingHandler’dan türetilip bir ileti işleyicisi olarak eklenir, böylece arka uca gelen tüm istekleri işleyebilir.
Çözüm Gezgini'nde AppBackend projesine sağ tıklayın, Ekle'yi ve ardından Sınıf'ı seçin.
Yeni AuthenticationTestHandler.cs sınıfını adlandırıp Ekle’yi seçerek sınıfı oluşturun. Bu sınıf, kolaylık için Temel Kimlik Doğrulaması kullanarak kullanıcıların kimliklerini doğrular. Uygulamanız herhangi bir kimlik doğrulama şemasını kullanabilir.
AuthenticationTestHandler.cs sınıfına aşağıdaki
using
deyimlerini ekleyin:using System.Net.Http; using System.Threading; using System.Security.Principal; using System.Net; using System.Text; using System.Threading.Tasks;
AuthenticationTestHandler.cs sınıfında
AuthenticationTestHandler
sınıf tanımını aşağıdaki kod ile değiştirin:Bu işleyici aşağıdaki üç koşul geçerli olduğunda bu isteği yetkilendirir:
- İstek bir Yetkilendirme üst bilgisi içerir.
- İstek temel kimlik doğrulaması kullanır.
- Kullanıcı adı dizesi ve parola dizesi aynı dizelerdir.
Aksi takdirde istek reddedilir. Bu kimlik doğrulama işlemi, geçerli bir kimlik doğrulama ve yetkilendirme yaklaşımı değildir. Yalnızca bu öğreticiye yönelik basit bir örnektir.
İstek iletisi
AuthenticationTestHandler
tarafından kimlik doğrulaması yapılır ve yetkilendirilirse, temel kimlik doğrulaması kullanıcısı HttpContext üzerindeki geçerli isteğe eklenir. HttpContext içindeki kullanıcı bilgileri, bildirim kaydı isteğine bir etiket eklemek amacıyla daha sonra başka bir denetleyici (RegisterController) tarafından kullanılır.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; } }
Not
Güvenlik notu:
AuthenticationTestHandler
sınıfı gerçek kimlik doğrulaması sağlamaz. Yalnızca temel kimlik doğrulamasını taklit etmek için kullanılır ve güvenli değildir. Üretim uygulamalarınızda ve hizmetlerinizde güvenli bir kimlik doğrulama mekanizması uygulamanız gerekir.İleti işleyicisini kaydetmek için Program.cs dosyasında yönteminin
Register
sonuna aşağıdaki kodu ekleyin:config.MessageHandlers.Add(new AuthenticationTestHandler());
Yaptığınız değişiklikleri kaydedin.
WebAPI arka ucunu kullanarak bildirimlere kaydolma
Bu bölümde, bildirim hub’ları için istemci kitaplığını kullanarak WebAPI arka ucuna bir kullanıcı ve cihazı bildirimlere kaydetme isteklerini işlemek üzere yeni bir denetleyici ekleyeceksiniz. Denetleyici, kimliği doğrulanmış ve AuthenticationTestHandler
tarafından HttpContext’e eklenmiş kullanıcı için bir kullanıcı etiketi ekler. Etiket "username:<actual username>"
dize biçiminde olacaktır.
Çözüm Gezgini'nde, AppBackend projesine sağ tıklayın ve ardından NuGet Paketlerini Yönet'i seçin.
Sol bölmede Çevrimiçi’ni seçin ve Arama kutusuna Microsoft.Azure.NotificationHubs yazın.
Sonuç listesinde Microsoft Azure Notification Hubs’ı ve ardından Yükle’yi seçin. Yüklemeyi tamamlayın ve sonra NuGet Paket Yöneticisi penceresini kapatın.
Bu eylem Microsoft.Azure.Notification Hubs NuGet paketini kullanarak Azure Notification Hubs SDK'sına bir başvuru ekler.
Bildirimleri göndermek için kullanılan bildirim hub'ı bağlantısını temsil eden yeni bir sınıf dosyası oluşturun. Çözüm Gezgini'nde Modeller klasörüne sağ tıklayın, Ekle'yi ve ardından Sınıf'ı seçin. Yeni sınıfı Notifications.cs olarak adlandırın, ardından Ekle’yi seçerek sınıfı oluşturun.
Notifications.cs sınıfında aşağıdaki
using
deyimini dosyanın üst kısmına ekleyin:using Microsoft.Azure.NotificationHubs;
Notifications
sınıf tanımını aşağıdaki kodla değiştirin ve iki yer tutucuyu bildirim hub’ınızın bağlantı dizesi (tam erişimli) ve hub adı ile değiştirdiğinizden emin olun (Azure portalında bulunabilir):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>"); } }
Önemli
Devam etmeden önce hub'ınızın adını ve DefaultFullSharedAccessSignature değerini girin.
Ardından RegisterController adlı yeni bir denetleyici oluşturun. Çözüm Gezgini'nde Denetleyiciler klasörüne sağ tıklayın, Ekle'yi ve ardından Denetleyici'yi seçin.
API Denetleyicisi - Boş'u ve ardından Ekle'yi seçin.
Denetleyici adı kutusuna, yeni sınıfı adlandırmak için RegisterController yazın ve Ekle’yi seçin.
RegisterController.cs sınıfına aşağıdaki
using
deyimlerini ekleyin:using Microsoft.Azure.NotificationHubs; using Microsoft.Azure.NotificationHubs.Messaging; using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Aşağıdaki kodu
RegisterController
sınıf tanımına ekleyin. Bu kodda, HttpContext’e eklenen kullanıcı için bir kullanıcı etiketi eklersiniz. Kullanıcının kimliği doğrulanmış ve eklediğinizAuthenticationTestHandler
ileti filtresi tarafından HttpContext’e eklenmiştir. Ayrıca, kullanıcının istenen etiketlere kaydolma haklarının olduğunu doğrulamak için isteğe bağlı denetimler ekleyebilirsiniz.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()); } }
Yaptığınız değişiklikleri kaydedin.
WebAPI arka ucundan bildirim gönderme
Bu bölümde, istemci cihazlarına bildirim göndermeleri için bir yol sunan yeni bir denetleyici ekleyeceksiniz. Bildirim, ASP.NET WebAPI arka ucundaki Azure Notification Hubs .NET Kitaplığı’nı kullanan kullanıcı adı etiketini temel alır.
Önceki bölümde RegisterController denetleyicisini oluşturduğunuz gibi NotificationsController adlı yeni bir denetleyici oluşturun.
NotificationsController.cs sınıfına aşağıdaki
using
deyimlerini ekleyin:using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Aşağıdaki yöntemi NotificationsController sınıfına ekleyin:
Bu kod, Platform Bildirim Hizmeti (PNS)
pns
parametresini temel alan bir bildirim türü gönderir.to_tag
değeri, iletideki kullanıcı adı etiketini ayarlamak için kullanılır. Bu etiket, etkin bir bildirim hub'ı kaydının kullanıcı etiketi ile eşleşmelidir. Bildirim iletisi, POST isteğinin gövdesinden çekilir ve hedef PNS biçimlendirilir.Desteklenen cihazlarınızın bildirimleri almak için kullandığı PNS’e bağlı olarak, bildirimler çeşitli biçimler tarafından desteklenmektedir. Örneğin, Windows cihazlarında başka bir PNS tarafından doğrudan desteklenmeyen bir WNS ile bildirim kullanabilirsiniz. Böyle bir durumda arka ucunuzun, desteklemeyi planladığınız cihazların PNS’si için bildirimi desteklenen bir bildirim biçimine dönüştürmesi gerekir. Daha sonra NotificationHubClient sınıfında uygun gönderme API’sini kullanın.
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); }
Uygulamayı çalıştırmak ve o ana kadar gerçekleştirdiğiniz işin doğruluğundan emin olmak için F5 tuşuna basın. Uygulama bir web tarayıcısı açar ve ASP.NET giriş sayfasında görüntülenir.
Yeni WebAPI arka ucunu yayımlama
Ardından bu uygulamayı tüm cihazlardan erişilebilir kılmak için bir Azure web sitesine dağıtacaksınız.
AppBackend projesine sağ tıklayıp Yayımla’yı seçin.
Yayımlama hedefi olarak Microsoft Azure App Service’i ve ardından \*\*Yayımla’yı seçin. App Service Oluştur penceresi açılır. Burada, Azure’da ASP.NET web uygulamasını çalıştırmak için gereken tüm Azure kaynaklarını oluşturabilirsiniz.
App Service Oluştur penceresinde Azure hesabınızı seçin. Tür>Web Uygulamasını Değiştir'i seçin. Varsayılan Web App Adı’nı değiştirmeyin ve Abonelik, Kaynak Grubu ve App Service Planı’nı seçin.
Oluştur’u seçin.
Özet bölümündeki Site URL özelliğini not edin. Bu URL, daha sonra bu öğreticide arka uca ait uç noktanız olacaktır.
Yayımla’yı seçin.
Sihirbazı tamamladıktan sonra ASP.NET web uygulamasını Azure’da yayımlar ve ardından uygulamayı varsayılan tarayıcıda açar. Uygulamanız Azure App Services’te görüntülenebilir.
URL, daha önce belirttiğiniz web uygulaması adını http://< app_name.azurewebsites.net> biçiminde kullanır.
iOS uygulamanızı değiştirme
Azure Notification Hubs kullanarak iOS uygulamalarına anında iletme bildirimleri gönderme öğreticisinde oluşturduğunuz Tek Sayfa görünümü uygulamasını açın.
Not
Bu bölümde, projenizin boş bir kuruluş adıyla yapılandırıldığı varsayılır. Aksi takdirde, kuruluşunuzun adını tüm sınıf adlarına ekleyin.
Main.storyboard
dosyasında, nesne kitaplığındaki ekran görüntüsünde gösterilen bileşenleri ekleyin.Kullanıcı adı: Yer tutucu metin içeren bir UITextField, Sonuç gönderme etiketinin hemen altında ve sol ve sağ kenar boşluklarına ve sonuçları gönderme etiketinin altına kısıtlanmış Kullanıcı Adı girin.
Parola: Kullanıcı adı metin alanının hemen altında, sol ve sağ kenar boşluklarına ve kullanıcı adı metin alanının altına kısıtlanmış, yer tutucu metin içeren Bir UITextField , Parola Girin. Öznitelik Denetçisi'nde, Dönüş Anahtarı'nın altındaki Güvenli Metin Girişi seçeneğini işaretleyin.
Oturum açın: Parola metin alanının hemen altında etiketlenmiş bir UIButton düğmesi ve Control-Content altındaki Öznitelikler Denetçisi'nde Etkin seçeneğinin işaretini kaldırın
WNS: Hub'da ayarlandıysa bildirim Windows Bildirim Hizmeti'ni göndermeyi etkinleştirin ve etkinleştirin. Bkz. Windows Kullanmaya Başlama öğreticisi.
GCM: Hub'da ayarlanmışsa, bildirimi Google Cloud Messaging'e göndermeyi etiketleyin ve etkinleştirin. Bkz. Android Kullanmaya Başlama öğreticisi.
APNS: Apple Platform Bildirim Hizmeti'ne bildirim göndermeyi etkinleştirmek için etiketleyip geçiş yapın.
Alıcı Kullanıcı Adı: Yer tutucu metin içeren bir UITextField, GcM etiketinin hemen altında, sol ve sağ kenar boşluklarıyla GCM etiketinin altında kısıtlanmış Alıcı kullanıcı adı etiketi.
Azure Notification Hubs kullanarak iOS uygulamalarına anında iletme bildirimleri gönderme öğreticisine bazı bileşenler eklendi.
Ctrl tuşunu basılı tutarak görünümdeki
ViewController.h
bileşenlerden şu yeni çıkışları ekleyin:@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;
içinde
ViewController.h
, içeri aktarma deyimlerinizden sonra aşağıdakileri#define
ekleyin. Yer tutucuyu<Your backend endpoint>
, önceki bölümde uygulamanızın arka ucu dağıtmak için kullandığınız Hedef URL ile değiştirin. Örneğin,http://your_backend.azurewebsites.net
:#define BACKEND_ENDPOINT @"<Your backend endpoint>"
Projenizde oluşturduğunuz ASP.NET arka ucuyla arabirim oluşturmak için adlı
RegisterClient
yeni bir Cocoa Touch sınıfı oluşturun. öğesindenNSObject
devralan sınıfı oluşturun. Ardından içine aşağıdaki koduRegisterClient.h
ekleyin:@interface RegisterClient : NSObject @property (strong, nonatomic) NSString* authenticationHeader; -(void) registerWithDeviceToken:(NSData*)token tags:(NSSet*)tags andCompletion:(void(^)(NSError*))completion; -(instancetype) initWithEndpoint:(NSString*)Endpoint; @end
içinde
RegisterClient.m
bölümünü güncelleştirin@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
@implementation
RegisterClient.m dosyasındaki bölümünü aşağıdaki kodla değiştirin:@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
Bu kod, uygulamanızın arka ucuna REST çağrıları gerçekleştirmek için NSURLSession kullanarak uygulama arka ucunuzdan kaydolma ve bildirim hub'ı tarafından döndürülen registrationId değerini yerel olarak depolamak için NSUserDefaults kılavuz makalesinde açıklanan mantığı uygular.
Bu sınıf, düzgün çalışması için özelliğinin
authorizationHeader
ayarlanmasını gerektirir. Bu özellik, oturum açmadanViewController
sonra sınıfı tarafından ayarlanır.içinde
ViewController.h
için bir#import
deyimiRegisterClient.h
ekleyin. Ardından cihaz belirteci için bir bildirim ve bölümünde birRegisterClient
örneğe@interface
başvuru ekleyin:#import "RegisterClient.h" @property (strong, nonatomic) NSData* deviceToken; @property (strong, nonatomic) RegisterClient* registerClient;
ViewController.m'de
@interface
bölümüne bir özel yöntem bildirimi ekleyin:@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
Not
Aşağıdaki kod parçacığı güvenli bir kimlik doğrulama şeması değildir; uygulamasını
createAndSetAuthenticationHeaderWithUsername:AndPassword:
, yazmaç istemci sınıfı tarafından kullanılacak bir kimlik doğrulama belirteci oluşturan özel kimlik doğrulama mekanizmanızla (örneğin, OAuth, Active Directory) değiştirmelisiniz.@implementation
Ardından bölümünde, cihaz belirteciniViewController.m
ve kimlik doğrulama üst bilgisini ayarlamak için uygulamayı ekleyen aşağıdaki kodu ekleyin.-(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; }
Cihaz belirtecinin ayarlanmasının Oturum aç düğmesini nasıl etkinleştirenlere dikkat edin. Bunun nedeni, oturum açma eyleminin bir parçası olarak görünüm denetleyicisinin uygulama arka ucuyla anında iletme bildirimlerine kaydolmasıdır. Cihaz belirteci düzgün şekilde ayarlanana kadar Oturum açma eyleminin erişilebilir olmasını istemezsiniz. Önceki kayıttan önce olduğu sürece, giriş bilgilerini anında iletme kaydından ayrıştırabilirsiniz.
ViewController.m'de, Oturum aç düğmenizin eylem yöntemini uygulamak için aşağıdaki kod parçacıklarını ve ASP.NET arka ucu kullanarak bildirim iletisini gönderme yöntemini kullanın.
- (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]; }
Bildirim Gönder düğmesinin eylemini, ASP.NET arka ucu kullanacak ve bir anahtar tarafından etkinleştirilen herhangi bir PNS'ye gönderecek şekilde güncelleştirin.
- (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]; }
işlevinde
ViewDidLoad
örneği başlatmakRegisterClient
ve metin alanlarınız için temsilciyi ayarlamak için aşağıdakileri ekleyin.self.UsernameField.delegate = self; self.PasswordField.delegate = self; self.RecipientField.delegate = self; self.registerClient = [[RegisterClient alloc] initWithEndpoint:BACKEND_ENDPOINT];
Şimdi içinde
AppDelegate.m
yöntemininapplication:didRegisterForPushNotificationWithDeviceToken:
tüm içeriğini kaldırın ve şununla değiştirin (görünüm denetleyicisinin APN'lerden alınan en son cihaz belirtecini içerdiğinden emin olmak için):// 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; }
Son olarak içinde
AppDelegate.m
aşağıdaki yönteme sahip olduğunuzdan emin olun:- (void)application:(UIApplication *)application didReceiveRemoteNotification: (NSDictionary *)userInfo { NSLog(@"%@", userInfo); [self MessageBox:@"Notification" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"]]; }
Uygulamayı test edin
XCode'da uygulamayı fiziksel bir iOS cihazında çalıştırın (anında iletme bildirimleri simülatörde çalışmaz).
iOS uygulama kullanıcı arabiriminde hem kullanıcı adı hem de parola için aynı değeri girin. Ardından Oturum aç'a tıklayın.
Kayıt başarısı konusunda sizi bilgilendiren bir açılır pencere görmeniz gerekir. Tamam'a tıklayın.
*Alıcı kullanıcı adı etiketi metin alanına, başka bir cihazdan kayıtta kullanılan kullanıcı adı etiketini girin.
Bir bildirim iletisi girin ve Bildirim Gönder'e tıklayın. Yalnızca alıcı kullanıcı adı etiketiyle kaydı olan cihazlar bildirim iletisini alır. Yalnızca bu kullanıcılara gönderilir.
Sonraki adımlar
Bu öğreticide, kayıtlarıyla ilişkili etiketleri olan belirli kullanıcılara anında iletme bildirimleri göndermeyi öğrendiniz. Konum tabanlı anında iletme bildirimleri göndermeyi öğrenmek için aşağıdaki öğreticiye ilerleyin: