Xamarin SDK (Beta)

This page gives you all of the documentation needed to integrate the 2mee Xamarin SDK. This page will be updated with any changes or new features added to the SDK.

Introduction

This document will guide you through the creation of both Android and iOS apps using Appear2mee provided in the Xamarin giving you guidance on how to display Instant Human Messages on Android and iPhone devices.

This document will refer to the sample App supplied within the Appear2mee React SDK.

If you need to download the Appear2mee Xamarin apps before starting this guide, you can do so here at https://www.2mee.com/SDK/Appear2meeXamarinSDK.zip.

iOS

This document will guide you through the example iOS Xamarin2mee app SDK showing how to integrate the Appear2mee SDK into a Xamarin iOS app. If you need to download the Appear2mee Xamarin apps before starting this guide, you can do so here at http://www.2meefiles.com/Appear2meeXamarinSDK.zip (open in a new window).

Introduction

Messages are sent from the 2mee Platform using push notifications. The notification includes the url's of files that are required to display the notification. These files must be downloaded by the device in order to present the notification. If the push is scheduled, rather than send “now”, a content-available (silent) notification is sent first with the urls required, to give two opportunities of downloading the files. The main alert push notification will also attempt to download any files that are not already available. If the message file is not available in the time allotted by iOS a fallback text is “posted” as the notification. This fallback text is included in the notification. This fallback text is included in the notification and is set by your platform user.

3D and Haptic Touch on Notifications

3D Touch is a pressure-sensitive feature that uses capacitive sensors integrated into the smartphone's display to sense the pressure of a touch. A 3D Touch on a notification will bring up an extended view of the notification. Appear2mee messages use a Content Extension to display this extended view. Since iOS 12.1.1 haptic touch does the same thing. Haptic touch measures the spreading touch of your finger pad as you press harder on the screen and gives a feedback vibration.

If the user does a 3D Touch on a notifications, the Appear2mee SDK will display the full message in an extended view (Content Extension). The in app view will only be shown, if the user does a light (normal) touch on the notification.

Getting Started

An iOS 2mee enabled message app uses a number of components. The app itself, a service extension, and a content extension. These components are linked together using an App Group, that allows files downloaded by the service extension, or the main app, to be shared with each of the components. This sharing allows files that have been downloaded in the main app or the service extension, to be use in the content extension to display the notification, and in the main app to display the message if it was not displayed in the content extension.

The first step in Visual studio is to create or open an existing iOS app.

NuGet Package

The App, Service and Content Extension all use the NuGet Appear2meeiOS package. Install the package in your app.

Required Capabilities

Note: You may find it easier to create a shadow app in Xcode, an app with same bundle id and entitlements. Xcode will generate the correct settings and the correct certificates automatically. You will still have to enter these into your Xamarin app, but you will not need to use the Certificates, Identifiers & Profiles section on Apple Developer Center.

If you do not use a shadow app on Xcode to generate your entitlements you should do so in the Apple developer portal. You may need to first generate the App id. You still need to set the following in Visual Studio.

A 2mee message app needs a number of capabilities set to work correctly. It firstly requires the push notification capability. This needs to be added to the Entitlements file.

Push notifications also require the app to do background processing. This is done in the Info.plist.

The main app, service extension, and content notification all require app group capabilities.

App Groups Setup

App groups are a way of sharing data between different apps and app services. App groups are defined in the your App Groups in Certificates, Identifiers and Profiles section of the Apple Developer Portal see Xamain app-groups-capabilities.

App groups can also be created within Xcode itself in the Capabilities section of the project using the + button. You may find it easier to create a shadow app in xcode (app with same bundle id and entitlements) as xcode will generate the correct settings and generate the correct certificates automatically.

Your App, the Content extension, and the Service Extension must use the same group. The name of this group is passed to the Appear2mee SDK in the App, Service Extension and Content Extension. The App Group allows data and files to be passed from the Service Extension to the App. In the Xamarin2mee App the AppGroup name is in a shared library to ensure the same name is used through the project.

namespace AppGroup
{
    public static class MyAppGroup
    {
        public static string name = "group.com.2mee.xamarin";
    }
}

2mee Platform Setup

In order to link the App to the 2mee platform it needs a Client ID and a secret key. These are generated in the 2mee platform. In order for the platform to connect to the App on the device a production push certificate in p12 format is required by the platform. See the 2mee Platform Docs for details of accessing the platform keys and how to upload the p12 certificate.

As the developer you will probably have to provide the push certificate. To generate a p12 certificate you need to access the Apple Developer Certificates, Identifiers & Profiles page, under iOS App ID Settings. Once you have generated and downloaded the certificate, import it to the Key Chain app on your mac, and then export in p12 format (with a password).

