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 theBackgroundWorker
class 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.pro
file:
-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.kt
at line 42, check if the class name needs to be updated. Renaming or ensuring compatibility with the expectedWorker
class 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.pro
file 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
minifyEnabled
is set totrue
in yourbuild.gradle
file to enable code shrinking and obfuscation. Combine this withshrinkResources true
to 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 true
is set in yourbuild.gradle
file, and include theandroidx.multidex:multidex
dependency 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
-dontwarn
rules suppress warnings for unused Kotlin reflection classes, reducing the risk of ProGuard including unnecessary code. - The
-keep
rules 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.gradle
accordingly:
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.gradle
dependency:
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 true
to 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.