Troubleshooting - Android SDK

    Issue

    A coroutine dependency error occurs during the build process with the following message.

    Text
    1234
    java.lang.NoClassDefFoundError: kotlin/coroutines/AbstractCoroutineContextKey
        at java.base/java.lang.ClassLoader.defineClass1(Native Method)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
      ...

    Cause

    If the kotlinx-coroutines-core library version is 1.3.5 or later, the kotlin-stdlib library version must be at a certain level or later.

    Solution

    Check whether the kotlin-stdlib library version is v.1.3.70 or later with the gradlew dependencies command. If the version is earlier than v.1.3.70, you need to update it.

    Issue

    Deeplink Open events that occur through the push notifications generated by the Braze SDK are not collected by Airbridge. Instead, the App Open event is collected.

    Cause

    The Airbridge Android SDK uses the dataString in the action and intent of the Activity to distinguish between Deeplink Open events and App Open events.

    When a user opens the app through a push notification using the Braze SDK, the app goes through an activity called NotificationTrampolineActivity. This activity handles push notifications, but the dataString is not included in its action and intent, preventing the SDK from determining if it's a Deeplink Open event or an App Open event.

    Solution

    The problem can be solved using the code snippet below for Airbridge Android SDK versions v2.21.5 and later.

    1234567
    val option = AirbridgeOptionBuilder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
      .setLifecycleIntegration {
        it.takeIf { it.javaClass.name == "com.braze.push.NotificationTrampolineActivity" }
        ?.run { intent?.extras?.getString("uri") }
      }
      .build()
    Airbridge.initializeSDK(application, option)
    12345678910111213141516
    AirbridgeOption option = new AirbridgeOptionBuilder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
      .setLifecycleIntegration(new AirbridgeLifecycleIntegration() {
          @Nullable
          @Override
          public String getDataString(@NonNull Activity activity) {
              if (activity.getClass().getName().equals("com.braze.push.NotificationTrampolineActivity")
                      && activity.getIntent() != null
                      && activity.getIntent().getExtras() != null) {
                  return activity.getIntent().getExtras().getString("uri");
              }
              return null;
          }
        })
      })
      .build();
    Airbridge.initializeSDK(application, option);

    Issue

    The "Manifest merger failed" error occurs during the build process.

    Cause

    The Airbridge SDK's AndroidManifest.xml includes rules to opt out of backing up the Shared Preferences data. The purpose of this rule is to avoid retaining the same Airbridge settings during the reinstallation of the app so that new installs or reinstalls can be detected accurately.

    Merging Airbridge SDK backup rules with your app backup rules can cause conflicts.

    Solution

    Below are the opt-out rules defined in the Airbridge SDK.

    123456789101112131415161718192021
    <?xml version="1.0" encoding="utf-8"?>
    <data-extraction-rules>
        <cloud-backup>
            <exclude domain="sharedpref" path="airbridge-internal" />
            <exclude domain="sharedpref" path="airbridge-install" />
            <exclude domain="sharedpref" path="airbridge-user-info" />
            <exclude domain="sharedpref" path="airbridge-user-alias" />
            <exclude domain="sharedpref" path="airbridge-user-attributes" />
            <exclude domain="sharedpref" path="airbridge-device-alias" />
            <exclude domain="database" path="airbridge.db" />
        </cloud-backup>
        <device-transfer>
            <exclude domain="sharedpref" path="airbridge-internal" />
            <exclude domain="sharedpref" path="airbridge-install" />
            <exclude domain="sharedpref" path="airbridge-user-info" />
            <exclude domain="sharedpref" path="airbridge-user-alias" />
            <exclude domain="sharedpref" path="airbridge-user-attributes" />
            <exclude domain="sharedpref" path="airbridge-device-alias" />
            <exclude domain="database" path="airbridge.db" />
        </device-transfer>
    </data-extraction-rules>
    12345678910
    <?xml version="1.0" encoding="utf-8"?>
    <full-backup-content>
        <exclude domain="sharedpref" path="airbridge-internal" />
        <exclude domain="sharedpref" path="airbridge-install" />
        <exclude domain="sharedpref" path="airbridge-user-info" />
        <exclude domain="sharedpref" path="airbridge-user-alias" />
        <exclude domain="sharedpref" path="airbridge-user-attributes" />
        <exclude domain="sharedpref" path="airbridge-device-alias" />
        <exclude domain="database" path="airbridge.db" />
    </full-backup-content>

    Fix conflict with fullBackupContent="string"

    Adding android:fullBackupContent="string" to the AndroidManifest.xml file may cause an error like the following.

    Build Output
    1
    Manifest merger failed : Attribute application@fullBackupContent value=(string) from AndroidManifest.xml

    To fix this error,

    • add xmlns:tools="http://schemas.android.com/tools" to the <manifest> tag

    • add tools:replace="android:fullBackupContent" to the <application> tag

    in the AndroidManifest.xml file.

    Fix conflict with dataExtractionRules="string resource"

    Adding android:dataExtractionRules="string resource" to the AndroidManifest.xml file may cause an error like the following.

    Build Output
    12
    Manifest merger failed : Attribute application@dataExtractionRules value=(string resource) from AndroidManifest.xml
    

    To fix this error,

    • add xmlns:tools="http://schemas.android.com/tools" to the <manifest> tag

    • add tools:replace="android:dataExtractionRules" to the <application> tag

    in the AndroidManifest.xml file.

    Fix conflict with allowBackup="false"

    Adding android:allowBackup="false" to the AndroidManifest.xml file may cause an error like the following.

    Build Output
    123
    Manifest merger failed : Attribute application@allowBackup value=(false) from AndroidManifest.xml:32:9-36
    	is also present at [:airbridge] AndroidManifest.xml:27:9-35 value=(true).
    	Suggestion: add 'tools:replace="android:allowBackup"' to <application> element at AndroidManifest.xml:30:5-250:19 to override.

    To fix this error,

    • add xmlns:tools="http://schemas.android.com/tools" to the <manifest> tag

    • add tools:replace="android:allowBackup" to the <application> tag

    in the AndroidManifest.xml file.

    If compileSdkVersion is lower than 31

    The android:dataExtractionRules has been added in API Level 31. Therefore, if the compileSdkVersion is lower than 31, an error like the following may occur.

    Build Output
    1
    AndroidManifest.xml: AAPT: error: attribute android:dataExtractionRules not found.

    To fix this error,

    • add xmlns:tools="http://schemas.android.com/tools" to the <manifest> tag

    • add tools:remove="android:dataExtractionRules" to the <application> tag

    in the AndroidManifest.xml file.

    For more guidance, refer to the articles below.

    Notice

    Airbridge Android SDK 4.9.0 and above do not require backup rule configuration. Only proceed with this step if you are using a version below 4.9.0.

    Why Configuration is Needed

    The Airbridge Android SDK requires certain data to be excluded from backup to ensure accurate reinstall detection. For SDK versions below 4.9.0, this must be configured manually.

    Configuration Methods

    If android:allowBackup="..." is included

    1. Add android:allowBackup to the tools:replace attribute of the <application> tag in AndroidManifest.xml. If there are other values, separate them with a comma (,). If there are no other values, do not use a comma.

      1234
      <application
          android:allowBackup="..."
          tools:replace="...,android:allowBackup"
          ...>

    If android:dataExtractionRules="..." is included

    1. Add android:dataExtractionRules to the tools:replace attribute of the <application> tag in AndroidManifest.xml. If there are other values, separate them with a comma (,). If there are no other values, do not use a comma.

      1234
      <application
          android:dataExtractionRules="..."
          tools:replace="...,android:dataExtractionRules"
          ...>
    2. Specify the backup rules file in android:dataExtractionRules="...". Add Airbridge exclusion rules to the backup rules file. (e.g., res/xml/data_extraction_rules.xml)

      123456789101112131415161718192021
      <?xml version="1.0" encoding="utf-8"?>
      <data-extraction-rules>
          <cloud-backup>
              <exclude domain="sharedpref" path="airbridge-internal" />
              <exclude domain="sharedpref" path="airbridge-install" />
              <exclude domain="sharedpref" path="airbridge-user-info" />
              <exclude domain="sharedpref" path="airbridge-user-alias" />
              <exclude domain="sharedpref" path="airbridge-user-attributes" />
              <exclude domain="sharedpref" path="airbridge-device-alias" />
              <exclude domain="database" path="airbridge.db" />
          </cloud-backup>
          <device-transfer>
              <exclude domain="sharedpref" path="airbridge-internal" />
              <exclude domain="sharedpref" path="airbridge-install" />
              <exclude domain="sharedpref" path="airbridge-user-info" />
              <exclude domain="sharedpref" path="airbridge-user-alias" />
              <exclude domain="sharedpref" path="airbridge-user-attributes" />
              <exclude domain="sharedpref" path="airbridge-device-alias" />
              <exclude domain="database" path="airbridge.db" />
          </device-transfer>
      </data-extraction-rules>

    If android:fullBackupContent="..." is included

    1. Add android:fullBackupContent to the tools:replace attribute of the <application> tag in AndroidManifest.xml. If there are other values, separate them with a comma (,). If there are no other values, do not use a comma.

      1234
      <application
          android:fullBackupContent="..."
          tools:replace="...,android:fullBackupContent"
          ...>
    2. Specify the backup rules file in android:fullBackupContent="...". Add Airbridge exclusion rules to the backup rules file. (e.g., res/xml/backup_rules.xml) Note that android:fullBackupContent="false" means there is no backup rules file, so you do not need to add the rules below.

      12345678910
      <?xml version="1.0" encoding="utf-8"?>
      <full-backup-content>
          <exclude domain="sharedpref" path="airbridge-internal" />
          <exclude domain="sharedpref" path="airbridge-install" />
          <exclude domain="sharedpref" path="airbridge-user-info" />
          <exclude domain="sharedpref" path="airbridge-user-alias" />
          <exclude domain="sharedpref" path="airbridge-user-attributes" />
          <exclude domain="sharedpref" path="airbridge-device-alias" />
          <exclude domain="database" path="airbridge.db" />
      </full-backup-content>

    Caution

    When adding values to the tools:replace attribute of the <application> tag, if there is a space after the comma (,), it may cause build errors in some Android Gradle Plugin (AGP) versions. Please be aware.

    Issue

    If an Airbridge SDK backup rule and a backup rule for a different third-party SDK (e.g., AppsFlyer SDK) overlap, you will see the build error below.

    123
    Attribute application@fullBackupContent value=(@xml/appsflyer_backup_rules) from [com.appsflyer:af-android-sdk:6.6.1] AndroidManifest.xml:14:18-73
    is also present at [io.airbridge:sdk-android:2.14.0] AndroidManifest.xml:27:18-78 value=(@xml/airbridge_auto_backup_rules).
    Suggestion: add 'tools:replace="android:fullBackupContent"' to <application> element at AndroidManifest.xml:7:5-13:19 to override.

    Cause

    Overlapping of the Airbridge SDK backup rules and third-party SDK backup rules can cause build errors.

    Solution

    Follow these steps to consolidate all SDK backup rules into one file.

    1. Create a backup rules file under the res/xml folder. If a file already exists, only add the Airbridge content.

      • For Android 11 and below: backup_rules.xml

        12345678910111213141516
        <?xml version="1.0" encoding="utf-8"?>
        <full-backup-content>
            <!-- Airbridge Backup Rules -->
            <exclude domain="sharedpref" path="airbridge-internal" />
            <exclude domain="sharedpref" path="airbridge-install" />
            <exclude domain="sharedpref" path="airbridge-user-info" />
            <exclude domain="sharedpref" path="airbridge-user-alias" />
            <exclude domain="sharedpref" path="airbridge-user-attributes" />
            <exclude domain="sharedpref" path="airbridge-device-alias" />
            <exclude domain="database" path="airbridge.db" />
          
            <!-- Appsflyer Backup Rules -->
            <exclude domain="sharedpref" path="appsflyer-data"/>
        	
        	<!-- Your Custom Backup Rules -->
        </full-backup-content>
      • For Android 12 and above: data_extraction_rules.xml

        123456789101112131415161718192021222324252627282930313233
        <?xml version="1.0" encoding="utf-8"?>
        <data-extraction-rules>
            <cloud-backup>
                <!-- Airbridge Backup Rules -->
                <exclude domain="sharedpref" path="airbridge-internal" />
                <exclude domain="sharedpref" path="airbridge-install" />
                <exclude domain="sharedpref" path="airbridge-user-info" />
                <exclude domain="sharedpref" path="airbridge-user-alias" />
                <exclude domain="sharedpref" path="airbridge-user-attributes" />
                <exclude domain="sharedpref" path="airbridge-device-alias" />
                <exclude domain="database" path="airbridge.db" />
        
                <!-- Appsflyer Backup Rules -->
                <exclude domain="sharedpref" path="appsflyer-data"/>
        
        	    <!-- Your Custom Backup Rules -->
            </cloud-backup>
            <device-transfer>
                <!-- Airbridge Backup Rules -->
                <exclude domain="sharedpref" path="airbridge-internal" />
                <exclude domain="sharedpref" path="airbridge-install" />
                <exclude domain="sharedpref" path="airbridge-user-info" />
                <exclude domain="sharedpref" path="airbridge-user-alias" />
                <exclude domain="sharedpref" path="airbridge-user-attributes" />
                <exclude domain="sharedpref" path="airbridge-device-alias" />
                <exclude domain="database" path="airbridge.db" />
        
                <!-- Appsflyer Backup Rules -->
                <exclude domain="sharedpref" path="appsflyer-data"/>
        
        	    <!-- Your Custom Backup Rules -->
            </device-transfer>
        </data-extraction-rules>
    2. Add android:allowBackup to the tools:replace attribute of the <application> tag in AndroidManifest.xml. If there are other values, separate them with a comma (,). If there are no other values, do not use a comma.

      1234
      <application
          android:fullBackupContent="@xml/custom_backup_rules"
          android:dataExtractionRules="@xml/custom_data_extraction_rules"
          tools:replace="android:fullBackupContent,android:dataExtractionRules">

    Caution

    When adding values to the tools:replace attribute of the <application> tag, if there is a space after the comma (,), it may cause build errors in some Android Gradle Plugin (AGP) versions. Please be aware.

    Issue

    GAID is being collected as 00000000-0000-0000-0000-000000000000 even though LAT (Limited Ad Tracking) is deactivated.

    Cause

    The AD_ID permission has been excluded due to other third-party libraries.

    Solution

    Add AD_ID permission.

    12345
    <manifest ...>
      ...
      <uses-permission android:name="com.google.android.gms.permission.AD_ID" />
      ...
    </manifest>

    Issue

    When uploading your app to Google Play Console, you may receive the following warning or rejection messages:

    • "Your app doesn't support 16 KB page size"

    • "16 KB page size compatibility required"

    • App upload is rejected or displayed in a warning state

    This is due to Google Play policy requirements that apps targeting Android 15 (API level 35) or higher must support 16KB page size.

    Cause

    Airbridge SDK supports 16KB page size from the following versions:

    However, SDK support alone is not sufficient. The entire app (APK/AAB) must be packaged with 16KB zipalign to pass Google Play policy.

    If APK/AAB is not built with 16KB zipalign:

    • You will receive warning or rejection messages when uploading to Google Play Console

    • Uploads will be completely blocked after November 1, 2025

    • The app may not work properly on 16KB page size devices in the future

    Solution

    Step 1: Check Airbridge SDK Version

    First, verify that your Airbridge SDK version supports 16KB. If you are using an older version, you must update to the latest version.

    Step 2: Check and Configure Android Gradle Plugin (AGP) Version

    Check your project's current AGP version.

    If using AGP 8.5.1 or higher:

    • 16KB zipalign is automatically applied without any additional configuration.

    • Proceed directly to Step 3.

    If using AGP 8.5.0 or lower:

    • Option A: Upgrade AGP to 8.5.1 or higher

    • Option B: Keep current AGP version + Add configuration

      12345678
      android {
          ...
          packagingOptions {
              jniLibs {
                  useLegacyPackaging true
              }
          }
      }

    Step 3: Rebuild and Verify the App

    After changing the configuration, perform a clean build of your app.

    Step 4: Verify 16KB zipalign Application

    Verify that the built APK/AAB is properly 16KB zipaligned.

    Issue

    When setting android:allowBackup="false", the following build error appears.

    1
    Multiple entries with same key: android:allowBackup=REPLACE and android:allowBackup=REPLACE

    Cause

    This issue may occur due to differences in the Manifest Merger's parsing behavior depending on the version of the Android Gradle Plugin (AGP).

    In certain AGP versions, the parser fails to automatically trim whitespace following a comma (,) when interpreting the tools:replace="..." attribute in AndroidManifest.xml. In this scenario, the string containing the whitespace is incorrectly recognized as a distinct, invalid attribute key. Consequently, the attribute replacement rules may fail to apply, or build errors may occur due to duplicate declarations.

    Solution

    To resolve this issue, remove all spaces within the tools:replace attribute value and perform a Clean Build.