Tutorial: Mengirim pemberitahuan push ke pengguna tertentu menggunakan Azure Notification Hubs
Tutorial ini memperlihatkan cara menggunakan Azure Notification Hubs untuk mengirim pemberitahuan push ke pengguna aplikasi tertentu pada perangkat tertentu. Backend ASP.NET WebAPI digunakan untuk mengautentikasi klien dan membuat pemberitahuan, seperti yang ditunjukkan dalam artikel panduan Mendaftar dari backend aplikasi Anda.
Dalam tutorial ini, lakukan langkah-langkah berikut:
- Membuat proyek WebAPI
- Mengautentikasi klien ke backend WebAPI
- Mendaftar untuk pemberitahuan dengan menggunakan backend WebAPI
- Mengirim pemberitahuan dari backend WebAPI
- Terbitkan backend WebAPI baru
- Modifikasi aplikasi iOS Anda
- Uji aplikasi
Prasyarat
Tutorial ini mengasumsikan bahwa Anda telah membuat dan mengonfigurasi hub notifikasi seperti yang dijelaskan di Kirim pemberitahuan push ke aplikasi iOS menggunakan Azure Notification Hubs. Tutorial ini juga merupakan prasyarat untuk tutorial Secure Push (iOS). Jika Anda ingin menggunakan Mobile Apps sebagai layanan backend Anda, lihat Mulai Mobile Apps dengan Push.
Buat proyek WebAPI
Bagian berikut membahas pembuatan backend ASP.NET WebAPI baru. Proses ini memiliki tiga tujuan utama:
- Mengautentikasi klien: Anda menambahkan penangan pesan untuk mengautentikasi permintaan klien dan mengaitkan pengguna dengan permintaan.
- Daftar untuk pemberitahuan dengan menggunakan backend WebAPI: Anda menambahkan pengontrol untuk menangani pendaftaran baru untuk perangkat klien untuk menerima pemberitahuan. Nama pengguna yang diautentikasi secara otomatis ditambahkan ke pendaftaran sebagai tag.
- Kirim pemberitahuan ke klien: Anda menambahkan pengontrol untuk menyediakan cara bagi pengguna untuk memicu dorongan aman ke perangkat dan klien yang terkait dengan tag.
Buat backend API web ASP.NET Core 6.0 dengan melakukan tindakan berikut:
Untuk memeriksa, mulai Visual Studio. Pada menu Alat, pilih Ekstensi dan Pembaruan. Cari NuGet Package Manager di Visual Studio versi Anda, dan pastikan Anda memiliki versi terbaru. Jika versi Anda bukan versi terbaru, hapus instalasinya, lalu instal ulang NuGet Package Manager.
Catatan
Pastikan Anda telah memasang Visual Studio Azure SDK untuk penyebaran situs web.
Mulai Visual Studio atau Visual Studio Express.
Pilih Penjelajah Server, dan masuk ke akun Azure Anda. Untuk membuat sumber daya situs web di akun Anda, Anda harus masuk.
Di menu File Visual Studio, pilih Baru>Proyek.
Masukkan Web API di kotak pencarian.
Pilih templat proyek ASP.NET Core Web API, lalu pilih Berikutnya.
Dalam dialog Konfigurasikan proyek baru, beri nama proyek AppBackend, lalu pilih Berikutnya.
Dalam dialog Informasi tambahan:
- Konfirmasi bahwa Kerangka Kerja adalah .NET 6.0 (Dukungan jangka panjang).
- Konfirmasi bahwa kotak centang untuk Gunakan pengontrol (hapus centang untuk menggunakan API minimal) dicentang.
- Hapus centang Aktifkan dukungan OpenAPI.
- Pilih Buat.
Menghapus file templat WeatherForecast
- Hapus contoh file WeatherForecast.cs dan Controllers/WeatherForecastController.cs dari proyek AppBackend baru.
- Buka Properties\launchSettings.json.
- Ubah properti launchUrl dari weatherforcast menjadi appbackend.
Di jendela Konfigurasikan Microsoft Azure Web App, pilih langganan lalu, di daftar paket Azure App Service, lakukan salah satu tindakan berikut ini:
- Pilih paket Azure App Service yang telah Anda buat.
- Pilih Buat paket layanan aplikasi baru, lalu buat paket.
Anda tidak memerlukan database untuk tutorial ini. Setelah memilih paket layanan aplikasi, pilih OK untuk membuat proyek.
Jika Anda tidak melihat halaman ini untuk mengonfigurasi paket layanan aplikasi, lanjutkan dengan tutorial. Anda dapat mengonfigurasinya saat menerbitkan aplikasi nanti.
Autentikasi klien ke backened WebAPI
Di bagian ini, Anda membuat kelas message-handler baru bernama AuthenticationTestHandler untuk backend baru. Kelas ini berasal dari DelegatingHandler dan ditambahkan sebagai penangan pesan sehingga dapat memproses semua permintaan yang masuk ke backend.
Di Penjelajah Solusi, klik kanan proyek AppBackend, pilih Tambahkan, lalu pilih Kelas.
Beri nama kelas baru AuthenticationTestHandler.cs, lalu pilih Tambahkan untuk menghasilkan kelas. Kelas ini mengautentikasi pengguna dengan menggunakan Otentikasi Dasar untuk kesederhanaan. Aplikasi Anda dapat menggunakan skema autentikasi apa pun.
Di AuthenticationTestHandler.cs, tambahkan pernyataan
using
berikut:using System.Net.Http; using System.Threading; using System.Security.Principal; using System.Net; using System.Text; using System.Threading.Tasks;
Di AuthenticationTestHandler.cs, ganti
AuthenticationTestHandler
definisi kelas dengan kode berikut:Handler mengotorisasi permintaan ketika tiga kondisi berikut ini benar:
- Permintaan ini menyertakan header Otorisasi.
- Permintaan ini menggunakan autentikasi dasar.
- String nama pengguna dan string kata sandi adalah string yang sama.
Jika tidak, permintaan ditolak. Autentikasi ini bukan pendekatan autentikasi dan otorisasi yang benar. Ini hanya contoh sederhana untuk tutorial ini.
Jika pesan permintaan diautentikasi dan diotorisasi oleh
AuthenticationTestHandler
, pengguna otentikasi dasar dilampirkan ke permintaan saat ini di HttpContext. Informasi pengguna di HttpContext akan digunakan oleh pengontrol lain (RegisterController) nantinya untuk menambahkan tag ke permintaan pendaftaran pemberitahuan.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; } }
Catatan
Catatan keamanan: Kelas
AuthenticationTestHandler
tidak menyediakan autentikasi yang benar. Ini hanya digunakan untuk meniru autentikasi dasar dan tidak aman. Anda harus menerapkan mekanisme autentikasi aman dalam aplikasi dan layanan produksi Anda.Untuk mendaftarkan penangan pesan, tambahkan kode berikut di akhir metode
Register
di file Program.cs:config.MessageHandlers.Add(new AuthenticationTestHandler());
Simpan perubahan Anda.
Daftar untuk pemberitahuan dengan menggunakan bakcend WebAPI
Di bagian ini, Anda menambahkan pengontrol baru ke backend WebAPI untuk menangani permintaan untuk mendaftarkan pengguna dan perangkat untuk pemberitahuan dengan menggunakan pustaka klien untuk hub notifikasi. Pengontrol menambahkan tag pengguna untuk pengguna yang diautentikasi dan dilampirkan ke HttpContext oleh AuthenticationTestHandler
. Tag memiliki format string, "username:<actual username>"
.
Pada Penjelajah Solusi, klik kanan proyek AppBackenddan pilih Manage NuGet Packages.
Di panel kiri, pilih Online lalu, dalam kotak Pencarian, ketik Microsoft.Azure.NotificationHubs.
Dalam daftar hasil, pilih Microsoft Azure Notification Hubs, lalu pilih Pasang. Selesaikan penginstalan, lalu tutup jendela NuGet Package Manager.
Tindakan ini menambahkan referensi ke SDK Microsoft Azure Notification Hubs dengan menggunakan paket Microsoft.Azure.Notification Hubs NuGet.
Buat file kelas baru yang mewakili koneksi dengan hub notifikasi yang digunakan untuk mengirim notifikasi. Di Penjelajah Solusi, klik kanan folder Model, pilih Tambahkan, lalu pilih Kelas. Beri nama kelas baruNotifications .cs, lalu pilih Tambahkan untuk membuat kelas.
Di Nitifications.cs, tambahkan
using
pernyataan berikut di bagian atas file:using Microsoft.Azure.NotificationHubs;
Ganti
Notifications
definisi kelas dengan kode berikut, dan ganti dua placeholder dengan string koneksi (dengan akses penuh) untuk hub notifikasi dan nama hub Anda (tersedia di portal Microsoft Azure):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>"); } }
Penting
Masukkan nama dan DefaultListenSharedAccessSignature hub Anda sebelum melanjutkan.
Selanjutnya, buat pengontrol baru bernama RegisterController. Di Penjelajah Solusi,klik kanan folder Pengontrol, pilih Tambahkan, lalu pilih Pengontrol.
Pilih Pengontrol API - Kosong, lalu pilih Tambahkan.
Dalam kotak Nama pengontrol, ketik RegisterController untuk memberi nama kelas baru, lalu pilih Tambahkan.
Di RegisterController.cs, tambahkan pernyataan
using
berikut:using Microsoft.Azure.NotificationHubs; using Microsoft.Azure.NotificationHubs.Messaging; using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Tambahkan kode berikut di dalam
RegisterController
definisi kelas. Dalam kode ini, Anda menambahkan tag pengguna untuk pengguna yang dilampirkan ke HttpContext. Pengguna diautentikasi dan dilampirkan ke HttpContext oleh filter pesan yang Anda tambahkan,AuthenticationTestHandler
. Anda juga dapat menambahkan pemeriksaan opsional untuk memverifikasi bahwa pengguna memiliki hak untuk mendaftarkan tag yang diminta.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()); } }
Simpan perubahan Anda.
Kirim pemberitahuan dari backend WebAPI
Di bagian ini, Anda menambahkan pengontrol baru yang mengekspos cara perangkat klien untuk mengirim pemberitahuan. Pemberitahuan didasarkan pada tag nama pengguna yang menggunakan Azure Notification Hubs .NET Library di ASP.NET backend WebAPI.
Buat pengontrol baru lainnya bernama NotificationsController dengan cara yang sama seperti Anda membuat RegisterController di bagian sebelumnya.
Di NotificationsController.cs, tambahkan
using
pernyataan berikut:using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Tambahkan metode berikut ke kelas NotificationsController:
Kode ini mengirimkan jenis notifikasi yang didasarkan pada parameter Layanan Pemberitahuan Platform
pns
(PNS). Nilaito_tag
digunakan untuk mengatur tag nama pengguna pada pesan. Tag ini harus cocok dengan tag nama pengguna dari pendaftaran hub notifikasi aktif. Pesan pemberitahuan ditarik dari isi permintaan KIRIMAN dan diformat untuk target PNS.Berdasarkan PNS yang digunakan oleh perangkat yang didukung untuk menerima notifikasi, notifikasi didukung oleh berbagai format. Misalnya, pada perangkat Windows, Anda mungkin menggunakan pemberitahuan toast dengan WNS yang tidak didukung langsung oleh PNS lain. Dalam hal demikian, backend Anda perlu memformat pemberitahuan ke pemberitahuan yang didukung untuk PNS perangkat yang Anda rencanakan untuk didukung. Kemudian gunakan API kirim yang sesuai pada kelas NotificationHubClient.
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); }
Untuk menjalankan aplikasi dan memastikan keakuratan pekerjaan Anda sejauh ini, pilih kunci F5. Aplikasi ini membuka browser web, dan ditampilkan di beranda ASP.NET.
Terbitkan backend WebAPI baru
Selanjutnya, Anda menerapkan aplikasi ke situs web Azure untuk membuatnya dapat diakses dari semua perangkat.
Klik kanan proyek AppBackend, lalu pilih Terbitkan.
Pilih Microsoft Azure App Service sebagai target penerbitan Anda, lalu pilih **Terbitkan. Jendela Buat Azure App Service terbuka. Di sini Anda dapat membuat semua sumber daya Azure yang diperlukan untuk menjalankan ASP.NET web di Azure.
Di jendela Buat Azure App Service, pilih akun Azure Anda. Pilih Ubah Jenis>Aplikasi Web. Pertahankan Nama Aplikasi Web default, lalu pilih Langganan, Grup Sumber Daya, dan Paket Azure App Service.
Pilih Buat.
Catat properti URL Situs di bagian Ringkasan. URL ini adalah titik akhir back-end Anda nanti dalam tutorial.
Pilih Terbitkan.
Setelah Anda menyelesaikan wizard, wizard akan menerbitkan aplikasi web ASP.NET ke Azure lalu membuka aplikasi di browser default. Aplikasi Anda dapat dilihat di Azure App Services.
URL menggunakan nama aplikasi web yang Anda tentukan sebelumnya, dengan format http://<
Modifikasi aplikasi iOS Anda
Buka aplikasi tampilan Halaman Tunggal yang Anda buat di tutorial Kirim pemberitahuan push ke aplikasi iOS menggunakan tutorial Azure Notification Hubs.
Catatan
Bagian ini mengasumsikan bahwa proyek Anda dikonfigurasi dengan nama organisasi kosong. Jika tidak, prepend nama organisasi Anda ke semua nama kelas.
Dalam file
Main.storyboard
, tambahkan komponen yang ditampilkan di cuplikan layar dari pustaka objek.Nama Pengguna: UITextField dengan teks tempat penampung, Masukkan Nama Pengguna, tepat di bawah label kirim hasil dan dibatasi ke margin kiri dan kanan dan di bawah label kirim hasil.
KataSandi : UITextField dengan teks tempat penampung, Masukkan Kata Sandi, tepat di bawah bidang teks nama pengguna dan dibatasi ke margin kiri dan kanan dan di bawah bidang teks nama pengguna. Centang opsi Entri Teks Aman di Pemeriksa Atribut, di bawah Kunci Pengembalian.
Masuk: UIButton berlabel tepat di bawah bidang teks kata sandi dan kosongkan opsi Diaktifkan di Pemeriksa Atribut, di bawah Control-Content
WNS: Beri label dan beralih untuk mengaktifkan pengiriman pemberitahuan Windows Notification Service jika telah disiapkan di hub. Lihat tutorial Memulai Windows.
GCM: Beri label dan beralih untuk mengaktifkan pengiriman notifikasi ke Google Cloud Messaging jika telah disiapkan di hub. Lihat tutorial Memulai Android.
APNS: Beri label dan beralih untuk mengaktifkan pengiriman pemberitahuan ke Apple Platform Notification Service.
Nama Penerima: UITextField dengan teks tempat penampung, Masukkan nama penerima, tepat di bawah label GCM dan dibatasi ke margin kiri dan kanan dan di bawah label GCM.
Beberapa komponen ditambahkan dalam tutorial Kirim pemberitahuan push ke aplikasi iOS menggunakan tutorial Azure Notification Hubs.
Ctrl seret dari komponen dalam tampilan ke
ViewController.h
dan tambahkan outlet baru ini:@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;
Dalam
ViewController.h
, tambahkan#define
berikut ini setelah pernyataan impor Anda. Ganti tempat penampung<Your backend endpoint>
dengan URL Tujuan yang Anda gunakan untuk menyebarkan backend aplikasi Anda di bagian sebelumnya. Misalnya,http://your_backend.azurewebsites.net
:#define BACKEND_ENDPOINT @"<Your backend endpoint>"
Dalam proyek Anda, buat kelas Cocoa Touch baru yang dinamai
RegisterClient
untuk antarmuka dengan ASP.NET backend yang Anda buat. Buat kelas yang mewarisi dariNSObject
. Tambahkan kode berikut diRegisterClient.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
Di bagian
RegisterClient.m
, perbarui bagian@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
Ganti bagian
@implementation
di RegisterClient.m dengan kode berikut:@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
Kode ini mengimplementasikan logika yang dijelaskan dalam artikel panduan Mendaftar dari backend aplikasi Anda menggunakan NSURLSession untuk melakukan panggilan REST ke backend aplikasi Anda, dan NSUserDefaults untuk secara lokal menyimpan registrationId yang dikembalikan oleh hub pemberitahuan.
Kelas ini mengharuskan
authorizationHeader
propertinya diatur agar dapat bekerja dengan baik. Properti ini diatur oleh kelasViewController
setelah masuk.Dalam
ViewController.h
, tambahkan pernyataan#import
untukRegisterClient.h
. Kemudian tambahkan deklarasi untuk token perangkat dan referensi ke instansRegisterClient
di bagian@interface
:#import "RegisterClient.h" @property (strong, nonatomic) NSData* deviceToken; @property (strong, nonatomic) RegisterClient* registerClient;
Di ViewController.m, tambahkan deklarasi metode privat di bagian
@interface
ini:@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
Catatan
Cuplikan berikut bukan skema autentikasi yang aman, Anda harus mengganti implementasi
createAndSetAuthenticationHeaderWithUsername:AndPassword:
dengan mekanisme autentikasi tertentu yang menghasilkan token autentikasi untuk digunakan oleh kelas klien register, misalnya OAuth, Active Directory.Kemudian di bagian
@implementation
dariViewController.m
, tambahkan kode berikut, yang menambahkan implementasi untuk mengatur token perangkat dan header autentikasi.-(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; }
Perhatikan cara mengatur token perangkat memungkinkan tombol Masuk. Ini karena sebagai bagian dari tindakan masuk, pengontrol tampilan mendaftar untuk pemberitahuan push dengan backend aplikasi. Anda tidak ingin tindakan Masuk dapat diakses hingga token perangkat telah disiapkan dengan benar. Anda dapat memisahkan masuk dari pendaftaran push selama yang pertama terjadi sebelum yang terakhir.
Di ViewController.m, gunakan cuplikan berikut untuk mengimplementasikan metode tindakan untuk tombol Masuk dan metode untuk mengirim pesan pemberitahuan menggunakan backend ASP.NET Anda.
- (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]; }
Perbarui tindakan untuk tombol Kirim Pemberitahuan untuk menggunakan backend ASP.NET dan kirim ke PNS yang diaktifkan oleh sakelar.
- (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]; }
Dalam fungsi
ViewDidLoad
, tambahkan yang berikut ini untuk membuat instansiRegisterClient
instans dan mengatur delegasi untuk bidang teks Anda.self.UsernameField.delegate = self; self.PasswordField.delegate = self; self.RecipientField.delegate = self; self.registerClient = [[RegisterClient alloc] initWithEndpoint:BACKEND_ENDPOINT];
Sekarang di
AppDelegate.m
, hapus semua konten metodeapplication:didRegisterForPushNotificationWithDeviceToken:
dan ganti dengan yang berikut (untuk memastikan bahwa pengontrol tampilan berisi token perangkat terbaru yang diambil dari APN):// 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; }
Akhirnya di
AppDelegate.m
, pastikan Anda memiliki metode berikut:- (void)application:(UIApplication *)application didReceiveRemoteNotification: (NSDictionary *)userInfo { NSLog(@"%@", userInfo); [self MessageBox:@"Notification" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"]]; }
Uji aplikasi
Di XCode, jalankan aplikasi pada perangkat iOS fisik (pemberitahuan push tidak berfungsi di simulator).
Di UI aplikasi iOS, masukkan nilai yang sama untuk nama pengguna dan kata sandi. Lalu klik Masuk.
Anda akan melihat pop-up yang memberi tahu Anda tentang keberhasilan pendaftaran. Klik OK.
Di bidang teks *tag nama pengguna Penerima, masukkan tag nama pengguna yang digunakan dengan pendaftaran dari perangkat lain.
Masukkan pesan pemberitahuan dan klik Kirim Pemberitahuan. Hanya perangkat yang memiliki pendaftaran dengan tag nama pengguna penerima yang menerima pesan pemberitahuan. Ini hanya dikirim ke pengguna tersebut.
Langkah berikutnya
Dalam tutorial ini, Anda sudah mempelajari cara mengirim pemberitahuan push kepada pengguna tertentu yang memiliki tag terkait dengan pendaftaran mereka. Untuk mempelajari cara membuat pemberitahuan push berbasis lokasi, lanjutkan ke tutorial berikut:
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk