필터

Android Troubleshooting

Using bnc.lt or a Custom Link Domain

  • bnc.lt link domain
<activity android:name="com.yourapp.your_activity">
    <!-- App Link your activity to Branch links-->
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
         <data android:scheme="https" android:host="bnc.lt" />
         <data android:scheme="http" android:host="bnc.lt" />
    </intent-filter>
</activity>
  • custom link domain
<activity android:name="com.yourapp.your_activity">
    <!-- App Link your activity to Branch links-->
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
         <data android:scheme="https" android:host="your.app.com" />
         <data android:scheme="http" android:host="your.app.com" />
    </intent-filter>
</activity>

Deep Link Routing

  • Loads a specific URI Scheme path, for example
    • $deeplink_path="content/123"
    • $android_deeplink_path="content/123"
  • Recommend to use Navigate to content instead
<meta-data android:name="io.branch.sdk.auto_link_path" android:value="content/123/, another/path/, another/path/*" />

Deep Link Routing in App

  • 사용 WebView and ChromeTab within the app to render HTML normally
  • Branch links within the WebView will route internally within your app, while other contents will continue to route externally
  • Launch Branch deep links with Web View
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val webView = findViewById(R.id.webView) as WebView
    webView!!.webViewClient = BranchWebViewController("appname.app.link", MainActivity2::class.java)
    webView!!.loadUrl(URL_TO_LOAD)
}

inner class BranchWebViewController internal constructor(private val myDomain_: String, private val activityToLaunch_: Class<*>) : WebViewClient() {

    override fun onLoadResource(view: WebView, url: String) {
        super.onLoadResource(view, url)
    }

    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
        val url = request.url.toString()

        if (url.contains(myDomain_)) {
            val i = Intent(view.context, activityToLaunch_)
            i.putExtra("branch", url)
            i.putExtra("branch_force_new_session", true)
      //finish(); if launching same activity
            startActivity(i)
        } else {
            view.loadUrl(url)
        }

        return true
    }
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    WebView webView = (WebView) findViewById(R.id.webView);
    webView.setWebViewClient(new BranchWebViewController(YOUR_DOMAIN, MainActivity.class)); //YOUR_DOMAIN example: appname.app.link
    webView.loadUrl(URL_TO_LOAD);
}

public class BranchWebViewController extends WebViewClient {

    private String myDomain_;
    private Class activityToLaunch_;

    BranchWebViewController(@NonNull String myDomain, Class activityToLaunch) {
        myDomain_ = myDomain;
        activityToLaunch_ = activityToLaunch;
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        String url = request.getUrl().toString();

        if (url.contains(myDomain_)) {
            Intent i = new Intent(view.getContext(), activityToLaunch_);
            i.putExtra("branch", url);
            i.putExtra("branch_force_new_session", true);
            startActivity(i);
            //finish(); if launching same activity
        } else {
            view.loadUrl(url);
        }

        return true;
  • Launch Branch deep links with Chrome Tabs
val builder = CustomTabsIntent.Builder()
val customTabsIntent = builder.build()
customTabsIntent.intent.putExtra("branch", BRANCH_LINK_TO_LOAD)
customTabsIntent.intent.putExtra("branch_force_new_session", true)
customTabsIntent.launchUrl([email protected], Uri.parse(BRANCH_LINK_TO_LOAD))
//finish() if launching same activity
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.intent.putExtra("branch", BRANCH_LINK_TO_LOAD);
customTabsIntent.intent.putExtra("branch_force_new_session", true);
customTabsIntent.launchUrl(MainActivity.this, Uri.parse(BRANCH_LINK_TO_LOAD));
//finish(); if launching same activity

Deep Link Activity Finishes

  • Be notified when the deep link Activity finishes
<meta-data android:name="io.branch.sdk.auto_link_request_code" android:value="@integer/AutoDeeplinkRequestCode" />
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    // Checking if the previous activity is launched on branch Auto deep link.
    if (requestCode == resources.getInteger(R.integer.AutoDeeplinkRequestCode)) {
        //Decide here where  to navigate  when an auto deep linked activity finishes.
        //For e.g. Go to HomeActivity or a  SignUp Activity.
        val i = Intent(applicationContext, CreditHistoryActivity::class.java)
        startActivity(i)
    }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Checking if the previous activity is launched on branch Auto deep link.
    if(requestCode == getResources().getInteger(R.integer.AutoDeeplinkRequestCode)){
        //Decide here where  to navigate  when an auto deep linked activity finishes.
        //For e.g. Go to HomeActivity or a  SignUp Activity.
        Intent i = new Intent(getApplicationContext(), CreditHistoryActivity.class);
        startActivity(i);
    }
}

Test Deeplink Routing for Your Branch Links

Append ?bnc_validate=true to any of your app's Branch links and click it on your mobile device (not the Simulator!) to start the test.

For instance, to validate a link like: "https://<yourapp\>.app.link/NdJ6nFzRbK" click on: "https://<yourapp\>.app.link/NdJ6nFzRbK?bnc_validate=true"

Pre Android API 15 Support

