1. Home
  2. Developers
  3. Xamarin
  4. Xamarin.Android Plugin

Xamarin.Android Plugin

This document will show you how to integrate the Apptentive SDK into your Xamarin.Android app, configure it, and test to make sure it’s working properly. Each section lists the minimum necessary configuration, as well as optional steps.

System Requirements

Minimum SDK version: 14 (Android 4.0)

Dependencies

Our SDK has a dependency on the following support libraries, version 28.0.0

If you use a newer version of any support library, you will need to include a newer version of all four of the above libraries in your app. This avoids potential issues caused by a mismatch in support library versions.

Supported Languages

We have translated all hard-coded strings in our SDK into the following languages. The content of all Interactions comes from our server, and you may translate the text for each Interaction by visiting the Translations Page.

Locale Qualifier Language Name
None English
ar Arabic
el Greek
da Danish
de German
es Spanish
fr French
fr-rCA French Canadian
it Italian
ja Japanese
ko Korean
nl Dutch
pl Polish
pt Brazilian Portuguese
ru Russian
sv Swedish
tr Turkish
zh Chinese (Traditional)
zh-rCN Chinese (Simplified)

 

Adding Apptentive

NuGet

Using the NuGet package manager is the easiest way to integrate. Follow the official Microsoft Visual Studio NuGet guide to add Apptentive.Android package to your project.

Register Apptentive

Register Apptentive in your Application class.

using System;
using Android.App;
using Android.Runtime;
using ApptentiveSDK.Android;

namespace ApptentiveSample
{
    [Application]
    public class MyApplication : Application
    {
        public MyApplication(IntPtr handle, JniHandleOwnership ownerShip)
            : base(handle, ownerShip)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();
            Apptentive.Register(this, "Your Apptentive Key", "Your Apptentive Signature");
        }
    }

}

Make sure you use the Apptentive App Key and Signature for the Android app you created in the Apptentive console. Sharing these keys between two apps, or using keys from the wrong platform is not supported, and will lead to incorrect behavior. You can find them here.

Styling Apptentive

Apptentive will inherit your app’s styles by default. If you are using a Light/Dark AppCompat theme, Apptentive will look like your app by default. But if you are using another theme, or if you want to force Apptentive to adopt different styles than your app, please follow instructions in Android Interface Customization.

Message Center

Showing Message Center

With the Apptentive Message Center your customers can send feedback, and you can reply, all without making them leave the app. Handling support inside the app will increase the number of support messages received and ensure a better customer experience.

Message Center lets customers see all the messages they have send you, read all of your replies, and even send screenshots that may help debug issues.

Add Message Center to talk to your customers.

Find a place in your app where you can add a button that opens Message Center. Your settings page is a good place.

protected override void OnCreate(Bundle savedInstanceState)
{
    ...
    var messageCenterButton = FindViewById<Button>(Resource.Id.messageCenterButton);
    // Don't show the button until Message Center is available
    Apptentive.CanShowMessageCenter((canShow) => {
        if (canShow)
        {
            messageCenterButton.Visibility = Android.Views.ViewStates.Visible;
            messageCenterButton.Click += delegate
            {
                Apptentive.ShowMessageCenter(this, (shown) => Console.WriteLine("Message Center shown: " + shown));
            };
        }
        else
        {
            messageCenterButton.Visibility = Android.Views.ViewStates.Gone;
        }
    });
    ...
}

Checking Unread Message Count

You can also check to see how many messages are waiting to be read in the customer’s Message Center.

var unreadMessageCount = Apptentive.UnreadMessageCount;

Unread Message Count Notification

You can receive a callback when a new unread message comes in. You can use this callback to notify your customer, and display a badge letting them know how many unread messages are waiting for them. Because this listener could be called at any time, you should store the value returned from this method, and then perform any user interaction you desire at the appropriate time.


protected override void onCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    SetContentView(Resource.Layout.Main);

    Apptentive.AddUnreadMessagesListener(this);
}

public void OnUnreadMessageCountChanged(int count)
{
    // Your code here
}

