Skip to content
Get Help

Upgrade to the Branch Android SDK 6.0Beta

To upgrade your app from the Branch Android SDK 5.x to the 6.0 beta, update the SDK in step 1, then follow Upgrade from 5.x. That section takes you through steps 2 to 4 and every other call that changed.

Version 6.0 starts from one configuration object, and your app gets all deep link data from requestDeepLinkData.

Beta

The Android SDK 6.0 is a beta, and its API can still change before the final release. Test it in development and test builds only, and don't ship it to Google Play.

If you find a problem or a gap, email support@branch.io with "Testing new SDK Beta" as the subject.

Use an AI coding assistant (Optional) ​

Copy this prompt into a coding assistant like Claude Code or Cursor, and it upgrades the SDK for you.

text
Upgrade this app to the Branch Android SDK 6.0 beta, version 6.0.0-beta.3.

Read this guide and follow it. Don't rely on what you already know about the
Branch SDK, because 6.0 removes or changes most of the 5.x API:
https://help.branch.io/developer-hub/android-sdk-6-integration.md

1. Find the app's Branch integration. Look for io.branch.sdk.android in the
   Gradle files, for io.branch entries in AndroidManifest.xml, for
   io.branch.sdk string resources, for an assets/branch.json file, and for
   Branch calls in the Application class and activities.
2. Before you change any code, collect what you need. Reuse the Branch keys
   already in the project, and ask me for any that are missing, including
   both the live key and the test key. If the app has product flavors, ask
   me which Branch key each flavor uses. If more than one activity handles
   links, ask me which one should call requestDeepLinkData.
3. Follow step 1 in the guide, then every step in "Upgrade from 5.x",
   including the steps for 5.x code that still builds. Then apply any case
   in "Handle edge cases" that fits this app.
4. Write code in the app's language, Kotlin or Java. Don't change the app's
   intent filters or launch modes.
5. Build the app and fix any errors.
6. Finish with a list of the files you changed, anything you couldn't
   migrate, and the checks from step 4 in the guide for me to run on a
   device.

Review the changes before you merge them.

1. Update the SDK to the beta version ​

Change io.branch.sdk.android:library to version 6.0.0-beta.3 exactly, so your app doesn't pick up a different build. Version 6.0 needs a minSdk of 21 or later.

kotlin
// App module build.gradle.kts
dependencies {
    implementation("io.branch.sdk.android:library:6.0.0-beta.3")

    // (Optional) Collect the Google Advertising ID
    implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
}
If you collect the Google Advertising ID and minify release builds

Add this rule to your ProGuard rules file.

text
# The SDK finds the Google Advertising ID library by class name,
# so keep the class in minified builds
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient

2. Start the SDK ​

Build a BranchConfiguration with your Branch key, and pass it to Branch.initialize in your Application class. Use the same key as your 5.x app, which is usually in the io.branch.sdk.BranchKey meta-data in your manifest. If your app doesn't have an Application class yet, create one, and name it in the android:name attribute of the <application> element in your manifest.

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

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // Use your test key in debug builds and your live key in release builds
        val config = BranchConfiguration.Builder("<branch_key>")
            // Automatic opens are on by default. Set this to false to send
            // each open yourself, as in "Send opens yourself"
            .setAutomaticOpenEvents(true)
            // Set any other options on the builder here, as listed in
            // "BranchConfiguration reference"
            .build()

        // Start the SDK here, so it's ready before any activity asks for
        // link data
        Branch.initialize(this, config)
    }
}
java
import android.app.Application;
import io.branch.referral.Branch;
import io.branch.referral.BranchConfiguration;

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // Use your test key in debug builds and your live key in release builds
        BranchConfiguration config =
                new BranchConfiguration.Builder("<branch_key>")
                        // Automatic opens are on by default. Set this to
                        // false to send each open yourself, as in
                        // "Send opens yourself"
                        .setAutomaticOpenEvents(true)
                        // Set any other options on the builder here, as
                        // listed in "BranchConfiguration reference"
                        .build();

        // Start the SDK here, so it's ready before any activity asks for
        // link data
        Branch.initialize(this, config);
    }
}

Everywhere else, get the SDK from Branch.getInstance(), which is null until this call runs.

Use a different key for debug and release builds

