Xamarin Android

GitHub tag (latest by date)GitHub tag (latest by date)

❗️

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

imageimage
imageimage

Install Branch

NuGet

🚧

Google 광고 식별자(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);
        }
    }
}
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);
        }
    }
}
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 (email, 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 Event는 사용자가 제품과 상호 작용하여 최종적으로 구매전환할 때까지 발생하는 일련의 행위들과 관련이 있습니다. 예를 들면 지불정보 추가, 구매 등이 있습니다. Branch Universal Ads(광고 어트리뷰션)를 활성화시킬 경우, 이러한 이벤트는 자동으로 특정 광고 파트너에 맵핑됩니다. 먼저 추적중인 이벤트와 연관된 각 제품에 해당되는 BranchUniversalLink를 생성하기 바랍니다.

  • 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 Event는 사용자가 앱 내 콘텐츠에 대해 관심을 가지고 상호작용하는 행위를 취했을 때 전송하는 이벤트입니다. 예를 들면, 기사를 다루고 있는 앱에서 사용자가 콘텐츠를 검색하고, 읽고, 평가하고, 공유할 수 있습니다. 이는 블로그 게시물, 음악, 동영상, 사진, 전자상거래 카탈로그 항목 등 다양한 앱내 콘텐츠에 적용할 수 있습니다.

  • 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 Event는 사용자의 여정을 심화하기 위해 사용자가 단계별로 발생시키는 일련의 이벤트로 볼 수 있습니다. 이러한 이벤트는 사용자가 회원가입 또는 튜토리얼을 완료할 때 적용될 수 있고 게임 앱과 기타 유형의 앱에도 적용할 수 있습니다.

  • 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

  • 사전 정의된 표준 이벤트가 아닌 임의로 정의한 이벤트를 추적하려면 아래 내용을 참고하시기 바랍니다.

  • Custom Event의 이벤트명은 문자, 숫자, 하이픈, 공백 및 밑줄만 포함한 40자 이하의 문자열을 사용할 것을 권장하고 하이픈으로 시작하지 않기 바랍니다. Facebook에서는 이러한 규칙을 위반하는 이벤트를 받아들이지 않을 것이고, Facebook 연동을 활성화하면, Branch에서 검증을 통해 유효하지 않는 이벤트를 수정할 수도 있습니다.

  • 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
이 페이지가 도움이 되었습니까?