筛选项

Android 高级功能

创建内容引用 (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"));

创建深度链接

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);
            }
        }
    });

分享深度链接

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([email protected], "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) {
        }
    });

读取深度链接

  • 从深度链接中提取 Branch 数据
  • 最佳做法是从 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([email protected], 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));
                        }
                    });

前往内容

  • 用 Branch 深度链接数据工作
// 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([email protected], MainActivity2::class.java)
                intent.putExtra(""branchData"", referringParams.toString())
                startActivity(intent)

                // option 4: display data
                Toast.makeText([email protected], 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();

追踪内容

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

追踪用户

🚧

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 用户 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();

追踪事件

  • 与客户购买有关的所有事件都会归类到数据项的 “Commerce” 类别中
  • 与用户与应用中内容交互相关的所有事件都会归类到数据项的 “Content” 类别中。
  • 与用户在应用中的进展相关的所有事件都会归类到数据项的 “Lifecycle” 类别中。
  • To track custom events - not found in the table below - please see Track Custom Events
  • Validate with the Branch Dashboard

使用下表快速找到您要追踪的事件。

Event 名称事件类别Android
添加到购物车Commerce EventBRANCH_STANDARD_EVENT.ADD_TO_CART
加到收藏夹Commerce EventBRANCH_STANDARD_EVENT.ADD_TO_WISHLIST
查看购物车Commerce EventBRANCH_STANDARD_EVENT.VIEW_CART
发起购买Commerce EventBRANCH_STANDARD_EVENT.INITIATE_PURCHASE
添加付款信息Commerce EventBRANCH_STANDARD_EVENT.ADD_PAYMENT_INFO
购买Commerce EventBRANCH_STANDARD_EVENT.PURCHASE
消费积分Commerce EventBRANCH_STANDARD_EVENT.SPEND_CREDITS
搜索Content 事件BRANCH_STANDARD_EVENT.SEARCH
查看商品Content 事件BRANCH_STANDARD_EVENT.VIEW_ITEM
查看商品Content 事件BRANCH_STANDARD_EVENT.VIEW_ITEMS
频率Content 事件BRANCH_STANDARD_EVENT.RATE
分享Content 事件BRANCH_STANDARD_EVENT.SHARE
完成注册Lifecycle EventBRANCH_STANDARD_EVENT.COMPLETE_REGISTRATION
完成教程Lifecycle EventBRANCH_STANDARD_EVENT.COMPLETE_TUTORIAL
达标级别Lifecycle EventBRANCH_STANDARD_EVENT.ACHIEVE_LEVEL
解锁成就Lifecycle EventBRANCH_STANDARD_EVENT.UNLOCK_ACHIEVEMENT

处理推送通知

  • 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);
  • 要处理 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()

处理新的深度链接 sessionBuilder()....reInit() will clear the current session data, if there is any, and a new referred ""open"" will be attributed.

处理应用中的链接

  • 允许您通过启动 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);

❗️

处理新的深度链接

在应用中处理新的深度链接将清除当前会话数据,并将新引用的 “open” 归因于此。

❗️

链接到当前打开的 activity

与处理推送通知类似,链接到当前打开的 activity 或在后堆栈中且部分可见的 activity 必须通过 sessionBuilder()....reInit()

启用100%匹配

  • Uses Chrome Tabs to increase attribute matching success.
  • 添加 implementation 'androidx.browser:browser:1.5.0' to your build.gradle
  • 如果您需要自定义标签库,但不希望启用100%匹配,则可以在会话初始化之前调用 Branch.enableCookieBasedMatching(null) prior to session initialization.

延迟会话初始化

有时,用户可能需要延迟会话初始化,例如进行异步调用以获得一些需要作为请求 metadata传递给 Branch 的数据。

在这种情况下,您可能会遇到 “SDK 已初始化”错误,这是由于 Activity 进入 RESUMED 状态时 Branch 会自行初始化会话而发生的。为避免这种情况,您可以手动禁用自动会话初始化,并在异步调用完成后自行初始化会话。

注意: 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);
    }
}

启用/禁用用户追踪

如果您需要按照 GDPR 的目的遵循用户不被追踪的请求,或者认为用户不应该被追踪,请利用此字段来防止 Branch 发送网络请求。此设置也可以在所有用户的特定链接或 Branch Link 中被启用。

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

您可以选择在应用的整个生命周期中调用它。调用后,网络请求将不会从 SDK发送。链接生成将继续起作用,但是不会包含有关用户的标识信息。此外,深度链接将继续起作用,但不会为用户追踪分析。

设置初始化 metadata

🚧

仅限数据集成

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}", […]);

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

控制 Branch 如何处理网络请求

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");