Filters

Xamarin Android - OLD

❗️

Google Play Services version 17+

If you reference Google Play Services version 17 or higher, you MUST complete Google's update instructions here.

Due to a major Google Play Services change made in June 2019, not completing the update steps will cause Branch's Android SDK (and various other cross-platform SDKs, e.g. Unity) to stop collecting Android AID which we use to ensure accurate deep linking and attribution.

If you are running Google Play Services versions below 17, no update is necessary.

Configure Branch

1364 1364

Install Branch

NuGet

🚧

Google Advertising Identifier (GAID)

Branch Xamarin SDK 8.0.0+ requires the Xamarin.GooglePlayServices.AdsIdentifier NuGet package to obtain the advertising id.

Note that version 117.0.1.5 does not work properly on Visual Studio for Mac 2019, use 117.0.1.3 instead.

The Branch Xamarin SDK is available as a NuGet package. The Branch NuGet package must be added to each of the Xamarin projects that will use Branch methods.

To add the Branch NuGet package to a project:

  1. Right-click on each project and select Add > Add NuGet Packages
  2. Find the Branch-Xamarin-Linking-SDK package and add it to the project
  3. Optional: Find the Xamarin.GooglePlayServices.AdsIdentifier package and add it to the Android project.

Configure App

Ensure that the Android project is not using the Shared Mono Runtime

  1. Right-click on the Android project and select: Options
  2. Select: Android Build
  3. On the General tab, un-check: Use Shared Mono Runtime

Add app capabilities in the app's Manifest file

In the Required permissions section of AndroidManifest.xml, configure the following permissions:

  • AccessNetworkState
  • Internet

Additional reading on the Android manifest:

Add the app's Branch key to the Strings.xml file

Add the Branch key to the Android project's Resources/values/Strings.xml file. This file contains values that can be accessed by the app's Application class.

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">TestXamarinFormsApp</string>
  <string name="branch_key">key_live_liAnF8k7gZUEZv76Rt9a4bffAzlC5zVW</string>
</resources>

Initialize Branch

*Create the project's Application.cs* class

  1. Right-click on the .Droid project and select Add > New File...
  2. Select: General > Empty File
  3. Name the file: Application.cs
  4. Enter the following code (replace 'TestAndroidApp' with the actual name of the app):
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using BranchXamarinSDK;

namespace TestAndroidApp.Droid
{
    [Application(AllowBackup = true, Icon = "@mipmap/icon", Label = "@string/app_name")]
    [MetaData("io.branch.sdk.auto_link_disable", Value = "false")]
    [MetaData("io.branch.sdk.TestMode", Value = "true")]
    [MetaData("io.branch.sdk.BranchKey", Value = "@string/branch_key")]

    public class TestAndroidApp : Application
    {
        public TestAndroidApp(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();
            BranchAndroid.GetAutoInstance(this.ApplicationContext);
        }
    }
}
KeyValue
io.branch.sdk.TestModeSetting this parameter to true enables Debug Mode, which causes simple uninstall/reinstalls of the app to trigger install events. Be sure to disable this before deploying to production. Note that enabling Debug Mode on Android also forces the app to use the Branch Test key if this key has been added to the project. Apps running with a Test key will be unable to receive data from Branch links created with the Live key.
io.branch.sdk.BranchKeyThe app's Branch key. Both a Live key and a Test key can be added to the Strings.xml file. When Test Mode is enabled the app will automatically use the Test key, if one has been specified.

Create an activity to handle Branch events: BranchActivity

  1. Right-click on the .Droid project and select Add > New File...
  2. Select: Android > Activity
  3. Rename the file: BranchActivity.cs
  4. Enter the following code (replace 'TestAndroidApp' with the actual name of the app):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using BranchXamarinSDK;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace TestAndroidApp.Droid
{
    [Activity(Label = "BranchActivity")]
    public class BranchActivity : Activity

    {
        private string logString = "";

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            LogMessage("Branch initialization completed: ");

            Dictionary<string, object> data = JsonConvert.DeserializeObject<Dictionary<string, object>>(Intent.GetStringExtra("BranchData"));
            foreach (var key in data.Keys)
            {
                LogMessage(key + " : " + data[key].ToString());
            }
        }

        #region Utils

        void LogMessage(string message)
        {
            Console.WriteLine(message);
            logString += DateTime.Now.ToLongTimeString() + "> " + message + "\n";
        }

        #endregion
    }
}

