In this blog, we are going to learn how to build an Ionic Angular app for implementing Firebase push notifications for both Android and iOS. We’ll create an ASP.NET project with SQL to send Firebase push notifications.
To check whether Node.js is already installed in your machine, ask for its version using the following command. If it is already installed, it returns the version number.
node -v v14.18.0
Otherwise, it returns the following error.
npm -v 6.14.15
Otherwise, it returns the following error.
ng version Angular CLI : 13.2.3
To check whether the Ionic CLI is already installed in your machine, execute the following command to ask for its version. If it is already installed, it returns the version details.
ionic info
Package | Command |
Node.js | Node.js |
npm | Installing Node.js will install npm. |
Angular CLI | npm i @angular/cli |
Ionic | npm install -g ionic |
After ensuring that the Angular CLI and Ionic are installed, create a new Ionic-with-Angular app using the following command. I am naming my app PushNotificationApp.
ionic start PushNotificationApp
Let’s install Capacitor in our app using the following command.
> ionic integrations enable capacitor
> cd .\PushNotificationApp
Run the npx cap init command. It will allow us to fill out our app’s information like the app name and Package ID to initialize Capacitor configuration.
npx cap init > App name: PushNotificationApp > App Package ID: com.pushnotification.app
Refer to the following screenshot.
Before adding any native platforms to this project, the app must be built at least once. A web build creates the web assets directory that Capacitor needs (www folder in Ionic Angular projects). Use the following command to build the project.
> Ionic build
Let’s add the iOS and Android platforms to this app in this section.
Before adding the Android platform, make sure to install the capacitor/android package using the following command.
> npm install @capacitor/android
Now, add the Android platform using the next command.
> npx cap add android
By running these commands, Android folders are created at the root of the project.
> npm install @capacitor/ios
Now, add the iOS platform with the next command.
> npx cap add ios
Running these commands creates iOS folders at the root of the project.
Create common services to invoke Web API calls and the HTTPClient inside the Service folder using the following command.
Let’s point to the projects src/app folder and run the following commands.
PushNotificationApp /src/app> ionic generate service Service/WebApi PushNotificationApp /src/app> ionic generate service Service/HttpProvider
Add the following code in the web-api.service.ts file in the following locations.
src/app/Service/web-api.service.ts
import { Injectable } from '@angular/core'; import { Observable, throwError } from 'rxjs'; import { map } from 'rxjs/operators'; import { catchError } from 'rxjs/internal/operators/catchError'; import { HttpHeaders, HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class WebApiService { constructor(private httpClient: HttpClient) { } // Post call method // Param 1 : url // Param 2 : model post(url: string, model: any): Observable<any> { const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }), observe: "response" as 'body' }; return this.httpClient.post( url, model, httpOptions) .pipe( map((response: any) => this.ReturnResponseData(response)), catchError(this.handleError) ); } private ReturnResponseData(response: any) { return response; } private handleError(error: any) { return throwError(error); } }
src/app/Service/http-provider.service.ts
import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { WebApiService } from './web-api.service'; var apiUrl = "https://localhost:44370/"; var httpLink = { addPushNotification: apiUrl + "api/pushNotification/addPushNotification", sendPushNotification: apiUrl + "api/pushNotification/sendPushNotification" } @Injectable({ providedIn: 'root' }) export class HttpProviderService { constructor(private webApiService: WebApiService) { } public addPushNotification(pushNotificationsDetail: any): Observable<any> { return this.webApiService.post(httpLink.addPushNotification , pushNotificationsDetail); } public sendPushNotification(pushNotificationsDetail: any): Observable<any> { return this.webApiService.post(httpLink.sendPushNotification,pushNotificationsDetail); } }
First, install the following push notification plugin to enable push notifications.
> npm install @capacitor/push-notifications
In the app.component.ts file, add the import section and const to make use of the push notification API.
const { PushNotifications } = Plugins; import { Plugins, PushNotification, PushNotificationToken, PushNotificationActionPerformed } from ‘@capacitor/core’;
Then, add the push notifications API for registration, registrationError, pushNotificationReceived, and pushNotificationActionPerformed inside the ngOnInit() function in app.component.ts to register and monitor push notifications.
Refer to the following code example.
PushNotifications.requestPermission().then(result => { if (result.granted) { PushNotifications.register(); } else { } }); PushNotifications.addListener('registration', (token: PushNotificationToken) => { let registrationToken = token.value; }); PushNotifications.addListener('registrationError', (error: any) => { }); PushNotifications.addListener('pushNotificationReceived', (notification: PushNotification) => { }); PushNotifications.addListener('pushNotificationActionPerformed', (args: PushNotificationActionPerformed) => { } );
registration: Used to register the push notification token of the app during installation.
registrationError: Used to handle any error occurring during the registration.
pushNotificationReceived: Used to handle notifications received when the app screen is active.
pushNotificationActionPerformed: Used to handle the action to be performed when interacting with a push notification.
I’ve shared the complete code of app.component.ts for your reference.
import { Component } from '@angular/core'; import { Plugins, PushNotification, PushNotificationToken, PushNotificationActionPerformed } from '@capacitor/core'; import { AlertController, Platform } from '@ionic/angular'; import { HttpProviderService } from './Service/http-provider.service'; const { PushNotifications } = Plugins; @Component({ selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.scss'], }) export class AppComponent { notificationDetail = { title: '', body: '' }; constructor(private alertCtrl: AlertController, private httpProvider: HttpProviderService, private platform: Platform) { } ngOnInit() { PushNotifications.requestPermission().then(result => { if (result.granted) { PushNotifications.register(); } else { } }); PushNotifications.addListener('registration', (token: PushNotificationToken) => { let registrationToken = token.value; if (registrationToken != null && registrationToken != 'null') { localStorage.setItem("registrationToken", registrationToken); var DeviceType = 0; if (this.platform.is("android")) { DeviceType = 1; } else if (this.platform.is("ios")) { DeviceType = 2; } var pushNotificationsDetail = { DeviceId: registrationToken, DeviceType: DeviceType } this.httpProvider.addPushNotification(pushNotificationsDetail).subscribe(async data => { if (data != null && data.body != null && data.body.isSuccess == true) { localStorage.setItem("IsSuccessPushRegistration", "true"); this.notificationDetail.title = "Success"; this.notificationDetail.body = data.body.message; this.showPushNotificationAlert(this.notificationDetail); } },async error => {}); } }, ); PushNotifications.addListener('registrationError', (error: any) => { }); PushNotifications.addListener('pushNotificationReceived', (notification: PushNotification) => { this.showPushNotificationAlert(notification); }); PushNotifications.addListener('pushNotificationActionPerformed', (args: PushNotificationActionPerformed) => { }); } async showPushNotificationAlert(notificationDetail: any) { const alert = await this.alertCtrl.create({ header: notificationDetail.title, message: notificationDetail.body, buttons: ['OK'] }); await alert.present(); } }
When token registration of the app is completed, store the registration token in the database for future use.
When a push notification is received when the app is open, the notification will show in a pop-up message.
In this section, we will send a message through a push notification using the Web API server.
Add all the basic validations like Title and Body in the HTML file. Refer to the following code.
src/app/home.component.ts
import { Component, ViewChild } from '@angular/core'; import { NgForm } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { AlertController, Platform } from '@ionic/angular'; import { HttpProviderService } from '../Service/http-provider.service'; @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], }) export class HomePage { notificationList = { NotificationTitle: '', NotificationBody:'' }; notificationDetail = { title: '', body: '' }; @ViewChild('sendForm', { static: false }) sendForm: NgForm; constructor(private router: Router, private route: ActivatedRoute, public alertController: AlertController, private httpProvider: HttpProviderService, private platform : Platform) { this.route.queryParams.subscribe(params => { if (this.router.getCurrentNavigation() && this.router.getCurrentNavigation().extras && this.router.getCurrentNavigation().extras.state) { let data = this.router.getCurrentNavigation().extras.state; this.showPushNotificationAlert(data); } }); } async showPushNotificationAlert(notificationDetail: any) { const alert = await this.alertController.create({ header: notificationDetail.title, message: notificationDetail.body, buttons: ['OK'] }); await alert.present(); } sendMessage(form: NgForm) { if (form.valid) { this.httpProvider.sendPushNotification(this.notificationList).subscribe(async data => { if (data != null && data.body != null && data.body.isSuccess == true) { this.notificationDetail.title = "Success"; this.notificationDetail.body = data.body.message; this.showPushNotificationAlert(this.notificationDetail); } },async error => {}); } else { this.notificationDetail.title = "Warning"; this.notificationDetail.body = "Please fill the message"; this.showPushNotificationAlert(this.notificationDetail); } } }
src/app/home.component.html
<ion-content> <form #sendForm="ngForm" novalidate> <ion-row class="row-style"> <ion-col class="align-center p-30"> <div class="label-message"> Title </div> </ion-col> </ion-row> <ion-row class="row-style"> <ion-col class="align-center p-30"> <ion-input type="text" id="message" name="message" #message="ngModel" [(ngModel)]="notificationList.NotificationTitle" placeholder="Type your title" required></ion-input> </ion-col> </ion-row> <ion-row class="row-style"> <ion-col class="align-center p-30"> <div class="label-message"> Description </div> </ion-col> </ion-row> <ion-row class="row-style"> <ion-col class="align-center p-30"> <ion-textarea type="text" id="message" name="message" #message="ngModel" [(ngModel)]="notificationList.NotificationBody" placeholder="Type your description" maxlength="120" required></ion-textarea> </ion-col> </ion-row> <ion-row class="row-style"> <ion-col class="align-center submit-btn p-30"> <ion-button type="submit" (click)="sendMessage(sendForm)">Send Message</ion-button> </ion-col> </ion-row> </form> </ion-content>
The following are screenshots of the Send Notification page.
Now, run the following commands to update code changes in the Android and iOS app builds.
> ionic build > npx cap copy > npx cap sync
Go to the Firebase Console, sign in with your email ID, and click the Create a project button, as shown in the screenshot.
Select the default account for Firebase and click Create Project.
Your project is ready to use. Now, click Continue.
Go to the Project Overview page in the Firebase project and at the top, click the Android icon to add a new Android app.
Then, click Register app.
The next prompt will ask you to download a google-services.json file. This file contains the information your Capacitor app needs to connect to Firebase from Android.
Download the google-services.json file to your local machine. Then, move the file into your Capacitor Android project directory, under android/app/.
iOS push notifications are more complicated than Android. Prior to being able to test push notifications with your iOS app, you must have a paid Apple Developer account to take care of the following items:
Go to the Project Overview page for the Firebase project and at the top, click the iOS icon to add a new iOS app.
The next screen will ask you for some information about your app:
Then, click Register app.
Download the GoogleService-Info.plist provided to your local machine.
Next, open the project in Xcode and run the following command.
npx cap open ios
Enable push notifications in Xcode.
Check the listed items inside the App > Signing & Capabilities tab.
Under the Signing section, click + Capability. Then, search for push notifications in the current modal.
Add the GoogleService-Info.plist in Xcode.
Open Podfile in Xcode.
target 'App' do capacitor_pods # Add your Pods here pod 'FirebaseCore' # Add this line pod 'Firebase/Messaging' # Add this line end
Run npx cap update ios to update the Ionic project.
To connect to Firebase when your iOS app starts up, follow these steps:
import Firebase
FirebaseApp.configure()
Note: On iOS, you will see a pop-up asking you to allow notifications for your app—make sure you choose to allow notifications!
To achieve APNS, we are using the jose-jwt NuGet package for iOS devices from the server-side.
Jose JWT will work only for .NET Framework 4.6.1 and later versions.
Here, we are using the .p8 file to get a private key and send notifications.
To generate a .p8 key file, go to your Apple developer account page and select Certificates, IDs & Profiles.
You can now upload the .p8 file (APNS auth key) to your Firebase console.
To upload your auth key, go to the Project Overview page:
We can test the push notification configuration from the Firebase console. Go to the Cloud Messaging section under the Grow header in the project panel.
Next, click New Notification.
When creating the notification, you only need to specify the following information:
Now, you can see the push notification in the notification panel.
In this section, we will discuss how to create a Web API in ASP.NET MVC for push notifications.
The purpose of this project is to send push notifications through Web API using a registration token stored in the database using the Push Notification plugin.
The Web API is a framework that makes it easy to build HTTP services for browsers and mobile devices. Using ASP.NET, Web API can communicate among different devices from the same database.
Follow these steps to create an ASP.NET web app:
After installing Entity Framework and SQL Server in our app, it will auto-generate the following section of providers inside the entityFramework section in the web.config file.
<entityFramework> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework>
Create a model class with the details of push notifications in the app. Refer to the following code example.
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Net; using System.Web; namespace PushNotificationWebAPIApplication.Models { public class PushNotification { [Key] public int Id { get; set; } public string DeviceId { get; set; } public string DeviceType { get; set; } public DateTime CreatedDate { get; set; } public bool IsDeleted { get; set; } } public class PushNotificationAddResponse { public bool IsSuccess { get; set; } public string Message { get; set; } } public class ResponseData { public bool IsSuccess { get; set; } public string Message { get; set; } public HttpStatusCode StatusCode { get; set; } } public class PushNotificationData { public int Id { get; set; } public string DeviceId { get; set; } public string DeviceType { get; set; } } public class PushNotificationResponseList : ResponseData { public List<PushNotificationData> PushNotification { get; set; } } public class Notification { public string NotificationTitle { get; set; } public string NotificationBody { get; set; } } }
Create a DBContext file in the app with the following code. This code will point to the connection from the web.config file.
using PushNotificationWebAPIApplication.Models; using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Web; namespace PushNotificationWebAPIApplication.Context { public class PushNotificationDbContext : DbContext { public PushNotificationDbContext() : base("name=PushNotificationContext") { } public DbSet<PushNotification> PushNotifications { get; set; } } }
Then, create a DatabaseInitializer file with the following code.
using System.Data.Entity; namespace PushNotificationWebAPIApplication.Context { public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<PushNotificationDbContext> { protected override void Seed(PushNotificationDbContext context) { base.Seed(context); } } }
Add the following connection string detail to the web.config file. This contains the server details, user ID, password, and database name.
Make sure to use the same connection name added in the DBContext.
<connectionStrings> <add connectionString="data source=SYNCLAPN18812;initial catalog=PushNotificationDB;persist security info=True;user id=sa;password=sa@1234" name="PushNotificationDBConnection" providerName="System.Data.SqlClient" /> </connectionStrings>
Now, go to Controller and expand it. By default, there will be some controllers in the Controller directory. To create a new controller:
Replace the code inside the controller with the following code.
using System; using System.Net; using System.Net.Http; using System.Web.Http; using System.Web.Http.Cors; using PushNotificationWebAPIApplication.Context; using PushNotificationWebAPIApplication.Models; using System.Linq; using System.Collections.Generic; using Newtonsoft.Json.Linq; using PushSharp.Core; using PushSharp.Google; using System.Configuration; namespace PushNotificationWebAPIApplication.Controllers { [EnableCors(origins: "*", headers: "*", methods: "*")] [RoutePrefix("api/pushNotification")] public class PushNotificationController : ApiController { public string TokenRegisterMessage = "Token was registered successfully"; public string SendPushNotificationMessage = "Push notification was send successfully"; private string serverKeyForApp = ConfigurationManager.AppSettings["FCMServerKeyForApp"]; private string senderIdForApp = ConfigurationManager.AppSettings["FCMSenderIdForApp"]; private string fcmNotificationSendURL = ConfigurationManager.AppSettings["FCMNotificationSendURL"]; private string appleKeyId = ConfigurationManager.AppSettings["AppleKeyId"]; private string appleTeamId = ConfigurationManager.AppSettings["AppleTeamId"]; private string appId = ConfigurationManager.AppSettings["AppId"]; private string appleAuthKeyFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigurationManager.AppSettings["AppleAuthKeyFile"]); private PushNotificationDbContext dbContext = new PushNotificationDbContext(); public PushNotificationController() { } /// <summary> /// Add Push Notification /// </summary> /// <param name="pushNotification"></param> /// <returns></returns> [HttpPost] [Route("addPushNotification")] public HttpResponseMessage AddPushNotification(PushNotification pushNotification) { var pushNotificationAddResponse = new PushNotificationAddResponse(); try { var PushNotification = new PushNotification { DeviceId = pushNotification.DeviceId, DeviceType = pushNotification.DeviceType, CreatedDate = DateTime.Now, IsDeleted = false }; var pushnotification = (from push in dbContext.PushNotifications where push.DeviceId == pushNotification.DeviceId && push.IsDeleted == false select push).FirstOrDefault(); if (pushnotification != null) { pushnotification.IsDeleted = true; dbContext.SaveChanges(); } dbContext.PushNotifications.Add(PushNotification); dbContext.SaveChanges(); pushNotificationAddResponse.IsSuccess = true; pushNotificationAddResponse.Message = TokenRegisterMessage; return Request.CreateResponse(HttpStatusCode.OK, pushNotificationAddResponse); } catch (Exception ex) { return Request.CreateResponse(HttpStatusCode.Unauthorized, ex.Message); } } /// <summary> /// Send Push Notification /// </summary> /// <param name="pushMessage"></param> /// <returns></returns> [HttpPost] [Route("sendPushNotification")] public HttpResponseMessage SendPushNotification(Notification notificationList) { var pushNotificationAddResponse = new PushNotificationAddResponse(); try { var responseStatus = new ResponseData(); var androidDeviceIdList = new List<string>(); var iosDeviceIdList = new List<string>(); var pushNotificationList = GetPushNotification(); if (pushNotificationList.Count > 0) { foreach (var notification in pushNotificationList) { if (notification.DeviceType == "1") { androidDeviceIdList.Add(notification.DeviceId); } else if (notification.DeviceType == "2") { iosDeviceIdList.Add(notification.DeviceId); } } if (androidDeviceIdList.Count > 0) { SendToAndroid(androidDeviceIdList, notificationList.NotificationBody, notificationList.NotificationTitle, serverKeyForApp, senderIdForApp); } if (iosDeviceIdList.Count > 0) { var apns = new IOSPushNotificationHandler(appleKeyId, appleTeamId, appId, appleAuthKeyFile, true); foreach (var token in iosDeviceIdList) { apns.JwtAPNsPush(token, notificationList.NotificationTitle, notificationList.NotificationBody); } } } pushNotificationAddResponse.IsSuccess = true; pushNotificationAddResponse.Message = SendPushNotificationMessage; return Request.CreateResponse(HttpStatusCode.OK, pushNotificationAddResponse); } catch (Exception ex) { return Request.CreateResponse(HttpStatusCode.Unauthorized, ex.Message); } } private List<PushNotificationData> GetPushNotification() { var responseStatus = new PushNotificationResponseList(); var pushNotificationList = new List<PushNotificationData>(); var pushnotification = (from push in dbContext.PushNotifications where push.IsDeleted ==false select push).ToList(); foreach (var notify in pushnotification) { var pushNotificationData = new PushNotificationData(); pushNotificationData.Id = notify.Id; pushNotificationData.DeviceId = notify.DeviceId; pushNotificationData.DeviceType = notify.DeviceType; pushNotificationList.Add(pushNotificationData); } return pushNotificationList; } public void SendToAndroid(List<string> deviceIdList, string NotificationBody, string NotificationTitle, string ServerKeyForApp, string SenderIdForApp) { var config = new GcmConfiguration(SenderIdForApp, ServerKeyForApp, null); config.GcmUrl = fcmNotificationSendURL; var broker = new GcmServiceBroker(config); broker.OnNotificationFailed += (notification, aggregateEx) => GcmNotificationFailed(aggregateEx); broker.OnNotificationSucceeded += (notification) => GcmNotificationSucceeded(); broker.Start(); broker.QueueNotification(new GcmNotification { RegistrationIds = deviceIdList, Notification = JObject.FromObject(new { body = NotificationBody, title = NotificationTitle, badge = 1 }), Priority = GcmNotificationPriority.High, ContentAvailable = true }); broker.Stop(); } private void GcmNotificationSucceeded() { GetDevicePushStatus("Notification has been sent"); } private void GcmNotificationFailed(AggregateException aggregateEx) { string errorMessage = ""; aggregateEx.Handle(ex => { if (ex is GcmNotificationException) { var notificationException = (GcmNotificationException)ex; var gcmNotification = notificationException.Notification; var description = notificationException.Description; if (description != null) errorMessage = "Notification Failed: Desc={" + description + "}"; else errorMessage = "Notification Failed: Desc={" + notificationException.Message + "}"; } else if (ex is GcmMulticastResultException) { var multicastException = (GcmMulticastResultException)ex; foreach (var succeededNotification in multicastException.Succeeded) { } foreach (var failedKvp in multicastException.Failed) { var n = failedKvp.Key; var e = failedKvp.Value; errorMessage += "Notification Failed: Desc={" + e.Message + "}"; } } else if (ex is DeviceSubscriptionExpiredException) { var expiredException = (DeviceSubscriptionExpiredException)ex; var oldId = expiredException.OldSubscriptionId; var newId = expiredException.NewSubscriptionId; errorMessage = "Device RegistrationId Expired: {" + oldId + "}"; if (!string.IsNullOrWhiteSpace(newId)) { errorMessage = "Device RegistrationId Changed To: {" + newId + "}"; } } else if (ex is RetryAfterException) { var retryException = (RetryAfterException)ex; errorMessage = "FCM Rate Limited, don't send more until after {" + retryException.RetryAfterUtc + "}"; } else if (ex is UnauthorizedAccessException) { var unauthorizedexception = (UnauthorizedAccessException)ex; errorMessage = "FCM Authorization Failed."; } else { errorMessage = "Notification Failed for some unknown reason"; } return true; }); GetDevicePushStatus(errorMessage); } private string GetDevicePushStatus(string statusText) { return statusText; } } }
Create IOSPushNotificationHandler and Http2CustomHandler class files. Refer to the following code examples.
IOSPushNotificationHandler.cs
using Jose; using Jose.keys; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.OpenSsl; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Security.Cryptography; using System.Threading.Tasks; namespace PushNotificationWebAPIApplication.Models { public class IOSPushNotificationHandler { public string Algorithm { get; set; } public string HostServerUrl { get; set; } public int HostPort { get; set; } public string APNsKeyId { get; set; } public string TeamId { get; set; } public string BundleAppId { get; set; } public string AppleAuthKeyFile { get; set; } public CngKey PrivateKey { get; set; } public string AccessToken { get; set; } public IOSPushNotificationHandler(string appleKeyId, string appleTeamId, string appId, string appleAuthKeyFile, bool production) { Algorithm = "ES256"; if (production == false) HostServerUrl = "api.development.push.apple.com"; else HostServerUrl = "api.push.apple.com"; HostPort = 443; APNsKeyId = appleKeyId; TeamId = appleTeamId; BundleAppId = appId; AppleAuthKeyFile = appleAuthKeyFile; } private long ToUnixEpochDate(DateTime date) { return (long)Math.Round((date.ToUniversalTime() - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds); } private async Task JwtAPNsPush(Uri host_uri, string access_token, byte[] payload_bytes) { var result = new ResponseData(); try { using (var handler = new Http2CustomHandler()) { using (var http_client = new HttpClient(handler)) { var request_message = new HttpRequestMessage(); { request_message.RequestUri = host_uri; request_message.Headers.Add("authorization", String.Format("bearer {0}", access_token)); request_message.Headers.Add("apns-id", Guid.NewGuid().ToString()); request_message.Headers.Add("apns-expiration", "0"); request_message.Headers.Add("apns-priority", "10"); request_message.Headers.Add("apns-topic", BundleAppId); request_message.Method = HttpMethod.Post; request_message.Content = new ByteArrayContent(payload_bytes); } var response_message = await http_client.SendAsync(request_message); if (response_message.StatusCode == System.Net.HttpStatusCode.OK) { var response_uuid = ""; IEnumerable<string> values; if (response_message.Headers.TryGetValues("apns-id", out values)) { response_uuid = values.First(); result.Message = $"success: '{response_uuid}'"; result.IsSuccess = true; } else { result.Message = "failure"; } } else { var response_body = await response_message.Content.ReadAsStringAsync(); var response_json = JObject.Parse(response_body); var reason_str = response_json.Value<string>("reason"); result.Message = $"failure: '{reason_str}'"; } } } } catch (Exception ex) { result.Message = $"exception: '{ex.Message}'"; } } private CngKey GetPrivateKey() { using (var reader = File.OpenText(AppleAuthKeyFile)) { var ecPrivateKeyParameters = (ECPrivateKeyParameters)new PemReader(reader).ReadObject(); var x = ecPrivateKeyParameters.Parameters.G.AffineXCoord.GetEncoded(); var y = ecPrivateKeyParameters.Parameters.G.AffineYCoord.GetEncoded(); var d = ecPrivateKeyParameters.D.ToByteArrayUnsigned(); return EccKey.New(x, y, d); } } private void JwtAPNsPushExtend(string device_token, string title, string body) { var host_uri = new Uri($"https://{HostServerUrl}:{HostPort}/3/device/{device_token}"); var _payload = new Dictionary<string, object>() { { "iss", TeamId }, { "iat", ToUnixEpochDate(DateTime.Now) } }; var header = new Dictionary<string, object>() { { "alg", Algorithm }, { "kid", APNsKeyId } }; var privateKey = GetPrivateKey(); AccessToken = JWT.Encode(_payload, privateKey, JwsAlgorithm.ES256, header); var payload = new byte[0]; { var data = JObject.FromObject(new { aps = new { alert = new { title = title, body = body }, badge = 1 } }); payload = System.Text.Encoding.UTF8.GetBytes(data.ToString()); } Task.Run(async () => await JwtAPNsPush(host_uri, AccessToken, payload)); } public void JwtAPNsPush(string device_token, string title, string body) { JwtAPNsPushExtend(device_token, title, body); } } }
Http2CustomHandler.cs
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace PushNotificationWebAPIApplication.Models { public class Http2CustomHandler : WinHttpHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { request.Version = new Version("2.0"); return base.SendAsync(request, cancellationToken); } } }
Maintain the following app ID, FCM server key and sender ID, Apple key ID, team ID, and auth key file details in the web.config file.
<add key="AppId" value="com.pushnotification.app" /> <!-- Android Config Push Notification - FCM --> <add key="FCMServerKeyForApp" value="*************************" /> <add key="FCMSenderIdForApp" value="***************" /> <add key="FCMNotificationSendURL" value="https://fcm.googleapis.com/fcm/send" /> <!-- IOS Config Push Notification --> <add key="AppleKeyId" value="ABC1DEF11G" /> <add key="AppleTeamId" value="ER342D23FD9" /> <add key="AppleAuthKeyFile" value="AuthKey_ABC1DEF11G.p8" />
Click the gear icon at the top left and select the Project settings of the Firebase Console. Select the Cloud Messaging tab.
Under Cloud Messaging API (Legacy), click the options (three dots on the right) and then click Manage API in Google Cloud Console. This will open a new page. Under Cloud Messaging, press Enable.
Refresh the page on your Firebase Console and copy your Server key and Sender ID.
Include the AuthKey_ ABC1DEF11G.p8 file in the app we created in the previous section.
The Apple key ID can also be derived from the name of the file for the key. Your file with the key will probably be named something like AuthKey_ABC1DEF11G.p8, so ABC1DEF11G is the key ID.
The team ID can be found in the upper-right corner of the Apple account webpage.
For more details, refer to the complete project in the Firebase Push Notification for Android and IOS repository.
I hope this blog provided a clear idea about how to build Ionic with Angular apps for implementing Firebase push notifications for both Android and iOS and creating ASP.NET projects with SQL to send Firebase push notifications.