Filters

Android Advanced Features

Create Content Reference

val buo = BranchUniversalObject()
        .setCanonicalIdentifier("content/12345")
        .setTitle("My Content Title")
        .setContentDescription("My Content Description")
        .setContentImageUrl("https://lorempixel.com/400/400")
        .setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC)
        .setLocalIndexMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC)
        .setContentMetadata(ContentMetadata().addCustomMetadata("key1", "value1"))
BranchUniversalObject buo = new BranchUniversalObject()
        .setCanonicalIdentifier("content/12345")
        .setTitle("My Content Title")
        .setContentDescription("My Content Description")
        .setContentImageUrl("https://lorempixel.com/400/400")
        .setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC)
        .setLocalIndexMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC)
        .setContentMetadata(new ContentMetadata().addCustomMetadata("key1", "value1"));

Create Deep Link

val lp = LinkProperties()
        .setChannel("facebook")
        .setFeature("sharing")
        .setCampaign("content 123 launch")
        .setStage("new user")
        .addControlParameter("$desktop_url", "http://example.com/home")
        .addControlParameter("custom", "data")
        .addControlParameter("custom_random", Long.toString(Calendar.getInstance().getTimeInMillis()))

    buo.generateShortUrl(this, lp, BranchLinkCreateListener { url?, error? ->
        if (error == null) {
            Log.i("BRANCH SDK", "got my Branch link to share: " + url)
        }
    })
LinkProperties lp = new LinkProperties()
        .setChannel("facebook")
        .setFeature("sharing")
        .setCampaign("content 123 launch")
        .setStage("new user")
        .addControlParameter("$desktop_url", "https://example.com/home")
        .addControlParameter("custom", "data")
        .addControlParameter("custom_random", Long.toString(Calendar.getInstance().getTimeInMillis()));

    buo.generateShortUrl(this, lp, new Branch.BranchLinkCreateListener() {
        @Override
        public void onLinkCreate(String url, BranchError error) {
            if (error == null) {
                Log.i("BRANCH SDK", "got my Branch link to share: " + url);
            }
        }
    });

Share Deep Link

var lp = LinkProperties()
        .setChannel("facebook")
        .setFeature("sharing")
        .setCampaign("content 123 launch")
        .setStage("new user")
        .addControlParameter("$desktop_url", "http://example.com/home")
        .addControlParameter("custom", "data")
        .addControlParameter("custom_random", Long.toString(Calendar.getInstance().getTimeInMillis()))

    val ss = ShareSheetStyle(this@MainActivity, "Check this out!", "This stuff is awesome: ")
        .setCopyUrlStyle(resources.getDrawable(this, android.R.drawable.ic_menu_send), "Copy", "Added to clipboard")
        .setMoreOptionStyle(resources.getDrawable(this, android.R.drawable.ic_menu_search), "Show more")
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.FACEBOOK)
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL)
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.MESSAGE)
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.HANGOUT)
        .setAsFullWidthStyle(true)
        .setSharingTitle("Share With")

    buo.showShareSheet(this, lp, ss, object : Branch.BranchLinkShareListener {
        override fun onShareLinkDialogLaunched() {}
        override fun onShareLinkDialogDismissed() {}
        override fun onLinkShareResponse(sharedLink: String?, sharedChannel: String?, error: BranchError?) {}
        override fun onChannelSelected(channelName: String) {}
    })
