Integration

Kumulos provides an SDK in the form of a NuGet package for your Xamarin applications.

Integrate SDK components and dependencies

The Kumulos SDK is an open source project hosted on Github. You can find a link to the project in your agency console and here: https://github.com/Kumulos/KumulosSdkXamarin. It is distributed via a NuGet package for referencing in your apps.

Add the SDK package to your project via the package manager console by entering Install-Package KumulosXamariniOS or Install-Package KumulosXamarinDroid depending on which platform your project targets.

The Kumulos SDK is also dependent on the Settings Plugin (Xam.Plugins.Settings) in order to persist the Installation ID. This is also distributed as a NuGet package.

Initialization

To configure the SDK for use you need to initialize it with your app's API credentials. This should be done early in your application startup so that you can start calling API methods and using features.

var config = new Dictionary<string, string>
 {
    { "apiKey", "YOUR_API_KEY" },
    { "secretKey", "YOUR_SECRET_KEY" }
 };

KumulosSDK.Initialize(new Kumulos.iOS.DeviceInfo(), CrossSettings.Current, config);

Your API Key and Secret Key can be obtained from the App Dashboard in your agency console.

The DeviceInfo implementation is platform specific and should be one of Kumulos.iOS.DeviceInfo or Kumulos.Droid.DeviceInfo depending on your target.

You don't need to initialize the Kumulos SDK every time you wish to make an API call. It only needs to be initialized once, after which it will remember the API key and secret key you've given it the first time.

Analytics

So long as you initialize the SDK at some point in your app's lifecycle, Kumulos will automatically record analytics data such as the device model, operating system version and more, available in Analytics & Reporting for your app.

Installation ID

When initialized for the first time, the Kumulos SDK will create a unique identifier for the current installation. This identifier can be used to target push notifications to a specific device via KScript or the Push Notifications API.

In order to retrieve this identifier, simply access the class variable:

string id = KumulosSDK.InstallId

Once you have the installation ID, you can send it to your app's backend to be used later for push targeting. For more information about push targeting, please see the KScript Documentation or push notification documentation as appropriate.

Location Tracking

You can send Kumulos location updates and use this to trigger events such as push notifications when an install enters a GeoFence.

Once you have configured location updates on the platform of choice you can send the updates to Kumulos via the helper method in the stats namespace.

Helper implementation classes of the interface are provided in the Droid / iOS Xamarin packages.

KumulosSDK.Stats.SendLocationUpdate(ISendLocationInformation request);

Push

The Kumulos SDK provides push notifications via APNS and GCM. To integrate Kumulos Push into your app you have to complete the following steps:

Configuring APNS

Configuring APNS for iOS with Kumulos

Configuring GCM

Configuring GCM for Android with Kumulos

Next you need to enable and configure the Kumulos push service with the certificates you have created.

Registering on iOS

The KumulosSDK provides a helper method to configure notification permissions for alert, badge and sound permissions then trigger a user prompt with one line of code.

Kumulos.iOS.Push.RegisterForRemoteNotifications();

To send the returned device token to the Kumulos Push service, the OS will trigger a callback with the device token. Depending on the OS version, the definition will change slightly. From either, you can forward the token to the Kumulos SDK.

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    Kumulos.iOS.Push.RegisterDeviceToken(deviceToken);
}

Registering on Android

The KumulosSDK provides a helper intent service for registering with GCM along with a helper method to check for availability of the play service.

if (Kumulos.Droid.Push.IsPlayServicesAvailable(this)) {
    var intent = new Intent(this, typeof(Kumulos.Droid.GcmRegistrationIntentService));
    StartService(intent);
}

You will need to ensure your app has the INTERNET permission and provide your GCM sender id in the AndroidManifest.xml inside the application block.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example">

    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Optionally add the wake lock permission to stop the CPU from sleeping when a message is received -->
    <!-- <uses-permission android:name="android.permission.WAKE_LOCK" /> -->

    <application
        android:name=".ExampleApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data android:name="kumulos_gcm_sender_id" android:value="[YOUR_SENDER_ID]\0" />

        <!-- Kumulos Push receiver -->
        <receiver android:name="com.kumulos.android.PushBroadcastReceiver" android:exported="false">
            <intent-filter>
                <action android:name="com.kumulos.push.RECEIVED" />
                <action android:name="com.kumulos.push.OPENED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

Receiving on Android

To provide a service which will receive notifications and raise a local notification to the user and tray you must add a GcmListenerService, which is provided as part of the SDK. To enable it simply register the app for receiving notification intents, again inside the application block.

<receiver android:name="com.google.android.gms.gcm.GcmReceiver"
      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="[YOUR_PACKAGE_NAME]" />
    </intent-filter>
