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>
- Change the following values to match your Branch Dashboard
your.app.com
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
- Used for
WebView
andChromeTab
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(this@MainActivity2, 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()
andonStop()
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
orClassNotFoundException
- Add to your
build.gradle
defaultConfig {
multiDexEnabled true
}
- Add to your
Application class
and make sure it extendsMultiDexApplication
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 yourProguard
file
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 yourAndroidManifest.xml
can accept
Stuck in initState_ == SESSION_STATE.INITIALISING
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.
Updated 3 months ago