LinkProperties lp = new LinkProperties()
        .setChannel("facebook")
        .setFeature("sharing")
        .setCampaign("content 123 launch")
        .setStage("new user")
        .addControlParameter("$desktop_url", "https://example.com/home")
        .addControlParameter("custom", "data")
        .addControlParameter("custom_random", Long.toString(Calendar.getInstance().getTimeInMillis()));

    ShareSheetStyle ss = new ShareSheetStyle(MainActivity.this, "Check this out!", "This stuff is awesome: ")
        .setCopyUrlStyle(ContextCompat.getDrawable(this, android.R.drawable.ic_menu_send), "Copy", "Added to clipboard")
        .setMoreOptionStyle(ContextCompat.getDrawable(this, android.R.drawable.ic_menu_search), "Show more")
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.FACEBOOK)
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL)
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.MESSAGE)
        .addPreferredSharingOption(SharingHelper.SHARE_WITH.HANGOUT)
        .setAsFullWidthStyle(true)
        .setSharingTitle("Share With");

    buo.showShareSheet(this, lp,  ss,  new Branch.BranchLinkShareListener() {
        @Override
        public void onShareLinkDialogLaunched() {
        }
        @Override
        public void onShareLinkDialogDismissed() {
        }
        @Override
        public void onLinkShareResponse(String sharedLink, String sharedChannel, BranchError error) {
        }
        @Override
        public void onChannelSelected(String channelName) {
        }
    });

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
// listener (within Main Activity's onStart)
    Branch.sessionBuilder(this).withCallback(object : BranchReferralInitListener {
        override fun onInitFinished(referringParams: JSONObject?, error: BranchError?) {
            if (error == null) {
                Log.i("BRANCH SDK", referringParams.toString())
            } else {
                Log.e("BRANCH SDK", error.message)
            }
        }
    }).withData(this.intent.data).init()

    // latest
    val sessionParams = Branch.getInstance().latestReferringParams

    // first
    val installParams = Branch.getInstance().firstReferringParams
// listener (within Main Activity's onStart)
Branch.sessionBuilder(this).withCallback(new Branch.BranchReferralInitListener() {
	@Override
	public void onInitFinished(JSONObject referringParams, BranchError error) {
		if (error == null) {
			Log.i("BRANCH SDK", referringParams.toString());
		} else {
			Log.i("BRANCH SDK", error.getMessage());
		}
	}
}).withData(this.getIntent().getData()).init();

// latest
JSONObject sessionParams = Branch.getInstance().getLatestReferringParams();

// first
JSONObject installParams = Branch.getInstance().getFirstReferringParams();

Create QR Code

  • Create a BranchQRCode object and set the properties
  • Create a BranchUniversalObject and BranchLinkProperties
  • Use getQRCodeAsImage() or getQRCodeAsData() to get your QR code
val qrCode = BranchQRCode()
                .setCodeColor("#a4c639")
                .setBackgroundColor(Color.WHITE)
                .setMargin(1)
                .setWidth(512)
                .setImageFormat(BranchQRCode.BranchImageFormat.JPEG)
                .setCenterLogo("https://cdn.branch.io/branch-assets/1598575682753-og_image.png")

val buo = BranchUniversalObject()
                .setCanonicalIdentifier("content/12345")
                .setTitle("My Content Title")
                .setContentDescription("My Content Description")
                .setContentImageUrl("https://lorempixel.com/400/400")

val lp = LinkProperties()
                .setChannel("facebook")
                .setFeature("sharing")
                .setCampaign("content 123 launch")
                .setStage("new user")

qrCode.getQRCodeAsImage(this@MainActivity, buo, lp, object : BranchQRCodeImageHandler<Any?> {
                        override fun onSuccess(qrCodeImage: Bitmap) {
                            //Do something with your QR code here.
                        }

                        override fun onFailure(e: Exception) {
                            Log.d("Failed to get QR code", e.toString())
                        }
                    })
BranchQRCode qrCode = new BranchQRCode() //All QR code settings are optional
                        .setCodeColor("#a4c639")
                        .setBackgroundColor(Color.WHITE)
                        .setMargin(1)
                        .setWidth(512)
                        .setImageFormat(BranchQRCode.BranchImageFormat.PNG)
                        .setCenterLogo("https://cdn.branch.io/branch-assets/1598575682753-og_image.png");

BranchUniversalObject buo = new BranchUniversalObject()
                        .setCanonicalIdentifier("content/12345")
                        .setTitle("My QR Code");

LinkProperties lp = new LinkProperties()
                        .setChannel("facebook")
                        .setFeature("qrCode")
                        .setCampaign("content 123 launch");