Create an activity to handle Branch errors: BranchErrorActivity

  1. Right-click on the .Droid project and select Add > New File...
  2. Select: Android > Activity
  3. Rename the file: BranchErrorActivity.cs
  4. Enter the following code (replace 'TestAndroidApp' with the actual name of the app):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace TestAndroidApp.Droid
{
    [Activity(Label = "BranchErrorActivity")]
    public class BranchErrorActivity : Activity
    {
        private string logString = "";

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            LogMessage("Branch initialization failed");
            LogMessage("Error code: " + Intent.Extras.GetInt("ErrorCode").ToString());
            LogMessage(Intent.Extras.GetString("ErrorMessage"));
        }

        #region Utils

        void LogMessage(string message)
        {
            Console.WriteLine(message);
            logString += DateTime.Now.ToLongTimeString() + "> " + message + "\n";
        }

        #endregion
    }
}

Initialize Branch and configure Branch session management

Branch must be initialized in the OnCreate method of either the Application class or the first Activity launched by the app. The OnNewIntent method must be added to retrieve the latest link identifier when the app becomes active due to a Branch link click.

If initialization is successful, the InitSessionComplete method will be invoked. If initialization is unsuccessful, the SessionRequestError method will be invoked. Deep link routing logic should be located in the InitSessionComplete method.

In the code example below the following Branch initialization and session management steps have been added to MainActivity.cs:

  • An Activity to respond to the app's URI Scheme
  • An Activity is launched in singleTask mode
  • Override the OnCreate method and initialize the Branch SDK
  • Override the OnNewIntent method
  • Add an InitSessionComplete method for processing Branch link information (this is where deep link routing code should be located)
  • Add a SessionRequestError method to handle situations where Branch fails to initialize
using Android.App;
using Android.Widget;
using Android.OS;
using BranchXamarinSDK;
using System;
using System.Collections.Generic;
using Android.Content;
using Newtonsoft.Json;

namespace TestAndroidApp.Droid
{
    [Activity(Label = "TestAndroidApp", MainLauncher = true, Icon = "@mipmap/icon", LaunchMode = Android.Content.PM.LaunchMode.SingleTask)]

    [IntentFilter(new[] { "android.intent.action.VIEW" },
    Categories = new[] { "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE" },
    DataScheme = "testandroidapp",
    DataHost = "open")]

    [IntentFilter(new[] { "android.intent.action.VIEW" },
    Categories = new[] { "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE" },
    DataScheme = "https",
    DataHost = "testandroidapp.app.link")]

    [IntentFilter(new[] { "android.intent.action.VIEW" },
    Categories = new[] { "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE" },
    DataScheme = "https",
    DataHost = "testandroidapp-alternate.app.link")]

    public class MainActivity : Activity, IBranchSessionInterface
    {

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            BranchAndroid.Init(this, Resources.GetString(Resource.String.branch_key), this);
        }

        // Ensure we get the updated link identifier when the app becomes active
        // due to a Branch link click after having been in the background
        protected override void OnNewIntent(Intent intent)
        {
            this.Intent = intent;
        }

        public void InitSessionComplete(Dictionary<string, object> data)
        {
            //Handle custom logic based on deep link data in InitSessionComplete

            //View all the link data in the console
            Console.WriteLine("My Link Data: " + JsonConvert.SerializeObject(data));

            //Preferred method: use BranchActivity created previously to handle the link data
            //Will need to update BranchActivity with desired custom logic, to open the correct page in the app
            var intent = new Intent(this, typeof(BranchActivity));
            intent.PutExtra("BranchData", JsonConvert.SerializeObject(data));

            StartActivity(intent);var intent = new Intent
        }

        public void SessionRequestError(BranchError error)
        {
            Console.WriteLine("Branch session initialization error: " + error.ErrorCode);
            Console.WriteLine(error.ErrorMessage);

            var intent = new Intent(this, typeof(BranchErrorActivity));
            intent.PutExtra("ErrorCode", error.ErrorCode);
            intent.PutExtra("ErrorMessage", error.ErrorMessage);

            StartActivity(intent);
        }
    }
}

Configure Branch with Xamarin Forms

Create a class for Branch session handling