Appear2mee Initialisation

In any 2mee face message app a connection to the 2mee Platform is required. The Platform client id and secret key are generated on the 2mee Platform for each app administered. If you are doing the Platform setup as well, see the 2mee Platform Docs. The init method Appear2mee.initWithID( TWOMEE_CLIENT_ID, TWOMEE_SECRET_KEY, SERVER_IP, APPGROUP) is used to allow the app to communicate with the 2mee platform and uses the app group to share files and data with extensions.

Note: All Appear2mee methods are static class methods.

using Appear2meeSDK;
....
....

[Export("application:didFinishLaunchingWithOptions:")]
public bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{ 
    Appear2mee.InitWithID(TWOMEE_CLIENT_ID,
                          TWOMEE_SECRET_KEY, 
                          SERVER_IP,
                          APPGROUP);

    requestAuthorization();
            
    return true;
}

A 2mee message app also requires at least a service extension to process the push notification and preferably also a content extension to display notifications when accessed by 3d touch. Each of these separate processes must be able to share the downloaded files. A common share group is used for this purpose. Files are written and read from a common shared area. The app group is generated by the developer within Xcode. In the example app this name is defined in the AppGroup project and is referenced in each of the separate projects.

To allow notifications the app user needs to give permission for notifications, this is done in the requestAuthorisationMethod method.

Important: If permission is not granted for notifications the app cannot receive messages from the platform.

Requesting Notification Permission

An iOS app requests notification permission using the UNUserNotificationCenter. iOS 12 has introduced a new option of provisional authorisation. In this mode the user will receive notifications without sound in the notification centre. These notifications allow the user to decide when the access the notification how to treat all notifications from your app. It is up to you the developer if you want to use this method, or for the user to have a dialog box presented asking for notification permission. Calling the UNUserNotificationCenter.Current.RequestAuthorization(options,completionHandler) method requests permission. If permission is granted the Appear2mee class method addAppear2meeNotificationCategory should be called to setup UNNotificationCategory for Appear2mee notifications. If the app has other UNNotificationCategory to set, it should do those first, as the AddAppear2meeNotificationCategory adds Appear2mee categories to the existing set.

void requestAuthorization()
{
    UNUserNotificationCenter.Current.Delegate = this;

    UNAuthorizationOptions options;
    if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
    {
        options = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound | UNAuthorizationOptions.Provisional;
    }
    else
    {
        options = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
    }

    UNUserNotificationCenter.Current.RequestAuthorization(options, (approved, err) =>
    {
        if (err == null)
        {
            if (approved)
            {
                // Setup Appear2mee notification actions.
                // Add any other independent UNNotificationCategory before
                // calling this method
                Appear2mee.AddAppear2meeNotificationCategory();
                InvokeOnMainThread(() =>
                {
                    UIApplication.SharedApplication.RegisterForRemoteNotifications();
                });

            }
        }
    });
}

If permission is granted then iOS will call, sometime in the future, the public virtual void RegisteredForRemoteNotifications(application, deviceToken) method. In this method the deviceToken needs to be sent to the 2mee Platform using the Appear2mee.RegisterDeviceToken method. In the example app we also log the device token as a string in the format iOS requires to send a push notification.