qrCode.getQRCodeAsImage(MainActivity.this, buo, lp, new BranchQRCode.BranchQRCodeImageHandler() {
                        @Override
                        public void onSuccess(Bitmap qrCodeImage) {
                            //Do something with the QR code here.
                        }

                        @Override
                        public void onFailure(Exception e) {
                            Log.d("Failed to get QR code", String.valueOf(e));
                        }
                    });

Navigate to Content

  • Do stuff with the Branch deep link data
// Listener (within Main Activity's onStart)
Branch.sessionBuilder(this).withCallback(object : BranchReferralInitListener {
    override fun onInitFinished(referringParams: JSONObject?, error: BranchError?) {
        if (error == null) {
            // Option 1: log data
            Log.i("BRANCH SDK", referringParams.toString())

            // Option 2: save data to be used later
            val preferences =  getSharedPreferences("MyPreferences", Context.MODE_PRIVATE)
            preferences.edit().putString("branchData", referringParams.toString()).apply();

            // Option 3: navigate to page
            val intent = Intent(this@MainActivity, MainActivity2::class.java)
            intent.putExtra("branchData", referringParams.toString())
            startActivity(intent)

            // Option 4: display data
            Toast.makeText(this@MainActivity, referringParams.toString(), Toast.LENGTH_SHORT).show()
        } else {
            Log.e("BRANCH SDK", error.message)
        }
    }
}).withData(this.intent.data).init()
// Listener (within Main Activity's onStart)
Branch.sessionBuilder(this).withCallback(new Branch.BranchReferralInitListener() {
    @Override
    public void onInitFinished(JSONObject referringParams, BranchError error) {
        if (error == null) {

          // Option 1: log data
          Log.i("BRANCH SDK", referringParams.toString());

          // Option 2: save data to be used later
          SharedPreferences preferences = MainActivity.this.getSharedPreferences("MyPreferences", Context.MODE_PRIVATE);
          preferences.edit().putString("branchData", referringParams.toString()).apply();

          // Option 3: navigate to page
          Intent intent = new Intent(MainActivity.this, OtherActivity.class);
          startActivity(intent);

          // Option 4: display data
          Toast.makeText(MainActivity.this, referringParams.toString(), Toast.LENGTH_LONG).show();

        } else {
            Log.i("BRANCH SDK", error.getMessage());
        }
    }
}).withData(this.getIntent().getData()).init();

Track Content

BranchEvent(BRANCH_STANDARD_EVENT.VIEW_ITEM).addContentItems(buo).logEvent(context)
new BranchEvent(BRANCH_STANDARD_EVENT.VIEW_ITEM).addContentItems(buo).logEvent(context);

Track Users

🚧

Sending PII

Be sure to not send any PII through this method. For additional details, please view our guide on Best Practices to Avoid Sending PII to Branch

  • Sets the identity of a user (ID, UUID, etc) for events, deep links, and referrals
  • 127 character max for user id
  • Validate with the Branch Dashboard
// login
    Branch.getInstance().setIdentity("your_user_id");

// logout
Branch.getInstance().logout();
// login
Branch.getInstance().setIdentity("your_user_id");

// logout
Branch.getInstance().logout();

Track Events

  • All events related to a customer purchasing are bucketed into a "Commerce" class of data items
  • All events related to users interacting with your in-app content are bucketed to a "Content" class of data items.
  • All events related to users progressing in your app are bucketed to a "Lifecycle" class of data items.
  • To track custom events - not found in the table below - please see Track Custom Events
  • Validate with the Branch Dashboard

Use the table below to quickly find the event you want to track.