</receiver>

You're done! The app can now receive push notifications from the Kumulos Push service.

Default Push Behavior

By default, the Kumulos PushBroadcastReceiver will show a notification on the notification area of the device when a content push is received.

Tapping this notification will open the main launcher activity of your application and track the push open conversion for you.

Your main activity will receive the push contents in its options bundle under the PushMessage.EXTRAS_KEY.

No action is taken for data pushes by default.

Customizing Push Behavior

To customize the behavior of the SDK when a push is received or its notification is tapped, we suggest subclassing the PushBroadcastReceiver and overriding its base methods depending on what you want to customize.

Example extension class:

using Kumulos.Droid;

namespace MyApp
{
    [BroadcastReceiver(Enabled = true, Exported = false)]
    [IntentFilter(new[] { ACTION_PUSH_RECEIVED, ACTION_PUSH_OPENED })]
    public class MyPushReceiver : PushBroadcastReceiver
    {

    }
}

Changing the Launched Activity

To change which activity will be launched when the user taps a notification, you can override the PushBroadcastReceiver.GetPushOpenActivityIntent(Context, PushMessage).

using Kumulos.Droid;
using Android.Content;

namespace MyApp
{
    [BroadcastReceiver(Enabled = true, Exported = false)]
    [IntentFilter(new[] { ACTION_PUSH_RECEIVED, ACTION_PUSH_OPENED })]
    public class MyPushReceiver : PushBroadcastReceiver
    {
        protected override Intent GetPushOpenActivityIntent(Context context, PushMessage pushMessage)
        {
            // TODO implement your own logic here
            return base.GetPushOpenActivityIntent(context, pushMessage);
        }
    }
}

The PushMessage model will not be added to the Intent by default, it is up to you to add it as an extra if desired:

Intent launchIntent = new Intent(context, MyActivity.class);
launchIntent.putExtra(PushMessage.EXTRAS_KEY, pushMessage);

You can return null to track the push conversion and do nothing when the notification is tapped.

If the Intent returned does not describe an Activity, it will be ignored

Customizing the Notification

To customize the notification shown to the user for content pushes, you can override PushBroadcastReceiver.BuildNotification(Context, PushMessage).

using Kumulos.Droid;
using Android.Content;

namespace MyApp
{
    [BroadcastReceiver(Enabled = true, Exported = false)]
    [IntentFilter(new[] { ACTION_PUSH_RECEIVED, ACTION_PUSH_OPENED })]
    public class MyPushReceiver : PushBroadcastReceiver
    {
        protected override Android.App.Notification BuildNotification(Context context, PushMessage pushMessage)
        {
            // TODO customize the notification
            return base.BuildNotification(context, pushMessage);
        }
    }
}

If you want to handle the open with the broadcast receiver, be sure to set up the content intent of the notification as follows:

Intent openIntent = new Intent(ACTION_PUSH_OPENED);
            openIntent.PutExtra(PushMessage.EXTRAS_KEY, JsonConvert.SerializeObject(pushMessage));
            openIntent.SetPackage(context.PackageName);

PendingIntent pendingOpenIntent = PendingIntent.GetBroadcast(
        context,
        (int)pushMessage.TimeSent,
        openIntent,
        PendingIntentFlags.UpdateCurrent | PendingIntentFlags.OneShot);

...

notificationBuilder.setContentIntent(pendingOpenIntent);

This will ensure that the notification conversion is tracked in Kumulos.

If you want to do something else, you can manually track push open conversion.

KumulosSDK.Push.TrackPushOpen(pushMessage.Id);

Launching a Service for Background Data Pushes

To launch a service when a background data push is received, you can override PushBroadcastReceiver#getBackgroundPushServiceIntent.

using Kumulos.Droid;
using Android.Content;

namespace MyApp
{
    [BroadcastReceiver(Enabled = true, Exported = false)]
    [IntentFilter(new[] { ACTION_PUSH_RECEIVED, ACTION_PUSH_OPENED })]
    public class MyPushReceiver : PushBroadcastReceiver
    {
        protected override Intent GetBackgroundPushServiceIntent(Context context, PushMessage pushMessage)
        {
            //- TODO implement your own logic here
            return base.GetBackgroundPushServiceIntent(context, pushMessage);
        }
    }
}

This would easily allow you to handle data processing in the background by launching an IntentService for example.

The PushMessage model will not be added to the Intent by default, it is up to you to add it as an extra if desired:

Intent serviceIntent = new Intent(context, MyIntentService.class);
serviceIntent.putExtra(PushMessage.EXTRAS_KEY, pushMessage);

Return null if you want to do nothing with the data push.