[Foundation.Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
public virtual void RegisteredForRemoteNotifications(UIKit.UIApplication application, Foundation.NSData deviceToken)
{
        byte[] bytes = deviceToken.ToArray<byte>();
        string[] hexArray = bytes.Select(b => b.ToString("x2")).ToArray();
        var deviceTokenStr = string.Join(string.Empty, hexArray);
        System.Console.WriteLine("deviceToken:" + deviceTokenStr);
        
        Appear2mee.RegisterDeviceToken(deviceToken);
}

Anytime the RegisteredForRemoteNotifications(application, deviceToken): method is called by iOS the Appear2mee.RegisterDeviceToken class method should be called, as deviceTokens can be changed or invalidate and the 2mee Platform needs to have the latest version even it appears to the app that it is unchanged. This is particularly important in development as multiple installs of production and development versions can lead to tokens being invalidated and then revalidated at a future install.

Receiving Remote Notifications

Notifications are sent by the 2mee Platform to your app. Your app needs to process these notifications using a service extension, which will be discussed later. After the service extension has processed the push notification they can be passed to the main app, if it is active. If the app it is not active, but is in the background, or not launched, notifications are sent to the notification center. When the user has responded to a notification in the notification center the app receives the notification response.

Receiving Notifications when in Foreground

When the application is in the foreground the app can choose to display incoming notifications in the notification center or directly within the app. It is recommended that you direct these notifications to the notification center, to avoid the user being surprised by a popup dialog.

[Foundation.Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public virtual void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
    // Do something with the notification
    Console.WriteLine("Active Notification: {0}", notification);

    if (Appear2mee.IsAppear2meeNotification(notification))
    {
         // notification from 2Mee Platform
         if (this.USE_NOTIFICATION_CENTER_WHEN_ACTIVE)
         {
              completionHandler(UNNotificationPresentationOptions.Alert | 
                            UNNotificationPresentationOptions.Badge |
                            UNNotificationPresentationOptions.Sound);
          }
          else
          {
               Appear2mee.DisplayNotification(notification, acceptExchangeKeyValues =>
               {
                    Console.WriteLine("accepted");
               }, dismissExchangeKeyValues =>
               {
                    Console.WriteLine("dismissed");
               });
               completionHandler(UNNotificationPresentationOptions.None);
          }
      }
      else
      { // handle other notifications
                completionHandler(UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Badge | UNNotificationPresentationOptions.Sound);
      }
}

The hander checks if the notification comes from the Platform, using the call method Appear2mee isAppear2meeNotification(), which will return true if the payload matches a 2mee Platform payload. The recommended step is just to then return the completion handler with the presentation options (USE_NOTIFICATION_CENTER_WHEN_ACTIVE == true). If however you wish to display the notification in the app the class method Appear2mee.DisplayNotification(withAcceptAction, withDismissAction) should be called with the notification and actions to be executed if the user accepts or dismisses the dialog that will be presented. These actions will be called with a dictionary of key/values that were attached to the notification in the 2mee Platform. Typically they can be used to perform some action based on the values present. For example, move to a page on the app {“page”:”sports/mens/shorts”}.

Responding to a Notification

When the user interacts with the notification it can be dismissed or “accepted”. These actions can causes the app to come into the foreground if the notification was accepted or process in the background, where the notification was dismissed. The notification response calls the UNUserNotificationCenterDelegate method DidReceiveNotificationResponse(center, response, action), Typically this delegate is the ApplicationDelegate, in the sample app this is where it is implemented. This method is used to direct the response of the app to the correct notification action.

[Foundation.Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public virtual void DidReceiveNotificationResponse(UNUserNotificationCenter center, 
                                                   UNNotificationResponse response, 
                                                   Action completionHandler)
{
    if (Appear2mee.DidReceiveNotificationResponse(response, acceptExchangeKeyValues =>
      {
        var res = "{" + string.Join(",", acceptExchangeKeyValues.Select(kv => kv.Key + "=" + kv.Value).ToArray()) + "}";
        Console.WriteLine("accepted:" + res);
       }, dismissExchangeKeyValues =>
       {
         var res = "{" + string.Join(",", dismissExchangeKeyValues.Select(kv => kv.Key + "=" + kv.Value).ToArray()) + "}";
         Console.WriteLine("dismissed:" + res);
        }))
    {
                // it was a 2mee Exchange notification
    }
    else
    {
        // some other notification
        // Take action based on Action ID
        switch (response.ActionIdentifier)
        {
            case "reply":
                // Do something
                break;
            default:
                // Take action based on identifier
                if (response.IsDefaultAction)
                {
                    // Handle default action...
                }
                else if (response.IsDismissAction)
                {
                    // Handle dismiss action
                }
                break;
        }
    }
    // Inform caller it has been handled
    completionHandler();
} 

The Appear2mee SDK is able to handle the notification response using the Appear2mee.DidReceiveNotificationResponse(response,acceptAction, dismissAction) returning true if the notification response was from a 2mee notification and false, if some other notification type that needs to be handled differently. This method handles the various possible responses to 2mee notification.

If the user has shown the notification using 3d touch then the response for the notification category will be an accept or dismiss action and the appropriate dismiss for accept action block will be called. If however the user has dismissed the notification with a swipe delete, the dismiss action block is called. If the notification was touched to accept, then the user has not seen the full message, even a text message may have been truncated, and a dialog will be shown with the message. Images/Animations/Videos are shown with a simple popup dialog with dismiss and accept buttons. A face message is shown with a popover where a swipe action outside the face will be a dismiss and a touch on the face will be an accept. These “dialog” responses will call the appropriate dismiss or accept action block.

Note: Notifications can be cleared in the notification center, in which case the app does not get any response.

The class method Appear2mee.DidReceiveNotificationResponse(response,acceptAction, dismissAction) is called with the notification response and the Actions to be executed if the user has/does accept or dismiss the notification. These Actions will be called with a dictionary of key/values that were attached to the notification in the 2mee Platform. Typically they can be used to perform some action based on the values present. For example, move to a page on the app {“page”:”sports/mens/shorts”}.

Silent Push Notifications

The 2mee Platform can also send silent notification, these too have to be processed by the Appear2mee SDK. Silent push notifications are handled in the app delegate DidReceiveRemoteNotification( application, userInfo, completionHandler). Not all notifications may relate to 2mee messages. The class method Appear2mee.DidReceiveRemoteNotification(userInfo, completionHandler) should be called to determine if the Appear2mee SDK has handled the incoming notification. If it is not a Appear2mee related notification the method will return false and pass control back, to allow the developer to handle the notification. If the method returns true the notification has been fully processed and the fetchCompletionHandler has already been called with the appropriate argument.

[Foundation.Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
public virtual void DidReceiveRemoteNotification(UIApplication application, 
                                                 NSDictionary userInfo, 
                                                 System.Action<UIBackgroundFetchResult> completionHandler)
{
    Console.WriteLine("Silent Notification: {0}", userInfo);
    var result = Appear2mee.DidReceiveRemoteNotification(userInfo, 
                                                         completionHandler);
    if (result)
    {
        // already handled by Appear2mee
    }
    else
    {
        completionHandler(UIBackgroundFetchResult.NoData);
    }
}

Service Extension

A service extension is used for mutable content remote push notification handling. The 2mee Platform sends push notifications with a payload of data, which can include a urls of message content. The service extension attempts to download these files and optionally create an image attachment that is displayed in the notification. The Appear2mee SDK also copies files to a shared data area so the the app itself can access the messages to. To copy the file the Services Extension and App must use App Groups as discussed above.

In Visual Studio you should add a Service Extension. If you already have a service extension you will need to modify it to include Appear2mee functionality. There is only one service extension per app.

Visual Studio will generate a temple for the service extension. You must add the NuGet package Appear2meeiOS to the service extension, using the same method as in your App.

Then edit the NotificationService.cs

The entry point to a service extension is the DidReceiveNotificationRequest method. To support the Appear2mee SDK the requestIdentifier must be stored. If the notification request has been sent from the 2mee Platform, the Appear2mee.handleAppear2meeNotification(BestAttempt, request,contentHandler, appGroup) class method will handle any file downloads and return true. If it is not a 2mee Platform notification the method immediately returns false and the developer is free to handle the notification as required.

using Appear2meeSDK;
using AppGroup;
....

[Register("NotificationService")]
public class NotificationService : UNNotificationServiceExtension {
    String requestIdentifier; 
    .....
      
    public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
    {
        ContentHandler = contentHandler;
        BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();
        requestIdentifier = request.Identifier;

        if (Appear2mee.HandleAppear2meeNotificationContent(BestAttemptContent, requestIdentifier, contentHandler,MyAppGroup.name))
        {
                // Was an Appear2mee notification and has been handled.
        }
        else
        {
            // Modify the notification content here...
            //BestAttemptContent.Title = $"{BestAttemptContent.Title}[modified]";
            ContentHandler(BestAttemptContent);
        }    
    }

As the service extension is only allowed a limited amount of time, the download might not be completed, which means that the HandleAppear2meeNotification method can be timeout asynchronously by a system call to TimeWillExpire method. The download tasks used by this method need to be canceled and the requestIdentifier stored earlier is used by the Appear2mee.cancelDownloadForRequest(requestIdentifier) method to identify which download tasks should be canceled.

public override void TimeWillExpire()
{
    // cancel any uncompleted tasks
    Appear2mee.CancelDownloadForRequest(requestIdentifier);

    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified 
    // content, otherwise the original push payload will be used.
    ContentHandler(BestAttemptContent);
}

App Groups Setup

The Service Extension target capabilities must include an App Group with the same group as used for the main app, so that the same file area is used to store and share common data and files. Adding this entry is on its own not sufficient to assign an App Group to your app id. You will need to go to the Certificates, Identifiers & Profiles section on Apple Developer Center and assign them there too. See Xamain app-groups-capabilities or see the note below if you have Xcode.

Note: You may find it easier to create a shadow app in Xcode, an app with same bundle id and entitlements, with a service extension of the same name. Xcode will generate the correct settings and the correct certificates automatically. You will still have to enter these into your Xamarin app, but you will not need to use the Certificates, Identifiers & Profiles section on Apple Developer Center.

Content Extension

Notifications that display complex content can use the default iOS display given when the user uses 3d touch (hard press). However, we can customise the way our notification content is displayed, using a notification extension. This allow us to display and play a face message (or image/animation/video) within the notification and stop/restart the message by touching the face/video.

A content extension target should be generated in Visual Studio, then there are a number of steps to adapting the extension for 2mee messages, but the sample app gives a fully working example that can be transfer easily to your own app. The content extension when running uses files that have been downloaded by the service extension or the app itself and stored in an App Group. The content extension must be given access to this shared area. Using the shared files not only allows 2mee messages to be displayed in the app itself, if required, but also seems to be more reliable than using attachments, which can occasionally fail.

After the target is created the info.plist NSExtension entry should be edited. The UNNotificationExtensionCategory MUST be appear2meeNotificationCategory. This is the category that the service extension will direct all 2mee messages too. Also to enable user touch capabilities UNNotificationExtensionUserInteractionEnabled entry must be added if not present and set to YES. Lastly the UNNotificationExtensionInitialContentSizeRatio should be set to 0.6.

You must add the NuGet package Appear2meeiOS to the service extension, using the same method as in your App.

NotificationViewController — Storyboard

A content extension created by Visual Studio contains a storyboard. It is recommended that you replace that with the one in the sample project. The sample project storyboard contains a custom UIView of type Appear2meeContentView. This view is able to display all the different types of content sent by the 2mee platform, face messages, images, animations and videos.

NotificationViewController

The Content Extension is a separate process from the app and service extension, and uses a NotificationViewController. The code itself very small as the real work is done in the Appear2meeContentView class that is a type of UIView in the storyboard file. The entry point is the DidReceiveNotification method. In this an instance of Appear2meeContentView is given the notification to display along with the NotificationViewController instance and the common App Group. Access to NotificationViewController which is an instance of UIViewController<UNNotificationContentExtension> allows the contentView to set the title on the “accept” action button or removed that button if a message has expired (in iOS 12).


using AppGroup;
......

namespace content2mee
{
    public partial class NotificationViewController : UIViewController, IUNNotificationContentExtension
    {
        protected NotificationViewController(IntPtr handle) : base(handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            // Do any required interface initialization here.
        }

        public void DidReceiveNotification(UNNotification notification)
        {
            contentView.DisplayNotification(notification,this,MyAppGroup.name);
        }

        [Export("didReceiveNotificationResponse:completionHandler:")]
        public void DidReceiveNotification(UNNotificationResponse response, Action<UNNotificationContentExtensionResponseOption> completionHandler)
        {
            contentView.DidReceiveNotificationResponse(response, completionHandler);
        }
    }
}

Responses to the content extension notification are send to the UNNotificationContentExtension protocol DidReceiveNotification(response, completionHandler), and are passed the the contentView to process.

App Groups Setup

The Content Extension target capabilities must include an App Group with the same group as used for the main app and shared in the demo app using common library, so that the same file area is used to store and share common data and files. Adding this entry is on its own not sufficient to assign an App Group to your app id. You will need to go to the Certificates, Identifiers & Profiles section on Apple Developer Center and assign them there too. See Xamain app-groups-capabilities or see the note below if you have Xcode.

Note: You may find it easier to create a shadow app in Xcode, an app with same bundle id and entitlements, with a service extension of the same name. Xcode will generate the correct settings and the correct certificates automatically. You will still have to enter these into your Xamarin app, but you will not need to use the Certificates, Identifiers & Profiles section on Apple Developer Center.

Further Steps

After completing the App setup and the service and content extensions the app will be functional. There are other options that you might need to setup within the app.

Customisation with userID

Many apps are linked to a separate system and have some kind of user identity. The SDK allows the app to store a userID. The 2mee platform can return reports based on a user supplied userID. This id should be a string and can be supplied after the init of the Appear2mee SDK using the class method Appear2mee.RegisterUserID. If a userID is not supplied the device token is used as the userID. In the demo app there is a button [set UserID] that can be used to open a text dialog to input a userID.

Check List

App

Add Appear2meeiOS NuGet package

Required Capabilities: push Notification

Required Capabilities: Remote Notifications

Required Capabilities:App Groups, Create App Group and Assign

Info.plist: Background Mode

Add App Group, to share with Extensions

Platform Keys, ClientID and Key. Init method

Request Notification Permission method, AddAppear2meeNotificationCategory.

Register deviceToken method

Handle Notifications when App is in foreground

Respond to notifications responses

Handle Silent Notifications

Service Extension

Create a Service Extension (Note: there is only one per App)

Add Appear2meeiOS NuGet package

Required Capabilities:App Groups, Assign same group as App.

Handle the Notification Request

Handle the Time Will Expire method

Content Extension

Create a Content Extension (Note: there can be many per App).

Add Appear2meeiOS NuGet package

Required Capabilities:App Groups, Assign same group as App.

Info.plist: Set UNNotificationExtensionCategory to appear2meeNotificationCategory

Info.plist: Set UNNotificationExtensionInitialContentSizeRatio to 0.6

Info.plist: Set UNNotificationExtensionUserInteractionEnabled to YES

Copy Demo MainInterface.storyboard to new Content Extension.

Handle DisplayNotification

Handle DidReceiveNotificationResponse

Android

If you need to download the Appear2mee Xamarin apps before starting this guide, you can do so here at http://www.2meefiles.com/Appear2meeXamarinSDK.zip (open in a new window).

The first step in Visual Studio is to create or open an existing Android app.

NuGet packages

Next install the Appear2meeAndroidSDK NuGet package. This is the package that contains the SDK. The 2mee Exchange sends notifications via firebase. If your app is not already setup to receive firebase notifications you will also need to include the NuGet packages associated with firebase notification, and setup the google services json file. See below for more details on google services installation, but first include the xamerin.googleplayservices.base and the xamerin.firebase.messaging NuGet packages. These packages will also install some dependencies. One dependency that was not pulled in atomically was xamarin.google.dagger. You should include this package too if you find your project does not compile.

Android Manifest

A 2mee enabled message app uses a number of components that are included in the SDK but must be given permission to be used in the AndroidManifest.xml file. These are the Appear2meeNotificationActivity that is called when a notification is selected. An internal JobService that downloads files. A broadcast receiver that is used to trigger the local notification at the correct time.

The AndroidManifest is found in the properties folder and can be edited directly by opening as a source file.

The manifest changes require customisation to match you apps MainActivity class. The Appear2mee in app notification notification view appears on top of your MainActivity call and within the manifest should be a fully qualified package name.

Note: The Appear2meeNotificationActivity uses an openGL View. Apps by default allow openGL views, but if you app has hardwareAccelerated set to false, you will need to set it to true either for the whole app or just the Appear2meeNotificationActivity activity, in your AndroidManifest.xml.

<application android:allowBackup="false" 
             android:icon="@mipmap/icon" 
             android:label="@string/app_name"
             android:name=".Appear2meeApplication">
		<!-- Appear2mee Notification Activity -->
		<activity android:name="com.twomee.appear2mee.Appear2meeNotificationActivity" 
		android:parentActivityName="com.twomee.Xamarin2mee.MainActivity"
		android:hardwareAccelerated="true"
		android:launchMode="singleTop" 
		android:theme="@style/Appear2mee.Translucent">
		<meta-data android:name="android.support.PARENT_ACTIVITY" 
		          android:value="com.twomee.Xamarin2mee.MainActivity" />
		</activity>
		<!-- Appear2mee Internal Job Service -->
		<service android:name="com.twomee.appear2mee.Appear2meeJobService" 
		         android:exported="false" 
		         android:permission="android.permission.BIND_JOB_SERVICE">
		</service>
		<!-- Appear2mee Internal Receiver triggered at Message Play Time -->
		<receiver android:name="com.twomee.appear2mee.Appear2meeNotificationBroadcastReceiver" />
		<!--  Firebase Messaging default uses ad id.-->
		<meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
		<meta-data android:name="com.google.firebase.messaging.default_notification_icon" 
		           android:resource="@mipmap/ic_launcher" />
</application>

See the demo app to copy paste to your app.

Note: The MainActivity class should not be allowed to have the default Xamarin path, but be assign the class path

[Activity(Name = "com.twomee.Xamarin2mee.MainActivity", 
          Label = "@string/app_name", 
          MainLauncher = true, 
          Icon = "@mipmap/icon")] 
public class MainActivity : Activity {
    ......

2mee Exchange Setup

In order to link the App to the exchange it needs a Client ID and a secret key. These are generated in the 2mee Exchange (the same exchange Client ID and secret key are used in the iOS app).

In order for the 2mee Exchange to connect to the App on the device the firebase cloud messaging server key, and firebase cloud messenger sender id (project number in google-services.json) are required by the exchange. The exchange uses the server key to authorise sending push notifications and the sender id/project number is used to check that deviceTokens registered on the exchange are for the same project as the server key. See the 2mee Exchange Docs for details of how to add the server key and senderid. The project server key are found in your firebase settings for your project.

Appear2mee Initialisation

The Appear2mee SDK needs to be setup in the Application class. This is to ensure that SDK is setup when a notification is opened. By default Xamarin Android apps do not create an application class, be rely on the base Application. An application class has to be created.

Documentation on how to create an Application class is poor and conflicting. See the demo app Appear2meeApplication.cs for a working example. The main requirement some to be the constructor with (IntPtr javaReference, JniHandleOwnership transfer) arguments. The application should also be given a fully qualified as this name is used within the AndroidManifest.

using Com.Twomee.Appear2mee;
.....

namespace Xamarin2mee
{
    [Application(Name = "com.twomee.Xamarin2mee.Appear2meeApplication")]
    public class Appear2meeApplication :  Application, Com.Twomee.Appear2mee.Appear2mee.IResponseListenerCallback
    {
     // Required constructor
        public Appear2meeApplication(IntPtr javaReference, JniHandleOwnership transfer)
          : base(javaReference, transfer) { }

The Appear2mee.Init is used within the OnCreate function.

        private static string APPEAR2MEE_CLIENT_ID = "<EXCHANGE_CLIENT_ID";
        private static string APPEAR2MEE_SECRET_KEY = "<EXCHANGE_KEY>";
        private static string APPEAR2MEE_SERVER_IP = "https://exchangebridge.2mee.com/";
   
        public override void OnCreate()
        {
            base.OnCreate();
            Appear2mee.Init(this, APPEAR2MEE_CLIENT_ID, APPEAR2MEE_SECRET_KEY,
                                               APPEAR2MEE_SERVER_IP);
        }
        .......
     }
}

Registering for and Receiving Remote Notifications

The FirebaseMessagingService is used to both handle device tokens registration on the 2mee Exchange and also receive then forward Firebase messages. If you have not used the FirebaseMessagingService before you should read the documentation at https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService.

If you are not familiar with Firebase then you should read the requirements for Android setup at https://firebase.google.com/docs/android/setup. If you are setting up a new project you will need to add the google-services.json to your project. This is found in your Firebase project settings.

The google-services.json file should be added to your project and the Build Action set to GoogleServicesJson.

Registering the Device Token

See the class MyFirebaseMessagingService.cs in the Android demo app. If have not already implemented firebase notifications in your app, copy this class. The onNewToken method should contain an Appear2mee call to the registerDeviceToken function. This method will register the app on the exchange.

public override void OnNewToken(string token)
{
    Log.Debug(TAG, "FCM token: " + token);
    Appear2mee.RegisterDeviceToken(token);
}

Receiving Remote Notifications

Push notifications are handled in the FirebaseMessagingService onMessageReceived. Exchange messages are data messages, and are handled using the Appear2mee.ObjectOnMessageReceived function. (This function has been renamed for Xamarin as the RemoteMessage is passed as an Object because the AndroidBindings generated by Xamarin did not recognise the RemoteMessage Object)

public override void OnMessageReceived(RemoteMessage message)
{

   var isMessageAppear2mee = Appear2mee.ObjectOnMessageReceived(message);
   if (isMessageAppear2mee)
   {
       // nothing to do. Already handled.
    }
    else
    {   // other notifications.  
        Log.Debug(TAG, "From: " + message.From);
        var body = message.GetNotification().Body;
        SendNotification(message);
    }
}

The Appear2mee.ObjectOnMessageReceived determines if the message is from the 2mee Exchange. If it is not a 2mee Exchange notification the function will return false and pass control back to allow the developer to handle the notification. If the function returns true the notification has been fully processed by the SDK.

Responding to Local Notifications

Remote push notifications are sent by the 2mee Exchange to your app, these notifications do not include an alert so that on receipt they are silent. The Appear2mee SDK has to process these notifications, downloaded any files and schedule an internal alarm at the play time. When the alarm is triggered the Appear2mee SDK displays a local notification

When the user interacts with the local notification it can be dismissed or “accepted”. If the notification was accepted the app will to come into the foreground or launch, and the Appear2meeNotificationActivity is started. When Appear2meeNotificationActivity launches it calls the appear2meeResponseListener callback function in the Application class (which must implement Appear2mee.ResponseListenerCallback). The appear2meeResponseListener callback returns a Appear2mee.ResponseListener, which determines what actions are taken when the user dismisses/accepts the dialog or face message. For example,

using Com.Twomee.Appear2mee;
...... 

namespace Xamarin2mee
{

    [Application(Name = "com.twomee.Xamarin2mee.Appear2meeApplication")]
    public class Appear2meeApplication :  Application, Appear2mee.IResponseListenerCallback
    {
        
        .........
        
        Appear2mee.IResponseListener Appear2mee.IResponseListenerCallback.Appear2meeResponseListener(Bundle payload)
        {
            return new Appear2meeResponse();
        }
    }

    class Appear2meeResponse : Java.Lang.Object, Appear2mee.IResponseListener
    {

        void Appear2mee.IResponseListener.AcceptAction(IDictionary<string, string> keyValueDict)
        {
            Context context = Application.Context;
            ToastLength duration = ToastLength.Short;
            var res = "{" + string.Join(",", keyValueDict.Select(kv => kv.Key + "=" + kv.Value).ToArray()) + "}";
            var toast = Android.Widget.Toast.MakeText(context, "Accept key/values" + res, duration);
            toast.Show();
        }

        void Appear2mee.IResponseListener.DismissAction(IDictionary<string, string> keyValueDict)
        {
            Context context = Application.Context;
            ToastLength duration = ToastLength.Short;
            var res = "{" + string.Join(",", keyValueDict.Select(kv => kv.Key + "=" + kv.Value).ToArray()) + "}";
            var toast = Android.Widget.Toast.MakeText(context, "Dismiss key/values" + res, duration);
            toast.Show();
        }

    }
}

In the Appear2meeNotificationActivity images/Animations/Videos are shown with a simple popup dialog with dismiss and accept buttons. A face message is shown with a popover where a swipe action outside the face will be a dismiss and a touch on the face will be an accept. These “dialog” responses will call the appropriate dismiss or accept listener action function.

The dismissAction/acceptAction functions are called with a dictionary of key/values that were attached to the notification in the 2mee Exchange. Typically they can be used to perform some action based on the values present. For example, move to a page on the app {“page”:”sports/mens/shorts”}.

Note: Notifications can be cleared in the notification drawer, in which case the app does not get any response.

Note: The Application class should implement the Appear2mee.IResponseListenerCallback

Notification View Icon

The default notification icons are 2mee png icons. To replace these icons you will need to name at least one image in your res/mipmap*** resources appear2mee_notification_icon, for the notification icon. The status bar notification icon (which is normally white on transparent) is called appear2mee_notification_icon_small and should be included in your drawables. See an android icon maker to make this status bar icon.

Auto backup

Apps that target Android 6.0 (API level 23) or higher are automatically enabled for Auto Backup. Xamarin android apps be default (at the time of writing) set the android:allowBackup=“true”. If your app does require backup, steps must be taken to avoid backing up the device connection to the 2mee exchange. Some of the Appear2mee SDK app data should not be backed up. It includes the device token and device specific data connecting the device to the 2mee Exchange. If a new device uses a backup it can lead to two devices connected to the same device entry and potentially a clash of settings. The userID and tags are stored in a different sharepref, and will be backed up, as these are in app user preferences.

In order to avoid backing up incorrect data your app should use the option to define which preferences are backed up.

<application
  android:name="com.twomee.appear2meereact.MainApplication"
  android:label="@string/app_name"
  android:icon="@mipmap/ic_launcher"
  android:roundIcon="@mipmap/ic_launcher_round"
  android:allowBackup="true" 
  android:fullBackupContent="@xml/my_backup_rules"
  android:theme="@style/AppTheme">
  <activity

In resources a file res/xml/my_backup_rules.xml defines which data to exclude from backup.

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <exclude domain="sharedpref" path="APPEAR2MEE.xml"/>
</full-backup-content>

This file and the application options should be included in your project.

The alternative is to disallow backups.

Further Steps

After completing the App setup the app will be functional. There are other options that you might need to setup within the app.

Customisation with userID

Many apps are linked to a separate system and have some kind of user identity. The SDK allows the app to store a userID. The 2mee exchange can return reports based on a user supplied userID. This id should be a string and can be supplied after the init of the Appear2mee SDK using the class method Appear2mee.registerUserID. If a userID is not supplied the device token is used as the userID. In the demo app there is a button [userID] that can be used to set the userID to the text in an input textbox.

Android Check List

App

Download firebase project google-services.json

Get Exchange Keys, ClientID and Key, for Appear2mee init.

Required permissions in AndroidMainifest

NuGet Appear2meeAndroidSDK, Firebase NuGet

Generate custom Application class. Implements ResponseListenerCallback

Application Class Name in AndroidMainifest

Implement ResponseListener, accept/dismiss actions

Add auto backup options to AndroidManifest, and exclude file to Resources

Add appear2mee_notification_icon to resources (mipmap)

Add appear2mee_notification_icon_small to resources (drawables)

MyFirebaseMessagingService Class

Register deviceToken in onNewToken function

Handle Appear2mee Notifications in onMessageReceived Function.

Handle other Notifications in onMessageReceived Function.

Last updated