Event NameEvent CategoryAndroid
Add To CartCommerce EventBRANCH_STANDARD_EVENT.ADD_TO_CART
Add To WishlistCommerce EventBRANCH_STANDARD_EVENT.ADD_TO_WISHLIST
View CartCommerce EventBRANCH_STANDARD_EVENT.VIEW_CART
Initiate PurchaseCommerce EventBRANCH_STANDARD_EVENT.INITIATE_PURCHASE
Add Payment InfoCommerce EventBRANCH_STANDARD_EVENT.ADD_PAYMENT_INFO
PurchaseCommerce EventBRANCH_STANDARD_EVENT.PURCHASE
Spend CreditsCommerce EventBRANCH_STANDARD_EVENT.SPEND_CREDITS
SearchContent EventBRANCH_STANDARD_EVENT.SEARCH
View ItemContent EventBRANCH_STANDARD_EVENT.VIEW_ITEM
View ItemsContent EventBRANCH_STANDARD_EVENT.VIEW_ITEMS
RateContent EventBRANCH_STANDARD_EVENT.RATE
ShareContent EventBRANCH_STANDARD_EVENT.SHARE
Complete RegistrationLifecycle EventBRANCH_STANDARD_EVENT.COMPLETE_REGISTRATION
Complete TutorialLifecycle EventBRANCH_STANDARD_EVENT.COMPLETE_TUTORIAL
Achieve LevelLifecycle EventBRANCH_STANDARD_EVENT.ACHIEVE_LEVEL
Unlock AchievementLifecycle EventBRANCH_STANDARD_EVENT.UNLOCK_ACHIEVEMENT

Handle Push Notifications

  • Deep link to content from push notifications just by adding a Branch link to your result intent
val resultIntent = Intent(this, TargetClass::class.java)
resultIntent.putExtra("branch", "http://xxxx.app.link/testlink")
resultIntent.putExtra("branch_force_new_session", true)
val resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT)
Intent resultIntent = new Intent(this, TargetActivity.class);
resultIntent.putExtra("branch","https://xxxx.app.link/testlink");
resultIntent.putExtra("branch_force_new_session",true);
PendingIntent resultPendingIntent =  PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
  • To handle situations where TargetActivity is in the foreground when push notification is clicked, don't forget to call sessionBuilder()...reInit() from onNewIntent inside TargetActivity:
override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        this.intent = intent
        // Branch reinit (in case Activity is already visible when Branch link is clicked)
        // will re-initialize only if "branch_force_new_session=true" intent extra is set
        Branch.sessionBuilder(this).withCallback(branchListener).reInit()
@Override
protected void onNewIntent(Intent intent) {
   super.onNewIntent(intent);
    setIntent(intent);
    // if activity is in foreground (or in backstack but partially visible) launching the same
    // activity will skip onStart, handle this case with reInitSession
    if (intent != null &&
          intent.hasExtra("branch_force_new_session") && 
          intent.getBooleanExtra("branch_force_new_session")) {
          Branch.sessionBuilder(this).withCallback(branchReferralInitListener).reInit();
    }
}

❗️

Handling a new deep link via sessionBuilder()....reInit()

Handling a new deep link via sessionBuilder()....reInit() will clear the current session data, if there is any, and a new referred "open" will be attributed.

Handle Links in Your Own App

  • Allows you to deep link into your own app from your app itself by launching a Chrome intent
val intent = Intent(this, ActivityToLaunch::class.java)
intent.putExtra("branch", "http://xxxx.app.link/testlink")
intent.putExtra("branch_force_new_session", true)
startActivity(intent)
Intent intent = new Intent(this, ActivityToLaunch.class);
intent.putExtra("branch","https://xxxx.app.link/testlink");
intent.putExtra("branch_force_new_session",true);
startActivity(intent);

❗️

Handling a new deep link

Handling a new deep link in your app will clear the current session data and a new referred "open" will be attributed.

❗️

Linking to the currently open activity

Similarly to handling push notifications, linking to the currently open activity or an activity that's in the backstack and partially visible, must be handled via sessionBuilder()....reInit().

Enable 100% Matching

  • Uses Chrome Tabs to increase attribute matching success.
  • Add implementation 'androidx.browser:browser:1.5.0' to your build.gradle.
  • If you need the custom tabs library but do not wish to enable 100% matching you can call Branch.enableCookieBasedMatching(null) prior to session initialization.

Delay Session Initialization

Sometimes, users may need to delay session initialization, for example to make an async call to retrieve some data that needs to be passed to Branch as request metadata.