Note: Do not pass an anonymous listener to Apptentive.

The listener will not be run on the UI thread, and may be called from a different Activity than the one that is set on the listener. The correct way of setting Apptentive listeners is to create a listener with the same lifecycle as it’s intended usage, then passing it to Apptentive. For example, if the listener is going to be used in a specific activity, make the listener an Activity data member. This way, when the activity is gone, the listener will automatically be garbage collected and Apptentive will know about this through WeakReference (and we’ll stop calling the listener).

Send Custom Data With a Message

You can pass in custom key/value pairs to Message Center that will be sent in the next message that the customer sends while Message Center is open. For instance, if you have a dining app, you could pass in a key of restaurant_name and value of Chipotle. If the customer sends a more than one message, only the first message will include this custom data. If you wish to add more custom data to another subsequent message, you will need to call this method with custom data again. Custom data can be of type String, Number, or Boolean.

var customData = new Dictionary<string, Java.Lang.Object>
{
    { "restaurant", "Joe's Pizza" },
    { "total_amount_spent", 32.25 }
};

Apptentive.ShowMessageCenter(this, (shown) => Console.WriteLine("Message Center shown: " + shown), customData);

You will see this custom data on the message in the Conversations View.

Attachments

Attachments are messages that you can send from the SDK programmatically, which will be visible to you in the Conversation View, but will not be visible to your customers in Message Center. They are great for sending contextual information or logs from rare crash events.

Hidden File Attachments

Hidden Text Messages

// Send a file.
using (var stream = File.OpenRead("<path>"))
{
    Apptentive.SendAttachmentFile(stream, "application/json");
}
// Send a text message.
Apptentive.SendAttachmentText("Message to display in the conversation view.");

Events

Events record user interaction. You can use them to determine if and when an Interaction will be shown to your customer. You will use these Events later to target Interactions, and to determine whether an Interaction can be shown. You trigger an Event with the Engage() method. This will record the Event, and then check to see if any Interactions targeted to that Event are allowed to be displayed, based on the logic you set up in the Apptentive Dashboard.

One good place to add an Event is when an Activity gains focus.

Apptentive.Engage(this, "my_event", (engaged) => Console.WriteLine("Interaction engaged: " + engaged));

Another is when a button is tapped or clicked.

sendButton.Click += delegate
{    
    Apptentive.Engage(this, "send_event");
};

When the user performs an action that indicates they are having a good experience:

void UserLikedArticle(bool liked) {
  if (liked) {
    Apptentive.Engage(this, "user_liked_article");
  }
}

If your app has a settings switch, you can add an Event when the switch is flipped.

var enableNotificationsSwitch = FindViewById<Switch>(Resource.Id.EnableNotificationsSwitch);
enableNotificationsSwitch.Checked = Preferences.NotificationsEnabled;
enableNotificationsSwitch.CheckedChange += (sender, args) =>
{
    Preferences.NotificationsEnabled = args.IsChecked;
    ToggleNotifications(args.IsChecked);
    Apptentive.Engage(this, "toggle_enable_notifications");
};

You can also add an Event when your app encounters an error.

try {
  processUserInput();
} catch (Exception e) {
  Log.e(TAG, e);
  Apptentive.engage(this, "exception_processing_user_input");
}

You can add an Event almost anywhere in your app, just remember that if you want to show an Interaction at that Event, it needs to be a place where launching an Activity will not cause a problem in your app.

We recommend that you create at least 10 Events. This gives you the flexibility to choose the best place for Interactions to display after your app is live, without having to update your app.

Note: Make sure you don’t start another Activity right after calling Apptentive.Engage(). If you do, and the Engage() call launches an Interaction, then the Activity you launch will cover it up. Instead, call Engage() in the OnResume() of that new Activity, or check the return value of Engage(). If it returns true, it is about to launch an Activity.

Event Names

Our web dashboard works best for up to several dozen unique event names. It does not work well if you auto-generate thousands of unique event names. If you plan to target users based on viewing a piece of content out of a collection of hundreds or thousands (say, SKUs in an online retail app), do not create event names for each piece of content. Instead, you can use Custom Person Data for item viewed.