Define the key for each build type. Then pass BuildConfig.BRANCH_KEY to the builder instead of the literal key.

kotlin
// App module build.gradle.kts
android {
    // Required with Android Gradle Plugin 8.0 or later
    buildFeatures { buildConfig = true }

    buildTypes {
        debug { buildConfigField("String", "BRANCH_KEY", "\"<test_key>\"") }
        release { buildConfigField("String", "BRANCH_KEY", "\"<live_key>\"") }
    }
}

Call requestDeepLinkData in your launcher activity's onCreate and onNewIntent methods, and route the user in its callback.

kotlin
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import io.branch.referral.Branch

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // The app launches. On a new install from a link, this returns
        // that link's data
        // Skip re-creations so they don't count as opens, for example
        // after a rotation
        if (savedInstanceState == null) requestBranchData()
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        // The SDK reads the link from the activity's current intent
        setIntent(intent)
        requestBranchData()
    }

    private fun requestBranchData() {
        // Branch runs the callback on the main thread
        // The params object holds the link's data, including any keys you
        // added to the link
        Branch.getInstance().requestDeepLinkData(this) { params, error ->
            if (error != null) {
                // The request failed, for example because the device is offline
            } else if (params?.optBoolean("+clicked_branch_link") == true) {
                // A Branch Link opened the app, so show the content it
                // points to
            }
        }
    }
}
java
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import io.branch.referral.Branch;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // The app launches. On a new install from a link, this returns
        // that link's data
        // Skip re-creations so they don't count as opens, for example
        // after a rotation
        if (savedInstanceState == null) {
            requestBranchData();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // The SDK reads the link from the activity's current intent
        setIntent(intent);
        requestBranchData();
    }

    private void requestBranchData() {
        // Branch runs the callback on the main thread
        // The params object holds the link's data, including any keys you
        // added to the link
        Branch.getInstance().requestDeepLinkData(this, (params, error) -> {
            if (error != null) {
                // The request failed, for example because the device is offline
            } else if (params != null
                    && params.optBoolean("+clicked_branch_link")) {
                // A Branch Link opened the app, so show the content it
                // points to
            }
        });
    }
}

Each requestDeepLinkData call counts as an install or open, so call it only where this sample does. Branch doesn't count an open on its own when your app returns from the background.

Read link data in this callback. When your app moves to the background, the SDK can clear the data that getLatestReferringParams() returns.

4. Check your integration ​

After you finish Upgrade from 5.x, run a debug build with verbose logging, open a Branch Link, and confirm that the link data arrives.

  1. Add .setLogLevel(BranchLogger.BranchLogLevel.VERBOSE) to the builder in your Application class, in debug builds only. The BranchLogger class is in the io.branch.referral package.
  2. Run the app on a device.
  3. Filter Logcat by the BranchSDK tag.
  4. Open a Branch Link for your app from a messaging or notes app. Use a link from the same Branch app as your key, such as a test-app.link link for a test key.
  5. Check that the RequestDeepLink Succeeded line in Logcat shows +clicked_branch_link as true.
  6. Check that your release build uses your live key, without the verbose log level.
If a check fails
  • If the link opens a browser instead of your app, Android didn't verify your App Links. On Android 12 or later, run adb shell pm get-app-links <package_name> and check that each Branch host shows as verified. If one doesn't, check that Branch has the SHA256 fingerprint of the key that signed the build.
  • If Branch.getInstance() returns null, check that the android:name attribute of <application> names your Application class.
  • If your callback gets an error, the Request DeepLink failed with HTTP code line in Logcat says why.
  • If build() throws an IllegalArgumentException, see Fix a configuration error.

Handle edge cases ​

Most integrations don't run into these cases. Check them when your app does one of these things, or when something doesn't work as expected.

Fix a configuration error ​

If the key is empty or a value is out of range, build() throws an IllegalArgumentException that lists each setting that isn't valid. The timeouts and the retry interval must be more than 0, and the retry count must be 0 or more. If you create the builder without a key, Branch.initialize throws the same exception.

Use coroutines ​

For launches, use the callback version of requestDeepLinkData from step 3, not the suspend version. The suspend version drops its request if something cancels the coroutine before Branch sends it, and a rotation cancels the lifecycleScope of the activity.