In this case, you may run into an error "SDK already initialized", which happens due to Branch self-initializing the session when Activity enters RESUMED state. To avoid that, you can disable auto-session-initialization manually and initialize the session yourself after the async call finishes.

Note: expectDelayedSessionInitialization() must be called before establishing the Branch singleton within your application class onCreate().

package com.eneff.branch.example.android

import android.app.Application
import io.branch.referral.Branch

class CustomApplicationClass : Application() {
    override fun onCreate() {
        super.onCreate()

        // Delay Session Initialization 
        Branch.expectDelayedSessionInitialization()

       // Branch object initialization
        Branch.getAutoInstance(this)
    }
}
package com.eneff.branch.example.android;

import android.app.Application;
import io.branch.referral.Branch;

public class CustomApplicationClass extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // Delay Session Initialization 
        Branch.expectDelayedSessionInitialization();

        // Branch object initialization
        Branch.getAutoInstance(this);
    }
}

Enable / Disable User Tracking

If you need to comply with a user's request to not be tracked for GDPR purposes, or otherwise determine that a user should not be tracked, utilize this field to prevent Branch from sending network requests. This setting can also be enabled across all users for a particular link, or across your Branch links.

Branch.getInstance().disableTracking(true)
Branch.getInstance().disableTracking(true);

You can choose to call this throughout the lifecycle of the app. Once called, network requests will not be sent from the SDKs. Link generation will continue to work, but will not contain identifying information about the user. In addition, deep linking will continue to work, but will not track analytics for the user.

Set initialization metadata

🚧

Data Integration Only

If you are using a 3rd Party Data Integration Partner that requires setting certain identifiers before initializing the Branch SDK, you should add this code snippet:

//Before you initialize the session.
Branch.getInstance().setRequestMetadata("{ANALYTICS_ID}", […]);

Replace {ANALYTICS_ID} with your Data Integration Partner's key.

Control How Branch Handles Network Requests

By default, Branch Android SDK uses Java's javax.net.ssl.HttpsURLConnection for network requests. There are known issues with that interface and typically applications use third party networking libraries, such as OkHttp, to customize their networking. Branch SDK provides an interface, BranchRemoteInterface, to apply your networking customization to how Branch handles network requests. Use the below API to set your implementation of BranchRemoteInterface to handle Branch requests.

setBranchRemoteInterface(remoteInterface: BranchRemoteInterface)
setBranchRemoteInterface(@NonNull BranchRemoteInterface remoteInterface)

Below is an example of an implementation of BranchRemoteInterface using OkHttp.

public class OkhttpBranchNetworkInterface extends BranchRemoteInterface {
  private OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(3, TimeUnit.SECONDS).writeTimeout(3, TimeUnit.SECONDS).connectTimeout(3, TimeUnit.SECONDS).build();

  @Override
  public BranchResponse doRestfulGet(String url) throws BranchRemoteException {
    Request request = new Request.Builder().url(url).build();

    return handleNetworkRequest(request);
  }

  @Override
  public BranchResponse doRestfulPost(String url, JSONObject payload) throws BranchRemoteException {
    Request request = new Request.Builder().url(url).post(RequestBody.create(MediaType.parse("application/json"), payload.toString())).build();

    return handleNetworkRequest(request);
  }

  private BranchResponse handleNetworkRequest(Request request) throws BranchRemoteException {
    try {
      Response response = okHttpClient.newCall(request).execute();
      ResponseBody rb = response.body();
      if (rb != null) throw new BranchRemoteException(BranchError.ERR_BRANCH_NO_CONNECTIVITY);
      return new BranchResponse(rb.string(), response.code());
    } catch(Exception exception) {
      if (exception instanceof SocketTimeoutException) {
        // add desired retry logic, then eventually throw BranchError.ERR_BRANCH_REQ_TIMED_OUT
        throw new BranchRemoteException(BranchError.ERR_BRANCH_REQ_TIMED_OUT);
      } else {
        // handle other failures as needed, throw BranchError.ERR_BRANCH_NO_CONNECTIVITY as a default
        throw new BranchRemoteException(BranchError.ERR_BRANCH_NO_CONNECTIVITY);
      }
    }
  }
}
public class OkhttpBranchNetworkInterface extends BranchRemoteInterface {
  private OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(3, TimeUnit.SECONDS).writeTimeout(3, TimeUnit.SECONDS).connectTimeout(3, TimeUnit.SECONDS).build();