If the Intent returned does not describe a Service, it will be ignored

URL Pushes

Push notifications sent to open a URL will, by default, track the push open if the user taps the notification, and then open the default web browser.

Overriding All Behaviors

If you want to completely replace the logic for handling pushes, you can override PushBroadcastReceiver.OnPushReceived(Context, PushMessage).

Bear in mind you will be responsible for all aspects of the push process such as showing a notification to the user, tracking an open conversion using KumulosSDK.Push.TrackPushOpen(string), or launching any activities or services.

Tracking open rates in iOS

When your app receives a push notification, or is launched by tapping on a push notification, your app's delegate will be called back by the OS.

To correctly report on push open rates & conversions, you need to tell Kumulos that the app was launched by the remote notification. A sample UNUserNotificationCenterDelegate is provided in the SDK, which will read the Notification ID and track its receipt with Kumulos.

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
   // Override point for customization after application launch.
   // If not required for your application you can safely delete this method

   // Watch for notifications while the app is active
   UNUserNotificationCenter.Current.Delegate = new Kumulos.iOS.UserNotificationCenterDelegate();

   return true;
}

The provided delegate tracks push open conversions when a user has tapped on a notification and launched the app. However, you may wish to customize when you want to track a push open. In those cases, you can simply call the SDK TrackPushOpen method as desired and pass in the id for the notification.

URL Pushes in iOS

When you send a URL push from Kumulos, you need to override the WillPresentNotification method in the NotificationCenter. Again, an implementation for this is provided within the delegate as part of the SDK.

NSDictionary custom = (NSDictionary)notification.Request.Content.UserInfo["custom"];
NSString key = new NSString("u");
if (custom.ContainsKey(key))
{
   string url = custom["u"].ToString();
   UIApplication.SharedApplication.OpenUrl(NSUrl.FromString(url));
}

Background Data

When you send a background data push with Kumulos, the content-available flag will be set on the notification. This will allow your app to be woken up to process the push notification in the background.

Make sure you have enabled the "Remote notifications" background mode in your project's "Capabilities" settings

The background push notification will trigger the DidReceiveRemoteNotification override defined in your AppDelegate.cs

public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
    NSDictionary aps = (NSDictionary)userInfo["aps"];
    NSDictionary custom = (NSDictionary)userInfo["custom"];

   if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Active) {
       Kumulos.KumulosSDK.Push.TrackPushOpen(custom["i"].ToString());   
   }

    NSDictionary custom = (NSDictionary)userInfo["custom"];
    NSString key = new NSString("a");
    if (custom.ContainsKey(key)) {
        string dataPayload = custom["a"].ToString();
        //- Do work.
    }
}

Note if you set a title & message then a notification will be shown to the user. If you want the push to be silent, don't set a title or message when sending.

Channels

You can create and manage subscriptions to push notification Channels via the SDK. Channels allow your users to define preferences for the type of content they would like to receive via notifications.

You can manage all channel interactions via the KumulosSDK.Push.Channels namespace in the SDK.

KumulosSDK.Push.Channels.ListChannels().ContinueWith(r =>
{
    Console.WriteLine(r.Result);
});

Helper methods are then available for creating, listing and managing subscriptions to channels. Each helper is async and can be awaited or given a continue block.

public Task<object> ClearSubscriptions ();
public Task<object> CreateChannel (string uuid, bool subscribe, string name, bool showInPortal, Dictionary<string, object> meta);
public Task<object> ListChannels ();
public Task<object> SetSubscriptions (string[] uuids);
public Task<object> Subscribe (string[] uuids);
public Task<object> Unsubscribe (string[] uuids);

Channel visibility and meta data can be controlled when they are created.

Build

You can interact with API methods defined in the Kumulos Build service using the KumulosSDK.Build.CallAPI method in the Build namespace of the SDK.

Parameters are provided as a list of key value pairs. Simply add a pair for each parameter that your API method expects and provide it as the second parameter to the CallAPI method.

var parameters = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("param1", "foo"),
    new KeyValuePair<string, string>("param2", "bar")
};

KumulosSDK.Build.CallAPI("myAPIMethod", parameters).ContinueWith(t =>
{
    ApiResponse response = t.Result;
});

A threading task will be returned, which your code can continue with once the network operation has completed. The Result of the task will be an ApiResponse object. This object can then be inspected for the payload of the API method, its response code and message.

Kumulos stores data fields as base64 encoded data, so if you receive data from Kumulos, you will have to base64 decode it to access the original data. Similarly, when you send data to Kumulos, you should base64 encode it before transport.

Changelog

1.1.0

  • Add geolocation update helper method

1.0.0

  • Initial release with Build, Push and Analytics support.