Upgrade from 5.x ​

Most of the upgrade is in how the SDK starts and how your app gets deep link data. Version 6.0 removes getAutoInstance and the session builder. Your app starts the SDK with Branch.initialize, and requestDeepLinkData returns link data.

  1. Replace Branch.getAutoInstance(this) in your Application class by following 2. Start the SDK.
  2. If your manifest names io.branch.referral.BranchApp or your Application class extends it, use your own Application class that extends android.app.Application. Version 6.0 removes BranchApp, so an app whose manifest still names it builds but crashes at launch.
  3. In your launcher activity, replace the sessionBuilder(...).init() call with the onCreate code in 3. Handle deep links. The 5.x guide put that call in onStart, but don't call requestDeepLinkData there or in a base class that every activity shares, because each call counts as another open.
  4. In onNewIntent, replace the reInit() call and the branch_force_new_session check around it with the onNewIntent code in 3. Handle deep links. Version 6.0 ignores that extra.
  5. If you used auto deep linking, start the right activity yourself in your requestDeepLinkData callback.
  6. If you used auto deep linking, remove the io.branch.sdk.auto_link_keys and io.branch.sdk.auto_link_path meta-data from your manifest, because 6.0 ignores it.
  7. If your app has an assets/branch.json file, move its settings to the builder. Version 6.0 ignores the key in this file, but the file's other settings override the builder's.
    • The branchKey, liveKey, testKey, and useTestInstance settings become the key you pass to the builder.
    • The apiUrl, fbAppId, cppLevel, and enableLogging settings map to the builder's setApiUrl, setFacebookAppId, setAttributionLevel, and setLogLevel methods.
    • The installReferrerFetchTimeout setting has no replacement. For deferInitForPluginRuntime, call requestDeepLinkData when your plugin's runtime is ready.
  8. Delete the assets/branch.json file.
  9. If you set the attribution level on the builder, pass each user's saved choice, because Branch.initialize applies the builder's level at every launch over the level that Branch saved. If you don't set it, each user's level and opt-out from 5.x carry over.
  10. (Optional) Remove the io.branch.sdk.BranchKey, io.branch.sdk.BranchKey.test, and io.branch.sdk.TestMode entries from your manifest and string resources.
  11. Build the app.
  12. Fix each build error by using the following table.
  13. Change the 5.x calls in the table that still build. These are disableTracking and Branch.notifyNativeToInit().
  14. Run the checks in 4. Check your integration.

This table maps 5.x calls to their 6.0 replacements. In this table, a call that starts with Branch. is static.

