CrossShovePlugin 9.0.0-alpha1

This is a prerelease version of CrossShovePlugin.
dotnet add package CrossShovePlugin --version 9.0.0-alpha1                
NuGet\Install-Package CrossShovePlugin -Version 9.0.0-alpha1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CrossShovePlugin" Version="9.0.0-alpha1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add CrossShovePlugin --version 9.0.0-alpha1                
#r "nuget: CrossShovePlugin, 9.0.0-alpha1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install CrossShovePlugin as a Cake Addin
#addin nuget:?package=CrossShovePlugin&version=9.0.0-alpha1&prerelease

// Install CrossShovePlugin as a Cake Tool
#tool nuget:?package=CrossShovePlugin&version=9.0.0-alpha1&prerelease                

CrossShovePlugin

Introduction

Welcome to the CrossShovePlugin - a C# Push Notification library currently for iOS (APNS) and Android (FCM).

Why is it called Cross Shove Plugin?

  • Cross = Cross Platform
  • Shove = Push
  • Plugin = It's a MAUI Plugin

The plugin is responsible for

  • Checking whether you have push permission
  • Registering for push notifications
  • handling the receipt of a push notification
    • Basic - title and message
    • Data - key value pairs
    • Background (coming soon)

The plugin needs to communicate with our shove server (api.shoveserver.com). The server is responsible for

  • Authorisation checks
  • Registering devices
    • Each device is given a unique ID so it doesn't matter whether Apple, Google or Microsoft suddenly provision a new push token for your customers device, the push server will ensure the details are updated.
  • Sending push messages
    • iOS - using the native Apple Push Notification Service (APNS)
    • Android - using the Firebase TBD (FCM)
    • WNS - Windows TBD
  • Automatic de-registering - if a push token is deemed invalid (e.g. the user has uninstalled your app) then the push token is removed.

Important Notes

It is recommended to keep your iOS, Android and Windows application identifiers the same, otherwise you will need to create separate 'applications' in the Shove server portal and this will add complexity in your server app when sending push notifications to devices on different platforms, for example when sending a push notification you need to specify your application ID, so instead of using the following

com.mycompany.myappname.ios
com.mycompany.myappname.droid
com.mycompany.myappname.win

Try to consistently use

com.mycompany.myappname

History

We were using Microsoft AppCenter to send basic push notifications and we were very happy with this. Microsoft unfortunately planned to shut it down on December 31st, they extended that deadline to the middle of February.

The official replacement is Azure Notification Hubs. For one of our projects we have a lot of devices registered and that would cost us a minimum of £100 a month. The cost along with the fear they could drop notification hubs or change it in the future made us decide to write our own implementation.

This plugin enables independent software developers to get up and running with the least amount of cost and the simplest set up.

Our immediate goal was to reach feature-parity with our current use of AppCenter

  • Request Push permission
  • Register a device
  • Send push to a device

Setup

A) Install the CrossShovePlugin NuGet

  • Add the CrossShovePlugin NuGet to
    • The shared / common project
    • iOS
    • Android
    • UWP
  • Don't forget to rebuid before you try to resolve your C# imports

B) Configure your mobile apps

For any project that you setup push notifications for there's a whole set of steps that's required and it's different per platform, please read these guides for each platform.

C) Initialise the CrossShovePlugin

For MAUI, you can put the following code snippet in your App.xaml.cs OnStart() method.

protected override void OnStart()
{

    CrossShovePlugin.Current.Init(

        publicAppKey: "my-PUBLIC-shove-key", // <-- Replace with your PUBLIC key

        pushMessageEventHandler: (object sender, PushMessageEventArgs e) =>
        {
            MainPage.DisplayAlert(e.Title, e.Message, "Ok"); // <-- Basic push
        }

    );
}

D) Permission hooks for Android

In your MainActivity you need to override the OnRequestPermissionsResult method so that the Shove library can be notified when the Notification permission has been enabled by the user (only actually invoked on Android 13+).

    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
    {
        Logger.Log(this, "OnRequestPermissionsResult invoked");

        Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

        // To inform Shove that Android has been granted permission for notifications
        // on Android 13+
        if (requestCode == ShovePlugin.PostNotificationsRequestCode)
        {
            ShovePlugin.Android13NotificationPermissionTaskCompletion?.SetResult(grantResults);
        }

        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

        Logger.Log(this, "OnRequestPermissionsResult done");
    }

Whenever a push notification is received a popup will be displayed to the user.

E) Listen to events

There are other initialisation delegates that you can optionally add during the intiialisation of the plugin:

  • shoveDeviceRegistered - The simplest title and message (as shown in the code above)
  • shovePushDataReceived - For when a data payload is also received
  • shoveTokenRefreshed - To notify your app that a native push token has been collected
  • shovePermissionChanged -
  • shoveDeviceRegistered -