Branch initializes asynchronously, with Branch link parameters being returned following a network call to Branch. If initialization is successful, the InitSessionComplete method will be invoked. If initialization is unsuccessful, the SessionRequestError method will be invoked. Deep link routing logic should be located in the InitSessionComplete method.

  1. Right-click on the C# project and select Add > New File...
  2. Select: General > Empty Class
  3. Rename the file: TestXamarinFormsApp.cs
  4. Enter the following code (replacing 'TestXamarinFormsApp' with the actual name of the app):
using BranchXamarinSDK;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;

namespace TestXamarinFormsApp
{
    public class TestXamarinFormsApp : Application, IBranchSessionInterface
    {

        public TestXamarinFormsApp()
        {
        }

        #region IBranchSessionInterface implementation

        public void InitSessionComplete(Dictionary<string, object> data)
        {
        }

        public void CloseSessionComplete()
        {
        }

        public void SessionRequestError(BranchError error)
        {
        }

        #endregion
    }
}

Create a class for handling link data

Branch stores link data in an object referred to as the Branch Universal Object, or BUO.

  1. Right-click on the C# project and select Add > New File...
  2. Select: General > Empty Class
  3. Rename the file: TestXamarinFormsAppBUO.cs
  4. Enter the following code (replace 'TestXamarinFormsApp' with the actual name of the app):
using BranchXamarinSDK;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;

namespace TestXamarinFormsApp
{
    public class TestXamarinFormsAppBUO : Application, IBranchBUOSessionInterface
    {

        public TestXamarinFormsAppBUO()
        {
        }

        #region IBranchBUOSessionInterface implementation

        public void InitSessionComplete(BranchUniversalObject buo, BranchLinkProperties blp)
        {
        }

        public void SessionRequestError(BranchError error)
        {
        }

        #endregion
    }
}

Ensure that the Android project is not using the Shared Mono Runtime

  1. Right-click on the Android project and select: Options
  2. Select: Android Build
  3. On the General tab, un-check: Use Shared Mono Runtime

Add app capabilities in the AndroidManifest.xml file

In the Required permissions section of AndroidManifest.xml, configure the following permissions:

  • AccessNetworkState
  • Internet

Additional reading on the Android manifest

Add the app's Branch key to the Strings.xml file

Create a Resources/values/Strings.xml file that can be accessed by the app's Application class for the Android project and add the Branch key to this file.

  1. In the Android project, browse to Resources/values
  2. Right-click on the values folder and select: Add > New File...
  3. Select: XML > Empty XML File
  4. Name the file: Strings
  5. Enter the following values:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">TestXamarinFormsApp</string>
    <string name="branch_key">key_live_liAnF8k7gZUEZv76Rt9a4bffAzlC5zVW</string>
</resources>

Configure the .Droid project's Application class

Within the .Droid project's Application class:

  • Set the Branch SDK's initialization parameters
  • Override the OnCreate() method to call BranchAndroid.GetAutoInstance

If an Appplication class does not already exist for the project, create one:

  1. Right-click on the .Droid project and select: Add > New File...
  2. Select: General > Empty Class
  3. Name the file: {app name} ('TestXamarinFormsApp', for example)

The file should have the following contents:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using BranchXamarinSDK;

namespace TestXamarinFormsApp.Droid
{

    [Application (AllowBackup = true, Icon = "@drawable/icon", Label = "@string/app_name")]
    [MetaData("io.branch.sdk.auto_link_disable", Value = "false")]
    [MetaData("io.branch.sdk.TestMode", Value = "true")]
    [MetaData("io.branch.sdk.BranchKey", Value = "@string/branch_key")]

    public class App : Application
    {
        public App(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();
            BranchAndroid.GetAutoInstance(this.ApplicationContext);
        }
    }
}
KeyValue
io.branch.sdk.TestModeSetting this parameter to true enables Debug Mode, which causes simple uninstall/reinstalls of the app to trigger install events. Be sure to disable this before deploying to production. Note that enabling Debug Mode on Android also forces the app to use the Branch Test key if this key has been added to the project. Apps running with a Test key will be unable to receive data from Branch links created with the Live key.
io.branch.sdk.BranchKeyThe app's Branch key. Both a Live key and a Test key can be added to the Strings.xml file. When Test Mode is enabled the app will automatically use the Test key, if one has been specified.

Initialize Branch

Branch must be initialized in the OnCreate method of either the Application class or the first Activity launched by the app. The OnNewIntent method must be added to retrieve the latest link identifier when the app becomes active due to a Branch link click.