5.x6.0
Branch.getAutoInstance(context) or Branch.getAutoInstance(context, key)Branch.initialize(context, config)
BranchApp as your Application classYour own Application class that calls Branch.initialize
io.branch.sdk.BranchKey in the manifest or in a string resource, the key in branch.json, or setBranchKey(key)BranchConfiguration.Builder("<branch_key>")
Branch.enableTestMode(), Branch.disableTestMode(), or io.branch.sdk.TestMode in the manifest or in a string resourcePass your test or live key to BranchConfiguration.Builder
Branch.sessionBuilder(activity)...init()requestDeepLinkData(activity, callback) in onCreate, not in onStart
Branch.sessionBuilder(activity)...reInit() in onNewIntentsetIntent(intent), then requestDeepLinkData(this, callback) for every new intent, with no branch_force_new_session check
putExtra("branch", url) with putExtra("branch_force_new_session", true), for a push notification or a link inside your appOpen your launcher activity with the branch extra, which requestDeepLinkData(activity, callback) reads. Version 6.0 ignores branch_force_new_session.
withData(uri) on the session builderrequestDeepLinkData(activity, callback) when uri is the activity's intent data, because that call reads the intent itself. For any other URI, requestDeepLinkData(uri, callback).
withCallback(BranchUniversalReferralInitListener) on the session builderA BranchReferralInitListener. In it, get the object and link properties with BranchUniversalObject.getReferredBranchUniversalObject() and LinkProperties.getReferredLinkProperties().
withDelay, isReferrable, and ignoreIntent on the session builder, plus removeSessionInitializationDelay, unlockPendingIntent, Branch.expectDelayedSessionInitialization, Branch.bypassWaitingForIntent, Branch.isWaitingForIntent, Branch.enableForcedSession, Branch.disableForcedSession, Branch.isForceSessionEnabled, Branch.enableBypassCurrentActivityIntentState, and Branch.bypassCurrentActivityIntentStateCall requestDeepLinkData when your app is ready to handle the link
Branch.notifyNativeToInit() and deferInitForPluginRuntime in branch.jsonCall requestDeepLinkData when your plugin's runtime is ready. The old call still builds but does nothing.
Auto deep linking with io.branch.sdk.auto_link_keys or io.branch.sdk.auto_link_path, and Branch.isAutoDeepLinkLaunch(activity)Start the activity yourself in your requestDeepLinkData callback
setIdentity(id)setUserAlias(id)
disableTracking(true) and disableTracking(false)setAttributionLevel(Defines.BranchAttributionLevel.NONE) in updateConfiguration, or another level to opt back in. The old calls still build, with a deprecation warning.
getInitState() compared to a SessionState valuegetInitState(), which returns a BranchSessionState that you check by type
Branch.useEUEndpoint()setEUEndpoint(true) on the builder
setNetworkTimeout, setNetworkConnectTimeout, setRetryCount, and setRetryIntervalBuilder methods with the same names. An out-of-range value makes build() throw.
Branch.setAPIUrl(url) and Branch.setCDNBaseUrl(url)setApiUrl(url) and setCdnBaseUrl(url) on the builder
Branch.setCallbackForTracingRequests(callback)setRequestTracingCallback(callback) on the builder
setBranchRemoteInterface(remoteInterface)setRemoteInterface(remoteInterface) on the builder
setDMAParamsForEEA(eeaRegion, adPersonalizationConsent, adUserDataUsageConsent)setDMAParameters(params) on the builder, or in updateConfiguration when consent changes, with params built by DMAParameters.Builder
Branch.setFBAppID(id)setFacebookAppId(id) on the builder
setPreinstallCampaign, setPreinstallPartner, and addInstallMetadataBuilder methods with the same names
Branch.setReferringLinkAttributionForPreinstalledAppsEnabled()setReferringLinkAttributionForPreinstalledApps(true) on the builder, which has no effect in 6.0.0-beta.3
addWhiteListedScheme(scheme) and setWhiteListedSchemes(schemes)addWhitelistedScheme(scheme) on the builder, once for each scheme
addUriHostsToSkip(host)addUriHostToSkip(host) on the builder
Branch.setIsUserAgentSync(sync)setUserAgentFetchSync(sync) on the builder
setLimitFacebookTracking, disableAdNetworkCallouts, and setNoConnectionRetryMaxRemoved, with no replacement
registerView() or registerView(callback) on BranchUniversalObject, or registerView(buo, callback) on BranchBranchEvent(BRANCH_STANDARD_EVENT.VIEW_ITEM).addContentItems(buo).logEvent(context)
addContentMetadata(key, value) and addContentMetadata(map) on BranchUniversalObjectgetContentMetadata().addCustomMetadata(key, value) for each key, which adds to the existing metadata
getMetadata() on BranchUniversalObjectgetContentMetadata().getCustomMetadata()
getPrice() and getCurrencyType() on BranchUniversalObjectThe price and currencyType fields of getContentMetadata(), which hold the real values. In 5.x, these calls always returned 0.0 and null. The price field is a Double that's null when no price is set, and currencyType is a CurrencyType enum.
setContentType(type) on BranchUniversalObjectDelete the call, because it did nothing in 5.x. To set a content type, use getContentMetadata().setContentSchema(schema) with a BranchContentSchema.
showShareSheet(...) on BranchUniversalObject, setCallback on BranchShareSheetBuilder, and listeners that implement Branch.ExtendedBranchLinkShareListenerBranch.getInstance().share(activity, buo, linkProperties, callback, title, subject), with a Branch.BranchNativeLinkShareListener callback. It needs API level 22 or later.
Branch.isInstantApp, Branch.showInstallPrompt, Branch.disableInstantDeepLinking, setInstantDeepLinkPossible, and isInstantDeepLinkPossibleRemoved, with no replacement
resetUserSession, disableAppList, Branch.disableDeviceIDFetch, Branch.isDeviceIDFetchDisabled, setInstallReferrerTimeout, setDeepLinkDebugMode, getDeeplinkDebugParams, notifyNetworkAvailable, cancelShareLinkDialog, and getBranchPluginSupportRemoved, with no replacement
setChannelProperties on BranchShareSheetBuilder, Branch.IChannelProperties, and BranchUniversalObject.RegisterViewStatusListenerRemoved, with no replacement
getType, setContentIndexingMode, setLocalIndexMode, isPublicallyIndexable, and isLocallyIndexable on BranchUniversalObjectRemoved, with no replacement

