Skip to main content

AppTrove SDK Flutter FAQ

This FAQ addresses common issues encountered when integrating the AppTrove SDK into Flutter applications for Android, focusing on build errors and release build issues. Each issue includes detailed explanations and solutions, including build configuration changes and ProGuard rules where applicable.


1. Why does the build fail with an "Inconsistent JVM-target compatibility" error when integrating the AppTrove SDK in Flutter?

Issue: The build fails with the following error:

Execution failed for task ':trackier_sdk_flutter:compileDebugKotlin'.
> Inconsistent JVM-target compatibility detected for tasks 'compileDebugJavaWithJavac' (1.8) and 'compileDebugKotlin' (17).

Cause: This error occurs due to a mismatch between the Java and Kotlin JVM target versions. The compileDebugJavaWithJavac task uses Java 1.8, while the compileDebugKotlin task targets JVM 17, leading to incompatibility.

Solution: Update the Android build.gradle file for the trackier_sdk_flutter module to align the Java and Kotlin JVM targets to version 17. Add the following configuration:

android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

kotlin {
jvmToolchain(17)
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}

Explanation:

  • compileOptions: Sets the Java source and target compatibility to Java 17, ensuring consistency with the Kotlin compiler.
  • kotlin { jvmToolchain(17) }: Configures the Kotlin compiler to target JVM 17.
  • sourceSets: Adds the src/main/kotlin directory to the source sets, ensuring Kotlin files are correctly included in the build.

Additional Steps:

  • Ensure the project's Kotlin version is compatible with JVM 17. Update the Kotlin plugin in the project-level build.gradle:
buildscript {
ext.kotlin_version = '1.9.0' // Use a version compatible with JVM 17
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

  • Clean and rebuild the project:
flutter clean
flutter pub get
flutter build apk


2. Why does the AppTrove SDK stop sending requests to the Apptrove server in Flutter release builds?

Issue: In release builds of the Flutter app, the AppTrove SDK fails to send requests to the Apptrove server, causing tracking features (e.g., installs, events) to stop functioning.

Cause: When building a release APK with ProGuard or R8 enabled (via minifyEnabled true), the obfuscation process may strip or rename critical classes used by the AppTrove SDK, particularly those related to Kotlin metadata and reflection. This prevents the SDK from making network requests.

Solution: Add the following ProGuard rules to the android/app/proguard-rules.pro file to preserve the necessary classes:

# Ensure that Map adapters and Kotlin classes are preserved
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.jvm.internal.** { *; }
-keep class kotlin.** { *; }
-keep class com.trackier.sdk.** { *; }
-dontwarn kotlin.**
-dontwarn com.trackier.sdk.**

Explanation:

  • -keep class kotlin.Metadata { *; }: Preserves Kotlin metadata required for reflection.
  • -keep class kotlin.reflect.jvm.internal.** { *; }: Ensures internal Kotlin reflection classes are not removed.
  • -keep class kotlin.** { *; }: Preserves all Kotlin classes to avoid issues with SDK dependencies.
  • -keep class com.trackier.sdk.** { *; }: Prevents obfuscation of AppTrove SDK classes.
  • -dontwarn kotlin.** and -dontwarn com.trackier.sdk.**: Suppresses warnings for Kotlin and AppTrove SDK classes that may not be directly referenced but are required at runtime.

Additional Steps:

  1. Enable ProGuard in Release Builds: Ensure ProGuard is enabled in the android/app/build.gradle file:
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

  1. Test the Release Build: Generate a release APK and test it in a staging environment to confirm that requests are sent to the Apptrove server:
flutter build apk --release

  1. Enable Debugging: If the issue persists, enable debug logging in the AppTrove SDK (refer to the SDK documentation) to identify the root cause of failed requests.

3. How do I ensure compatibility with Kotlin-based dependencies in the AppTrove SDK for Flutter?

Issue: The AppTrove SDK relies on Kotlin, and conflicts may arise if the Flutter app's Android module uses an incompatible Kotlin version or if ProGuard removes critical Kotlin classes.

Solution:

  1. Use a Compatible Kotlin Version: Ensure the Kotlin version in the Android module is compatible with the AppTrove SDK. Update the project-level build.gradle:
buildscript {
ext.kotlin_version = '1.9.0' // Use the version specified by AppTrove SDK
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

  1. Add ProGuard Rules for Kotlin: Include the following rules in android/app/proguard-rules.pro to prevent issues with Kotlin reflection and metadata:
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.jvm.internal.** { *; }
-dontwarn kotlin.**

  1. Verify Gradle Configuration: Ensure the trackier_sdk_flutter module's build.gradle includes the Kotlin plugin and compatible settings:
apply plugin: 'kotlin-android'

android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

kotlin {
jvmToolchain(17)
}
}

  1. Test Thoroughly: Test the app in both debug and release builds to ensure Kotlin-based features (e.g., coroutines, reflection) work correctly with the AppTrove SDK.

4. How do I troubleshoot other AppTrove SDK integration issues in Flutter?

General Troubleshooting Steps:

  1. Check SDK Version: Ensure you are using the latest version of the AppTrove SDK for Flutter. Update the dependency in pubspec.yaml:
dependencies:
trackier_sdk_flutter: ^latest_version

  1. Verify ProGuard Rules: Confirm that all recommended ProGuard rules are included in android/app/proguard-rules.pro.
  2. Enable Logging: Enable debug logging in the AppTrove SDK to identify issues. Refer to the SDK's documentation for enabling verbose logs.
  3. Test in Staging: Test the SDK in a release build with minifyEnabled true to replicate production conditions:
flutter build apk --release

  1. Check Network Permissions: Ensure the app has the necessary permissions (e.g., INTERNET) in android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />

  1. Contact Support: If issues persist, contact AppTrove SDK support with the following details:
    • SDK version
    • Flutter version
    • Kotlin version
    • Stack trace (if applicable)
    • ProGuard rules used
    • Build configuration (minifyEnabled, shrinkResources)

Additional Resources

  • AppTrove SDK Documentation: Refer to the official AppTrove SDK documentation for Flutter integration steps.
  • Flutter Documentation: Visit flutter.dev for guidance on building and optimizing Flutter apps.
  • ProGuard Documentation: Learn more about ProGuard rules at proguard.sourceforge.io.

For complete documentation, visit the Trackier Developer Portal.


5. Why does my Flutter app crash on Android 7 due to GMS (Google Mobile Services)?

Issue: The Flutter app crashes on Android 7 devices with the following error:

Caused by java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Duration;
at com.google.android.gms.ads.identifier.zzd.<clinit>(zzd.java)
at com.google.android.gms.ads.identifier.zzd.zza(zzd.java)
at com.google.android.gms.ads.identifier.AdvertisingIdClient.getAdvertisingIdInfo(AdvertisingIdClient.java)
at java.lang.reflect.Method.invoke(Method.java)
at com.trackier.sdk.DeviceInfo$Companion.getGAID(DeviceInfo.java)
at com.trackier.sdk.TrackierSDKInstance.initGaid(SourceFile)
at com.trackier.sdk.TrackierSDKInstance.access$initGaid(SourceFile)
at com.trackier.sdk.TrackierSDKInstance$initialize$1.invokeSuspend(TrackierSDKInstance.java)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(BaseContinuationImpl.java)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.java:1)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.java:1)
at kotlinx.coroutines.scheduling.TaskImpl.run(TaskImpl.java:1)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:1)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.java:1)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.java:1)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.java:1)

Cause: This error occurs because Android 7 (API level 24) doesn't natively support the java.time.Duration class, which was introduced in Android 8 (API level 26). The Google Mobile Services (GMS) library tries to use this class, causing a NoClassDefFoundError.

Solution: Add the following dependency to your android/app/build.gradle file:

android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
// Add this dependency:
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
}
}

dependencies {
// Add this dependency:
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
}

Explanation: The coreLibraryDesugaring dependency provides backported versions of Java 8+ APIs (including java.time.Duration) for older Android versions, allowing the GMS library to work properly on Android 7 devices.