AppTrove SDK Android FAQ
This FAQ addresses common issues encountered when integrating the AppTrove SDK into Android applications, focusing on crashes, app size increases, and build configuration problems. Each issue includes detailed explanations and solutions, including ProGuard rules where applicable.
1. Why does my app crash with a ClassCastException in DaggerWorkerFactory when using the AppTrove SDK?
Issue: The app crashes with the following stack trace:
FATAL EXCEPTION: WM.task-4 (Ask Gemini)
Process: com.ultrajhakaas.android, PID: 28083
java.lang.ClassCastException: class com.trackier.sdk.BackgroundWorker cannot be cast to androidx.work.Worker
at java.lang.Class.asSubclass(Class.java:4229)
at com.mobiotics.vlive.android.worker.DaggerWorkerFactory.createWorker(DaggerWorkerFactory.kt:42)
at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:82)
Cause: This occurs due to a mismatch between the expected androidx.work.Worker class and the AppTrove SDK's BackgroundWorker class, often caused by incorrect class casting in the dependency injection setup or ProGuard rules stripping necessary classes.
Solution:
- Ensure the AppTrove SDK is correctly integrated with
WorkManager. Verify that theBackgroundWorkerclass extendsandroidx.work.Worker. - If the issue persists, it may be due to ProGuard optimizations removing necessary classes. Add the following ProGuard rules to your
proguard-rules.profile:
-keep class com.trackier.sdk.BackgroundWorker { *; }
-keep class androidx.work.Worker { *; }
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.jvm.internal.** { *; }
-dontwarn kotlin.**
- If the crash occurs in
DaggerWorkerFactory.ktat line 42, check if the class name needs to be updated. Renaming or ensuring compatibility with the expectedWorkerclass can resolve this issue.
2. Why do the install and event features of the AppTrove SDK stop working in release builds?
Issue: When switching from a debug to a release build with minifyEnabled and shrinkResources enabled, the AppTrove SDK's install and event tracking features stop functioning.
Cause: ProGuard or R8 optimizations in release builds may strip or obfuscate classes required by the AppTrove SDK, particularly those related to Kotlin reflection or metadata. This can interfere with the SDK's ability to process installs and events.
Solution:
Add the following ProGuard rules to your proguard-rules.pro file to preserve the necessary classes:
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.jvm.internal.** { *; }
-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 com.trackier.sdk.** { *; }: Preserves all AppTrove SDK classes to prevent obfuscation.-dontwarn: Suppresses warnings for Kotlin and AppTrove SDK classes that may not be directly referenced but are required at runtime.
Additionally, ensure that minifyEnabled and shrinkResources are tested thoroughly in a staging environment before releasing to production.
3. Why does the app size increase by 200 KB to 1 MB after integrating the AppTrove SDK?
Issue: After integrating the AppTrove SDK, the APK size increases significantly, often by 200 KB to 1 MB.
Cause: The AppTrove SDK includes dependencies like the Kotlin Standard Library, Kotlin Reflection, and other libraries that contribute to the increased size. If your app already uses Kotlin, the SDK's inclusion of these dependencies may result in duplicated or unnecessarily large libraries.
Solution:
To minimize the size increase, optimize your app with the following steps:
- Review Dependencies: The AppTrove SDK includes the following dependencies, contributing to the size:
| Dependency | Size | Notes |
|---|---|---|
org.jetbrains.kotlin:kotlin-stdlib | ~1.5 MB | Kotlin Standard Library |
org.jetbrains.kotlin:kotlin-reflect | ~2.5 MB | Kotlin Reflection Library |
androidx.annotation:annotation | ~20 KB | Lightweight annotations |
org.jetbrains.kotlinx:kotlinx-coroutines-core | ~300 KB | Coroutines core library |
androidx.work:work-runtime-ktx | ~500 KB | WorkManager with Kotlin extensions |
com.squareup.moshi:moshi-kotlin | ~200 KB | Moshi JSON library |
com.squareup.moshi:moshi-kotlin-codegen | ~50 KB | Moshi codegen (compile-time only) |
com.android.installreferrer:installreferrer | ~50 KB | Google Play Install Referrer |
com.miui.referrer:homereferrer | ~50 KB | Xiaomi Install Referrer |
androidx.multidex:multidex | ~100 KB | Multidex support (if >64K methods) |
com.squareup.retrofit2:retrofit | ~100 KB | Retrofit networking |
com.squareup.retrofit2:converter-moshi | ~50 KB | Retrofit Moshi converter |
- Apply ProGuard Rules: Add the following rules to your
proguard-rules.profile to strip unused classes and reduce the APK size:
-dontwarn kotlin.reflect.jvm.**
-dontwarn kotlin.reflect.full.**
-dontwarn kotlin.reflect.jvm.KCallablesJvm
-dontwarn kotlin.reflect.full.KClasses
-dontwarn kotlin.reflect.jvm.internal.**
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.jvm.internal.** { *; }
-keep class com.trackier.sdk.** { *; }
-dontwarn kotlin.**
-dontwarn com.trackier.sdk.**
-keep class kotlin.** {
public protected *;
}
- Enable R8 Optimizations: Ensure
minifyEnabledis set totruein yourbuild.gradlefile to enable code shrinking and obfuscation. Combine this withshrinkResources trueto remove unused resources.
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
-
Consider Multidex: If your app exceeds 64K methods, ensure
multiDexEnabled trueis set in yourbuild.gradlefile, and include theandroidx.multidex:multidexdependency only if necessary. -
Analyze APK: Use Android Studio's APK Analyzer to identify which libraries contribute the most to the size and optimize accordingly.
Explanation:
- The
-dontwarnrules suppress warnings for unused Kotlin reflection classes, reducing the risk of ProGuard including unnecessary code. - The
-keeprules ensure essential Kotlin and AppTrove SDK classes are preserved. - Enabling R8 and resource shrinking removes unused code and resources, mitigating the size increase caused by the SDK's dependencies.
4. How do I ensure compatibility with Kotlin-based dependencies in the AppTrove SDK?
Issue: The AppTrove SDK heavily relies on Kotlin, and conflicts may arise if your app uses a different Kotlin version or if ProGuard removes critical Kotlin classes.
Solution:
- Use Compatible Kotlin Versions: Ensure your app's Kotlin version is compatible with the AppTrove SDK. Check the SDK's documentation for the required Kotlin version and update your
build.gradleaccordingly:
buildscript {
ext.kotlin_version = '1.9.0' // Use the version specified by AppTrove SDK
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
- Add ProGuard Rules for Kotlin: To prevent issues with Kotlin's reflection and metadata, include the following rules in
proguard-rules.pro:
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.jvm.internal.** { *; }
-dontwarn kotlin.**
- Test Thoroughly: Test your app in both debug and release builds to ensure that Kotlin-based features (e.g., coroutines, reflection) work correctly with the AppTrove SDK.
5. How do I troubleshoot other AppTrove SDK integration issues?
General Troubleshooting Steps:
- Check SDK Version: Ensure you are using the latest version of the AppTrove SDK. Update your
build.gradledependency:
dependencies {
implementation 'com.trackier:android-sdk:1.6.68'
}
- Verify ProGuard Rules: Double-check that all recommended ProGuard rules are included in
proguard-rules.pro. - Enable Logging: Enable debug logging in the AppTrove SDK to identify issues. Refer to the SDK's documentation for enabling verbose logs.
- Test in Staging: Test the SDK in a staging environment with
minifyEnabled trueto replicate release build conditions. - Contact Support: If issues persist, contact AppTrove SDK support with the following details:
- SDK version
- App's 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 detailed integration steps.
- ProGuard Documentation: Learn more about ProGuard rules at proguard.sourceforge.io.
- Android Developer Guide: Visit developer.android.com for guidance on optimizing APK size and configuring WorkManager.
For complete documentation, visit the Trackier Developer Portal.
6. Why does my app crash on Android 7 due to GMS (Google Mobile Services)?
Issue: The 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 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.