The BranchEvent and LinkProperties APIs stay the same.

BranchConfiguration reference ​

Version 6.0 moves the SDK's settings into one BranchConfiguration, which you create with BranchConfiguration.Builder and pass to Branch.initialize. This sample sets the builder's main options to their defaults or example values, with a note on what each one does.

kotlin
// Your live or test key
val config = BranchConfiguration.Builder("<branch_key>")
    // On by default. With false, Branch holds each open until you call
    // sendOpen(callback) or the app goes to the background
    .setAutomaticOpenEvents(true)

    // The least severe level that Branch logs. Logging stays off until
    // you set this or a logging callback.
    .setLogLevel(BranchLogger.BranchLogLevel.WARN)
    // Your logger instead of Logcat
    .setLoggingCallback { message, severity ->
        Log.d("Branch", "$severity: $message")
    }

    // Milliseconds to connect to Branch's servers
    .setNetworkConnectTimeout(10_000)
    // Milliseconds to wait for a response once connected
    .setNetworkTimeout(5_500)
    // Retries after a server error or a network failure
    .setRetryCount(3)
    // Milliseconds before the first retry, doubled for each retry after it,
    // up to 30 seconds
    .setRetryInterval(1_000)

    // FULL is the default; the others are REDUCED, MINIMAL, and NONE.
    // Branch applies this level at every launch and replaces the level it
    // saved, so if users can change their consent, pass their saved choice
    // instead, or leave this line out.
    .setAttributionLevel(Defines.BranchAttributionLevel.FULL)
    // EEA consent for Google. Branch keeps sending the last values set,
    // including values saved by 5.x.
    .setDMAParameters(
        DMAParameters.Builder()
            .setEeaRegion(true)
            .setAdPersonalizationConsent(false)
            .setAdUserDataUsageConsent(true)
            .build()
    )

    // Turns on the Meta install referrer
    .setFacebookAppId("1234567890")
    // Sent with the install
    .addInstallMetadata("app_variant", "free")
    // Only for apps preinstalled on devices
    .setPreinstallCampaign("spring_promo")
    .setPreinstallPartner("oem_partner")
    .build()

Branch.initialize(this, config)
java
// Your live or test key
BranchConfiguration config = new BranchConfiguration.Builder("<branch_key>")
        // On by default. With false, Branch holds each open until you
        // call sendOpen(callback) or the app goes to the background
        .setAutomaticOpenEvents(true)

        // The least severe level that Branch logs. Logging stays off
        // until you set this or a logging callback.
        .setLogLevel(BranchLogger.BranchLogLevel.WARN)
        // Your logger instead of Logcat
        .setLoggingCallback((message, severity) ->
                Log.d("Branch", severity + ": " + message))

        // Milliseconds to connect to Branch's servers
        .setNetworkConnectTimeout(10_000)
        // Milliseconds to wait for a response once connected
        .setNetworkTimeout(5_500)
        // Retries after a server error or a network failure
        .setRetryCount(3)
        // Milliseconds before the first retry, doubled for each retry
        // after it, up to 30 seconds
        .setRetryInterval(1_000)

        // FULL is the default; the others are REDUCED, MINIMAL, and NONE.
        // Branch applies this level at every launch and replaces the level
        // it saved, so if users can change their consent, pass their saved
        // choice instead, or leave this line out.
        .setAttributionLevel(Defines.BranchAttributionLevel.FULL)
        // EEA consent for Google. Branch keeps sending the last values
        // set, including values saved by 5.x.
        .setDMAParameters(new DMAParameters.Builder()
                .setEeaRegion(true)
                .setAdPersonalizationConsent(false)
                .setAdUserDataUsageConsent(true)
                .build())

        // Turns on the Meta install referrer
        .setFacebookAppId("1234567890")
        // Sent with the install
        .addInstallMetadata("app_variant", "free")
        // Only for apps preinstalled on devices
        .setPreinstallCampaign("spring_promo")
        .setPreinstallPartner("oem_partner")
        .build();