  @Override
  public BranchResponse doRestfulGet(String url) throws BranchRemoteException {
    Request request = new Request.Builder().url(url).build();

    return handleNetworkRequest(request);
  }

  @Override
  public BranchResponse doRestfulPost(String url, JSONObject payload) throws BranchRemoteException {
    Request request = new Request.Builder().url(url).post(RequestBody.create(MediaType.parse("application/json"), payload.toString())).build();

    return handleNetworkRequest(request);
  }

  private BranchResponse handleNetworkRequest(Request request) throws BranchRemoteException {
    try {
      Response response = okHttpClient.newCall(request).execute();
      ResponseBody rb = response.body();
      if (rb != null) throw new BranchRemoteException(BranchError.ERR_BRANCH_NO_CONNECTIVITY);
      return new BranchResponse(rb.string(), response.code());
    } catch(Exception exception) {
      if (exception instanceof SocketTimeoutException) {
        // add desired retry logic, then eventually throw BranchError.ERR_BRANCH_REQ_TIMED_OUT
        throw new BranchRemoteException(BranchError.ERR_BRANCH_REQ_TIMED_OUT);
      } else {
        // handle other failures as needed, throw BranchError.ERR_BRANCH_NO_CONNECTIVITY as a default
        throw new BranchRemoteException(BranchError.ERR_BRANCH_NO_CONNECTIVITY);
      }
    }
  }
}

Set Hashed Information for Facebook Advanced Matching

You can pass additional hashed information to the SDK before init() for Facebook Advanced Matching.

Branch branch = Branch.getAutoInstance(getApplicationContext())
branch.addFacebookPartnerParameterWithName("em", "194b86d986ad041666822dad7602f1a7bac1d9e286273e86141666ffb4b1909b")
Branch branch = Branch.getAutoInstance(getApplicationContext());
branch.addFacebookPartnerParameterWithName("em", "194b86d986ad041666822dad7602f1a7bac1d9e286273e86141666ffb4b1909b");

Detect Screenshots

When one of your users takes a screenshot within your app, you have the option to surface a pop-up that encourages them to share the content directly instead. A Branch Deep Link is generated, which they can easily copy and share using the pop-up.

var lp = LinkProperties().setChannel(“facebook”).setFeature(“sharing”).setCampaign(“content 123 launch”).setStage(“new user”).addControlParameter("$desktop_url", "http://example.com/home").addControlParameter("custom", "data").addControlParameter("custom_random", Long.toString(Calendar.getInstance().getTimeInMillis()))

val ss = ShareSheetStyle(this@MainActivity, "Check this out!", "This stuff is awesome: ").setCopyUrlStyle(resources.getDrawable(this, android.R.drawable.ic_menu_send), "Copy", "Added to clipboard").setMoreOptionStyle(resources.getDrawable(this, android.R.drawable.ic_menu_search), "Show more").addPreferredSharingOption(SharingHelper.SHARE_WITH.FACEBOOK).addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL).addPreferredSharingOption(SharingHelper.SHARE_WITH.MESSAGE).addPreferredSharingOption(SharingHelper.SHARE_WITH.HANGOUT).setAsFullWidthStyle(true).setSharingTitle("Share With")

buo.showShareSheet(this, lp, ss, object : Branch.BranchLinkShareListener {

    override fun onShareLinkDialogLaunched() {}

    override fun onShareLinkDialogDismissed() {}

    override fun onLinkShareResponse(sharedLink: String?, sharedChannel: String?, error: BranchError?) {}

    override fun onChannelSelected(channelName: String) {}

})

Recommended Next Steps