In the code example below the following Branch initialization and session management steps have been added to MainActivity.cs:

  • Register an Activity to respond to the app's URI Scheme
  • Ensure the Activity is launched in singleTask mode
  • Override the OnCreate method and initialize the Branch SDK
  • Override the OnNewIntent method
using System;

using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

using BranchXamarinSDK;
using TestXamarinFormsApp;

namespace TestXamarinFormsApp.Droid
{
    [Activity(Label = "TestXamarinFormsApp.Droid", LaunchMode = LaunchMode.SingleTask, Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

    [IntentFilter(new[] { "android.intent.action.VIEW" },
        Categories = new[] { "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE" },
        DataScheme = "testxamarinformsapp",
        DataHost = "open")]

    [IntentFilter(new[] { "android.intent.action.VIEW" },
        Categories = new[] { "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE" },
        DataScheme = "https",
        DataHost = "testxamarinformsapp.app.link")]

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

            TestXamarinFormsAppBUO linkData = new TestXamarinFormsAppBUO();
            BranchAndroid.Init(this, GetString(Resource.String.branch_key), linkData);
            LoadApplication(linkData);
        }

        protected override void OnNewIntent(Intent intent)
        {
            this.Intent = intent;
        }
    }
}

Implement Features

Create content reference

BranchUniversalObject universalObject = new BranchUniversalObject();
universalObject.canonicalIdentifier = "id12345";
universalObject.title = "id12345 title";
universalObject.contentDescription = "My awesome piece of content!";
universalObject.imageUrl = "https://s3-us-west-1.amazonaws.com/branchhost/mosaic_og.png";
universalObject.metadata.AddCustomMetadata("foo", "bar");

Create deep link

BranchLinkProperties linkProperties = new BranchLinkProperties();
linkProperties.tags.Add("tag1");
linkProperties.tags.Add("tag2");
linkProperties.feature = "sharing";
linkProperties.channel = "facebook";
linkProperties.controlParams.Add("$desktop_url", "http://example.com");

Branch.GetInstance().GetShortURL(callback,
                   universalObject,
                   linkProperties);

Share deep link

Branch.GetInstance().ShareLink (callback,
           universalObject,
           linkProperties,
           message)

Read deep link

  • Retrieve Branch data from a deep link
  • Best practice to receive data from the listener (to prevent a race condition)
  • Returns deep link properties
// latest
Dictionary<string, object> sessionParams = Branch.GetInstance().GetLatestReferringParams();

// first
Dictionary<string, object> installParams = Branch.GetInstance().GetFirstReferringParams();

Track users

  • Sets the identity of a user (ID, UUID, etc) for events, deep links, and referrals
  • Validate with the Branch Dashboard
Branch branch = Branch.GetInstance ();
branch.SetIdentity("the user id", this);  // Where this implements IBranchIdentityInterface
branch.Logout(this); // Where this implements IBranchIdentityInterface

Track commerce events

  • Commerce events describe events that relate to a customer interacting with your products and converting by purchasing. These are events like adding payment information, purchasing, viewing products, etc. If you have enabled Branch Universal Ads, these events will automatically map to certain Ad Partners. Start by creating a Branch Universal Object for each product that is associated with the event you're tracking.
  • From there, add the Branch Universal Object to the tracked event, and use the right predefined constant. For example, the code snippet below is to track when a user adds to cart, but simply replace that constant with another constant to track a different event.
  • A note on currency and exchange rates:
    If you track commerce events without a currency, we assume they are USD. If you track commerce events with a currency other than USD, we will convert the revenue specified to USD, using a recent exchange rate.
  • This allows you to easily visualize revenue on the Dashboard, across many countries and currencies, because all units are USD. The exchange rate is pulled from openexchangerates.org regularly, and is generally within an hour of the realtime exchange rate. If you view raw Branch events via either Webhooks or Exports, you can see the exchange rate used.
  • Validate with the Branch Dashboard
BranchUniversalObject universalObject = new BranchUniversalObject();
universalObject.canonicalIdentifier = "id12345";
universalObject.canonicalUrl = "https://branch.io/item/id12345";
universalObject.title = "Item 12345";
universalObject.contentDescription = "My awesome piece of content!";
universalObject.imageUrl = "https://s3-us-west-1.amazonaws.com/branchhost/mosaic_og.png";

