Push Notification is the standard mechanism for a server app to send a message to a mobile app installation. Such messages are sent indirectly, through a PNS (Push Notification Service) such as
- Apple: APNs (Apple Push Notification Service)
- Google: FCM (Firebase Cloud Messaging)
- Windows: WNS (Windows Notification Service)
This is a Zebble plugin that allow you to use push notification services.
It is available on NuGet: https://www.nuget.org/packages/Zebble.PushNotification/
The user should be prompted to allow notifications. Usually the app will show a message to explain the reason and get the user's permission. Once the user has accepted this, the registration process takes place.
- The Zebble mobile app registers for push notifications with the PN Service.
- PNS sends a unique
token
back to the app, which is the unique id of that installation. - The app will then register the
token
with the server app (via its API). - The server app will store this token as an
App Installation Record
in the database, with that user's ID.
At this stage, the server side app will be able to send messages to the installation token by calling the appropriate API on the PNS. To the server app, that token, is effectively an address to reach the user on a specific device.
Each message/payload (including json data) should not be more than 2KB.
- If you don't already have one, create your app account in the
Firebase Console
. - A Server API key and a Client ID are automatically generated for the app. This information is packaged in a
google-services.json
file that is automatically downloaded when you click ADD APP. Save this file in a safe place.
- Next to the
Project overview
click on the Cog icon. - Select
Cloud Messaging
- Under
Web Configuration
generate a key pair. You will need it for your appSettings.json
For using apple services you need to register your application in Apple developer portal to have a Bundle ID
. Follow the instructions in the following link:
https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html
An App ID
is a two-part string used to identify one or more apps from a single development team:
- The string consists of a
Team ID
and abundle ID Search string
joined together with a "." character. Team ID
is supplied by Apple and is unique to a specific development team.Bundle ID search string
is supplied by you to match either the bundle ID of a single app or a set of bundle IDs for a group of your apps.
- Activate push certificates on the Apple Developer Portal.
- The iOS Application Bundle identifier must be the same corresponding to the profile used for code signing the app.
- Right click on your Zebble iOS project in Visual Studio
- Go to
iOS Application
tab - Set
Identifier
field to the Bundle ID you set in the previous step - Now you should have a
.p12
file which can be used in your server side application to send push notifications.
The project template contains this file. Fill in the blanks. It's fairly self explanatory.
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
Add the following as the content of dict tag:
<key>aps-environment</key>
<string>development</string>
Set the correct CodesignProvision
in the iOS project properties.
- Go to the
Properties
section of your iOS project in Visual Studio. - Under iOS Application tab, scroll down to the "Background Modes" section. Enable
Remote notifications options
andRemoteNotifications
.
If you face any problems, check out the helper class on content folder, and
PushNotificationApplicationDelegate.txt
.
Add google-services.json
to the Android project folder with Build Action
set to GoogleServicesJson
(if the GoogleServicesJson build action is not shown, save and close the Solution, then reopen it).
<application android:label="Project Title">
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
</application>
Note: ${applicationId}
will be replaced with your app's package name automatically during build process.
First, you need to add the Olive.PushNotification NuGet package : Install-Package Olive.PushNotification
.
Now you should add this section to appsettings.json
file:
"PushNotification": {
"Apple": {
"CertificateFile": "...",
"Environment": "Sandbox",
"CertificatePassword": "..."
},
"Google": {
"SenderId": "...",
"AuthToken": "..."
},
"Windows": {
"PackageName": "...",
"PackageSID": "...",
"ClientSecret": "..."
}
}
Note: Please notice that depending on your development environment you may use SandBox or Production
Open Startup.cs
file and in the ConfigureServices(...)
method add services.AddPushNotification();
. it should be something like this:
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
services.AddPushNotification();
}
Olive exposes IPushNotificationService
interface under Olive.PushNotification
namespace, which enables you to implement push notification sending functionality. In order to send a push notification from your project using Olive, you must have an class which implements IUserDevice
interface as shown below:
public class iOSUserDevice : IUserDevice
{
public string DeviceType => "iOS";
public string PushNotificationToken => "Token";
}
AddPushNotification
method has another overload accepting an implementation of ISubscriptionIdResolver
, which will notify you if you used an expired token to send push notifications. Below you'll find a sample implementation:
public class SubscriptionIdResolver : ISubscriptionIdResolver
{
public async Task ResolveExpiredSubscription(string oldSubscriptionId, string newSubscriptionId)
{
// Find all devices matching old expired id
var devices = (await Database.Of<Device>()
.Where(d => d.PushNotificationToken == oldSubscriptionId)
.GetList()).ToArray();
if (devices.None()) return;
newSubscriptionId = newSubscriptionId.OrNullIfEmpty();
// Replace push notification token in your records, with the updated one or null (if nothing provided
await Database.Update(devices, x => x.PushNotificationToken = newSubscriptionId);
}
}
It's better you add your class in Domain project under Logic folder.
To send a push notification you should simply inject IPushNotificationService
in your class constructor or use Context.Current.GetService<Olive.PushNotification.IPushNotificationService>();
if you want to have property injection and call .Send(...)
.
Here we have used class constructor injection as shown below:
using Olive.PushNotification;
namespace Domain
{
public partial class ActionRequest
{
readonly IPushNotificationService PushNotificationService;
public ActionRequest(IPushNotificationService pushNotificationService)
{
this.PushNotificationService = pushNotificationService;
}
[...]
}
}
async void SendPushNotificationService()
{
var items = new List<iOSUserDevice>
{
new iOSUserDevice()
};
PushNotificationService.Send("Title", "Geeks push notification", items);
}
We will update this list with common issues you might face when testing your app.
Start the investigation by checking your server-side logs and look for ConnectionError
occurrences. If you found anything, a possible cause can be related to your production certificate. Try to reissue your production certificate again and don't forget to upload the corresponding .p12
again to the server.