In addition you can register as a event subscriber from anywhere in your code via the CrossShovePlugin class, for example

public MyCarouselPage() {

	CrossShovePlugin.ShoveTokenRefreshed += ( (object sender, string e) => { 
		// Do something to show this to the user
	});

}

Each of those handlers are described in more detail below

Event - shoveDeviceRegistered

When a push notification is received you will get the notification payload data in this event.

On iOS by default you need to tap the notification to receive the data (TBD true?)

Event - shovePushDataReceived

When a push notification is opened you will receive the payload data in this event. This is ideal to navigate to other place in your app.

shovePushDataReceived: (object sender, PushDataEventArgs e) =>
{
    MainPage.DisplayAlert(e.Title, e.Message + "Received Data!", "Ok");
}
Event - shoveTokenRefreshed

Please note that the token returned here is the native push token, it's for debugging purposes but you should not persist this on your server, instead if you require the unique Shove device ID then you can request it from the Plugin at any time (it doesn't change unless the app is re-installed, whereas the native push token can change multiple times).

pushTokenRefreshedHandler: (object sender, String e) =>
{
    MainPage.DisplayAlert("Shove Demo", $"New native push token created:{e} The Shove unique device ID is '{CrossShovePlugin.GetDeviceId()}'", "Ok");
}
Event - shovePermissionChanged

Perhaps you have a user-interface that needs to render something different depending on whether the user has provided push notification permission, or not.

For example, in an on-boarding carousel you might want to hide the 'Next' button until the user has requested the appropriate permission. Alternatively you might want to hide a panel if the permission has already been granted.

By listening to the ShovePermissionChanged event you can update your own properties to reflect the latest permissions.

CrossShovePlugin.ShovePermissionChanged += CrossShovePlugin_ShovePermissionChanged;

...

        private void CrossShovePlugin_ShovePermissionChanged(object sender, NotificationPermissionEnum e)
        {
            NextButtonEnabled = e.Equals(NotificationPermissionEnum.AUTHORIZED);

            ShoveRequestPushPanel = !e.Equals(NotificationPermissionEnum.AUTHORIZED);
            
        }
        
Event - shoveDeviceRegistered

Typically you can simply get the Shove Device ID from the plugin like this.

var ShoveDeviceToken = CrossShovePlugin.GetDeviceId();

Alternatively you can listen to registerDeviceReponseHandler to be notified when the Shove device ID is first assigned by the Shove Server.

Sending a push notification

The Shove server sends the push notifications using the APNS, FCM or WNS protocols, but your server is responsible for initiating the push.

Security / Public App Key / Private Server Key

Please note that the public app key is different to the private server key.

Public App Key - Must only be used in your mobile apps

Private Server Key - Must only be used when calling the shove server from your server over SSL

The Shove server will never let you send a push token without you providing your private key.

It's critical that you keep the private key secret by only passing it between your server and the shove server using a secure connection (SSL).

If you did use the private server key in your app then hackers could discover your private key and attempt to initiate push notification messages to your users without your permission.

One last time, NEVER use the private key from anywhere other than on your secure server using a secure connection over HTTPS.

Example server code

Here's an example server snippet that sends a push notification to a specific device.

Java
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"DeviceId\":\"device-com.devology.dummy.app-2d2c6a30-5d41-45a9-9a4b-0d01af91357c\",\n    \"Title\": \"MY TITLE\",\n    \"SubTitle\": \"MY SUBTITLE\",\n    \"Message\": \"MESSAGE BODY GOES HERE\",    \n  \"Data\": {\n    \"id\": \"5ffb379d06f90e614690153d\"}");
Request request = new Request.Builder()
  .url("https://api.shoveserver.com/api/SendPushNotification")
  .method("POST", body)
  .addHeader("PrivateServerKey", "your-private-server-key-goes-here")
  .addHeader("Content-Type", "application/json")
  .addHeader("Accept", "application/json")
  .build();
Response response = client.newCall(request).execute();
C# TBD
*TBD*

FAQs

  • Can the server send to more than one device at a time - No, not yet.

The future

In the future we will look at adding

  • Background events
  • Analytics
  • Tagging (e.g. adding tags to users then target them by those tags - for example based on their geographic location, interests, etc)
  • More depending on feedback and availability
  • Huawei HCM (Android FCM doesn't work on Huawei devices)

Licence

GPL 3 - https://www.gnu.org/licenses/gpl-3.0.html

Product Compatible and additional computed target framework versions.
.NET net9.0-android35.0 is compatible.  net9.0-ios18.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
9.0.0-alpha1 41 11/6/2024

(Not built for Win UI in this version)