  • Use Branch SDK 1.14.5
  • Add to onStart() and onStop()
override fun onStart() {
    super.onStart()
    Branch.getInstance().initSession()
}

override fun onStop() {
    super.onStop()
    Branch.getInstance().closeSession()
}
@Override
protected void onStart() {
    super.onStart();
    Branch.getInstance(getApplicationContext()).initSession();
}

@Override
protected void onStop() {
    super.onStop();
    branch.closeSession();
}

Using the Default Application Class

  • If your app does not have an application class
<application android:name="io.branch.referral.BranchApp">

Generate Signing Certificate

  • Used for Android App Link deep linking
  • Navigate to your keystore file
  • Run keytool -list -v -keystore my-release-key.keystore
  • Will generate a value like: AA:C9:D9:A5:E9:76:3E:51:1B:FB:35:00:06:9B:56:AC:FB:A6:28:CE:F3:D6:65:38:18:E3:9C:63:94:FB:D2:C1
  • Copy this value to your Branch Dashboard

Matching Through the Install Listener

  • Enable the ability to pass link_click_id from Google Play to Branch
  • This will increase attribution and deferred deep linking accuracy
  • Branch default is 1.5 seconds to wait for Google Play analytics
  • You can optimize the performance based on needs (e.g. 0, 5000, 10000)
  • Add to your application class before getAutoInstance (Load Branch
Branch.setPlayStoreReferrerCheckTimeout(5_000)
Branch.setPlayStoreReferrerCheckTimeout(5000);
  • Test
adb shell am broadcast -a com.android.vending.INSTALL_REFERRER -n io.branch.androidexampledemo/io.branch.referral.InstallListener --es "referrer" "link_click_id=123"

Enable Multidexing

  • Adding additional dependencies may overrun the dex limit and lead to NoClassDefFoundError or ClassNotFoundException
  • Add to your build.gradle
defaultConfig {
    multiDexEnabled true
}
  • Add to your Application class and make sure it extends MultiDexApplication
override fun attachBaseContext(base: Context?) {
    super.attachBaseContext(base)
    MultiDex.install(this)
}
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

InvalidClassException, ClassLoadingError or VerificationError

  • Often caused by a Proguard bug. Try the latest Proguard version or disable Proguard optimization by setting -dontoptimize

Proguard Warning or Errors with Answers-shim Module

  • Often caused when you exclude the answers-shim. Try adding -dontwarn com.crashlytics.android.answers.shim.** to your Proguard file

Proguard Warning or Errors with AppIndexing Module

  • The Branch SDK has optional dependency on Firebase app indexing to provide new Firebase content listing features. This may cause a proguard warning depending on your proguard settings. Please add the following to your proguard file to solve this issue: -dontwarn com.google.firebase.appindexing.

Proguard Rules Without Play Services Ads Module

  • The Branch SDK has an optional dependency on Play Services Ads for GAID matching. Using Proguard without using this library can create issue in fetching the GAID while creating Branch session and events.

Please add the following to your proguard file to solve this issue:

-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);
}

-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
java.lang.String getId();
boolean isLimitAdTrackingEnabled();
}

Unable to Open This Link Error

  • Happens whenever URI Scheme redirection fails.
  • Make sure you do not have $deeplink_path or you have a $deeplink_path which your AndroidManifest.xml can accept

Stuck in initState_ == SESSION_STATE.INITIALISING

  • Often caused because Branch does not have the right application context from your activity. To fix this, pass in the singleton class when you access the Branch instance:
Branch.getInstance(getApplicationContext());

Handle the Error - BranchError.ERR_BRANCH_ALREADY_INITIALIZED

Why do you see the error?

The Branch Android SDK will automatically initialize when the app comes to the foreground, and the first activity to show enters the RESUMED lifecycle state. This is done as a failsafe not to miss tracking sessions.

Therefore, if you

  • Delay or never attempt to initialize, or
  • Have the app open to activities other than the launcher activity (where you attempt to initialize the session)

The Branch SDK will automatically initialize.

What is the Branch SDK doing?
The SDK will automatically initialize under the above conditions. Then if the app's code later tries to initialize the SDK (again), the SDK will throw an error. This prevents initializing over and over again or other potentially unexpected states.

What can you do to handle the error?
If you want to delay initialization without having the SDK self-initialize, you can do so using this method: Branch.expectDelayedSessionInitialization()

Alternatively, you can ignore the error and add the following code snippet to your callback:

if(error.getErrorCode() == BranchError.ERR_BRANCH_ALREADY_INITIALIZED) {
   branchReferringParams_ = Branch.getLatestReferringParams();
}

Minimum Versions

If you'd like to support down to API version 9 on Android, please pin to version 1.14.5. If you'd like to support API level 15, please pin to a 2.x version. The minimum version we support for 3.x is Android version 16.


Recommended Next Steps