universalObject.metadata.price = (float)23.20;
universalObject.metadata.quantity = 1;
universalObject.metadata.sku = "1994329302";
universalObject.metadata.productName = "my_product_name1";
universalObject.metadata.productBrand = "my_product_brand1";
universalObject.metadata.productCategory =                      BranchProductCategory.APPAREL_AND_ACCESSORIES;
universalObject.metadata.productVariant = "XL";
universalObject.metadata.condition = BranchCondition.NEW;
universalObject.metadata.AddCustomMetadata("foo", "bar");

BranchEvent branchCommerceEvent = new BranchEvent(BranchEventType.PURCHASE);
branchCommerceEvent.SetAlias("new_user_purchase");
branchCommerceEvent.AddContentItem(universalObject); 
branchCommerceEvent.SetRevenue((float)1.5);
branchCommerceEvent.SetShipping((float)10.5);
branchCommerceEvent.SetCurrency(BranchCurrencyType.USD);
branchCommerceEvent.SetTax((float)12.3);

Branch.GetInstance().SendEvent(branchCommerceEvent);

Track content events

  • Content events are events that occur when a user engages with your in-app content. For example, if you have in-app articles, you would want to track events related to when users search, view content, rate the content, and share. This can apply to a wide variety of in-app content, such as blog posts, music, video, pictures, and e-commerce catalogue items.
  • Validate with the Branch Dashboard
BranchEvent branchContentEvent = new BranchEvent(BranchEventType.SEARCH);
branchContentEvent.SetAlias("my_custom_alias");
branchContentEvent.SetDescription("Product Search");
branchContentEvent.SetSearchQuery("user search query terms for product xyz");
branchContentEvent.AddCustomData("content_event_property_key1", "content_event_property_val1");

Branch.GetInstance().SendEvent(branchContentEvent);

Track lifecycle events

  • Lifecycle events can be described as events a user takes in your app to continue progressing. These events can apply to game apps, as well as non game apps, for when a user completes a user profile, registration or tutorial.
  • Validate with the Branch Dashboard
BranchEvent branchLifecycleEvent = new BranchEvent(BranchEventType.COMPLETE_REGISTRATION);
branchLifecycleEvent.SetAlias("registration_flow_xyz"); branchLifecycleEvent.SetDescription("Existing User Registration");
branchLifecycleEvent.AddCustomData("lifeycle_event_property_key1", "lifecycle_event_property_val1");

Branch.GetInstance().SendEvent(branchLifecycleEvent);

Track custom events

  • If you want to track an event that isn't a predefined event, simply do the following:
  • We strongly recommend using custom event names that contain no more than 40 characters, contain only letters, numbers, hyphens, spaces and underscores, and do not start with a hyphen. Facebook will not accept events that violate these rules, and if you enable the Facebook integration, Branch may sanitize your event names to pass validation.
  • Validate with the Branch Dashboard
BranchEvent branchCustomEvent = new BranchEvent("custom_event");
 branchCustomEvent.SetAlias("custom_event_alias");
 branchCustomEvent.SetDescription("Custom Event Description");
 branchCustomEvent.AddCustomData("custom_event_property_key1", "custom_event_property_val1");
branchCustomEvent.AddCustomData("custom_event_property_key2", "custom_event_property_val2");

Branch.GetInstance().SendEvent(branchCustomEvent);

Sample Testing Apps

There are four fully-functional demo apps included in this repository: a Xamarin Native and Xamarin Forms apps for both iOS and Android platforms. Use these apps as reference models for integrating the Branch SDK.

  • Testbed-Xamarin (Native apps)
  • Testbed-XamarinForms (Forms apps)

Troubleshoot Issues

Test deep link Android

  • Create a deep link from the Branch Marketing Dashboard
  • Delete your app from the device
  • Compile your app with Android Studio
  • Paste deep link in Google Hangouts
  • Click on the deep link to open your app

Android app fails to build with linking errors

The Newtonsoft JSON NuGet package is automatically added to a project when the Branch Xamarin SDK NuGet package is added. There is a known issue with this package that results in linking errors when building a project.

error XA0009: Error while loading assembly: /Users/david/Projects/TestXamarinFormsApp/Droid/obj/Debug/android/assets/mscorlib.dll

To resolve this issue with the Newtonsoft JSON NuGet package:

  1. Right-click on the project and select Options
  2. Go to Android Build and select the Linker tab
  3. Select: Release
  4. Go to the Ignore assemblies box
  5. Add: System.Core
  6. Rebuild the app

Recommended Next Steps