Branch.initialize(this, config);

Note

The builder also has setTestMode and setReferringLinkAttributionForPreinstalledApps, which have no effect in 6.0.0-beta.3.

Send opens yourself ​

With setAutomaticOpenEvents(false), Branch still resolves each link and calls your requestDeepLinkData callback, but it holds the open until you call sendOpen. Use this when the open needs data that arrives later, such as Adobe's Experience Cloud ID (ECID). Set the data with setRequestMetadata, then call sendOpen.

kotlin
// Call Branch.getInstance().sendOpen after requestDeepLinkData
// in requestBranchData() from step 3
// This example uses Adobe Identity, which returns the ECID asynchronously
Identity.getExperienceCloudId { ecid ->
    Branch.getInstance()
        .setRequestMetadata("\$marketing_cloud_visitor_id", ecid)
    Branch.getInstance().sendOpen { error ->
        // error is null when Branch sent the open
    }
}
java
// Call Branch.getInstance().sendOpen after requestDeepLinkData
// in requestBranchData() from step 3
// This example uses Adobe Identity, which returns the ECID asynchronously
Identity.getExperienceCloudId(ecid -> {
    Branch.getInstance()
            .setRequestMetadata("$marketing_cloud_visitor_id", ecid);
    Branch.getInstance().sendOpen(error -> {
        // error is null when Branch sent the open
    });
});
  • Call sendOpen once for each requestDeepLinkData call.
  • If you call sendOpen before the link data arrives, Branch sends the open when it does.
  • If your app goes to the background first, Branch sends the open then. At the NONE attribution level, Branch waits until the user opts in.
  • On a new install, events and other requests that need an open fail if they run before Branch sends the open.

Change settings while the app runs ​

To change a setting after start-up, pass updateConfiguration a configuration that sets only the changed values, as in this consent example. Create its builder without a key.

kotlin
// In your consent screen's handler, after Branch.initialize
fun onConsentChosen(
    level: Defines.BranchAttributionLevel,
    adPersonalization: Boolean,
    adUserData: Boolean
) {
    // Save the choice in your own storage, and pass it to the builder at
    // the next launch
    saveConsent(level, adPersonalization, adUserData)
    // No key
    val changes = BranchConfiguration.Builder()
        .setAttributionLevel(level)
        .setDMAParameters(
            DMAParameters.Builder()
                .setEeaRegion(true)
                .setAdPersonalizationConsent(adPersonalization)
                .setAdUserDataUsageConsent(adUserData)
                .build()
        )
        .build()
    Branch.getInstance().updateConfiguration(changes)
}
java
// In your consent screen's handler, after Branch.initialize
void onConsentChosen(Defines.BranchAttributionLevel level,
                     boolean adPersonalization, boolean adUserData) {
    // Save the choice in your own storage, and pass it to the builder at
    // the next launch
    saveConsent(level, adPersonalization, adUserData);
    // No key
    BranchConfiguration changes = new BranchConfiguration.Builder()
            .setAttributionLevel(level)
            .setDMAParameters(new DMAParameters.Builder()
                    .setEeaRegion(true)
                    .setAdPersonalizationConsent(adPersonalization)
                    .setAdUserDataUsageConsent(adUserData)
                    .build())
            .build();
    Branch.getInstance().updateConfiguration(changes);
}

The changes apply to the next request Branch sends, and settings you don't set keep their current values. Branch saves the attribution level and DMA values on the device, so they carry over to the next launch, unless your start-up configuration sets new ones.

An update doesn't start a new session. When a user opts in from NONE, Branch sends the open it held while attribution was off. With setAutomaticOpenEvents(false), Branch sends that open only after you call sendOpen, or once the app has gone to the background. A change between two levels other than NONE sends no open.

The key, setTestMode, setFacebookAppId, the preinstall settings, addInstallMetadata, and setAutomaticOpenEvents only apply at Branch.initialize, so updateConfiguration ignores them and logs a warning.