For example, you could set a key of viewed_item with a value 123456. You could then target users for whom that key matches, or is not null.

 

Interactions

All of the following Interactions can be configured in the Apptentive Dashboard to show up when any of your Events are engaged.

Ratings Prompt

Ratings prompts can help learn about your customer, asking customers that love your app to rate it in the applicable app store, and customer who don’t love it yet to give you feedback, or answer a Survey.

Surveys

Surveys are a powerful tool for learning about your customers’ needs.

Notes

Notes allow you to show an alert to customers, and optionally direct them to a Survey, Message Center, a Deep Link, or simply dismiss the Note.

Upgrade Messages

Upgrade Messages allow you to show a message to customers when they upgrade from an older version of your app to a specified version.

Push Notifications

Apptentive can send push notifications to ensure your customers see your replies to their feedback in Message Center.

Supported Push Providers

  • FCM

Firebase Cloud Messaging

If you are using Firebase Cloud Messaging (FCM) directly, without another push provider layered on top, please follow these instructions.

  1. Follow the FCM instructions to Set Up a Firebase Cloud Messaging Client App.
  2. Go to Integrations, choose Apptentive Push, and enter your FCM Server Key.
    Where is my Server Key?

    1. Open the Firebase Console: https://console.firebase.google.com
    2. Click on the appropriate project
    3. Click the little gear in the upper left corner, and select “Project Settings”
    4. Click the “Cloud Messaging” tab
    5. Copy the Server Key
    6. Enter this key in the Apptentive Push integration

  3. In your FirebaseInstanceIdService, pass Apptentive your token.
    using System;
    using Android.App;
    using Firebase.Iid;
    using Android.Util;
    using ApptentiveSDK.Android;
    
    namespace ApptentiveSample
    {
        [Service]
        [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
        public class MyFirebaseIIDService : FirebaseInstanceIdService
        {
            const string TAG = "MyFirebaseIIDService";
            public override void OnTokenRefresh()
            {
                var refreshedToken = FirebaseInstanceId.Instance.Token;
                Log.Debug(TAG, "Refreshed token: " + refreshedToken);
                Apptentive.SetPushNotificationIntegration(Apptentive.PushProviderApptentive, refreshedToken);
            }
        }
    }
  4. In your FirebaseMesagingService, get the title, body, and PendingIntent from the incoming push, and create a Notification to display to your customer. If the returned PendingIntent is null, then the push did not come from Apptentive, and you should handle it yourself.
    using System;
    using Android.App;
    using Android.Content;
    using Android.Media;
    using Android.Support.V4.App;
    using Android.Util;
    using ApptentiveSDK.Android;
    using Firebase.Messaging;
    
    namespace ApptentiveSample
    {
        [Service]
        [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
        public class MyFirebaseMessagingService : FirebaseMessagingService
        {
            const string TAG = "MyFirebaseMsgService";
    
            /**
             * Called when message is received.
             */
    
            public override void OnMessageReceived(RemoteMessage message)
            {
                var data = message.Data;
    
                if (Apptentive.IsApptentivePushNotification(data))
                {
                    Log.Error(TAG, "Apptentive push.");
                    var title = Apptentive.GetTitleFromApptentivePush(data);
                    var body = Apptentive.GetBodyFromApptentivePush(data);
                    Apptentive.BuildPendingIntentFromPushNotification((pendingIntent) =>
                    {
                        // This push is from Apptentive, but not for the active conversation, so we can't safely display it.
                        if (pendingIntent == null)
                        {
                            Log.Error(TAG, "Push notification was not for the active conversation. Doing nothing.");
                            return;
                        }
    
                        var defaultSoundUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
                    	var notificationBuilder = new NotificationCompat.Builder(this)
                        	.SetSmallIcon(Resource.Drawable.apptentive_status_gear)
                        	.SetContentTitle(title)
                        	.SetContentText(body)
                        	.SetAutoCancel(true)
                        	.SetSound(defaultSoundUri)
                        	.SetContentIntent(pendingIntent);
                    	var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
                    	notificationManager.Notify(0, notificationBuilder.Build());
                        
                    }, data);
                }
                else
                {
                    // Non-Apptentive push
                }
            }
        }
    }

Customer Authentication

At Apptentive, you are our customer, and we refer to your customers as consumers. If you have multiple consumers using your app, you may want to use Customer Authentication to protect each customer’s information from one another. Customer Authentication requires that you have authentication built into your app, and will also require you to modify your server’s authentication code to pass authentication information back to your app, and then to Apptentive. For more information on this feature, see our Customer Authentication Configuration Guide.

If you do not want to use Customer Authentication, or don’t have an authentication mechanism in your app, then Apptentive will still function, but all information will be stored in the same conversation.

How we log a customer in

Your server will authenticate a customer when they log in. At that time, you will need to generate a JSON Web Token (JWT) with a specific format, and signed with the JWT Signing Secret in your app’s API & Development page.

Logging a Customer In

The JWT will be a string. When your server generates a JWT, you will need to send it back to your app, and then log in to Apptentive with it. You will also need to pass in a callback that will allow you to handle login failures. Your callback must implement the Apptentive.LoginCallback interface.

Apptentive will securely manage the JWT. It is important not to reuse a JWT, or to store it in the app.

Apptentive.Login(yourLoginToken, (success, error) => Console.WriteLine("Login succeeded: " + shown + " (error: " + error + ")")); 

Logging a Customer Out

You should make sure to log a customer out any time you invalidate the customers session in your app. That means that when a customer explicitly logs out, you should also log them out of Apptentive. When they are logged out after a certain amount of time, you should likewise also log them out of Apptentive.

Apptentive.Logout();

Note: If your customer has logged out of your app, but you don’t log them out of Apptentive, their personal information may be visible to other app users.

Handling Authentication Failures

The JWT you create will have an expiration date, and will be signed with a secret. When the JWT expires, the server will reject any requests made with it. In this case, you should ask your customer to log in again. Other failure reasons are provided as well, but are only likely to occur during integration if there is a mistake in how you generate a JWT.

It is a good practice to choose an expiration that is longer than your normal session duration so that Apptentive does not cause your customer to need to re-authenticate.

Apptentive.SetAuthenticationFailedListener(yourAuthenticationFailedListener);
IAuthenticationFailedListener

Implement your IAuthenticationFailedListener, and keep a static reference to it, to avoid it being garbage collected. We do not store a strong reference to this listener.

public interface IAuthenticationFailedListener
{
    void OnAuthenticationFailed(Apptentive.AuthenticationFailedReason reason);
}
Logged Out Experience

When no customer is logged in, Apptentive’s public API methods will no-op. If you are using Message Center, and the button that launches it is visible in a part of your app that your customers can access without logging in to your app, you should follow the Message Center instructions above to hide the button unless Message Center can be shown.

Customer Information

Set Customer Contact Information

If you already know the customer’s email address or name, you can pass them to us to display in the conversation view on your Apptentive dashboard.

Apptentive.PersonEmail = email;
Apptentive.PersonName = name;

Message Center provides dialogs that allow your customers to set their name and email as well. Calling the above methods will overwrite what your customer enters. If you don’t want to overwrite what they enter, you can check their values first.

var email = Apptentive.PersonEmail;
var name = Apptentive.PersonName;

Custom Data

You can send Custom Data associated with either the device, or the person using the app. This is useful for sending user IDs and other information that helps you support your users better. Custom Data can also be used for configuring when Interactions will run. You can add custom data of type string, number, and bool.

Examples

Apptentive.AddCustomPersonData("user_id", 1234567890);
Apptentive.AddCustomPersonData("country", "United States");
Apptentive.AddCustomPersonData("pro_membership", true);

Apptentive.AddCustomDeviceData("wifi_only", true);

Other

Customizing the Look and Feel

Please see our Customization Guide for more information.

Updated on January 29, 2019

Was this article helpful?

Related Articles