I have a strange issue.
I have this kotlin piece of code that sorts a dictionary, inside my multidix mixed java-kotlin application. (code below)
when running the app on development phone (SAMSUNG s9) everything runs ok. When deployed the app to Fabric's "beta", a big portion (50%) of the users are having crashes of type NoClassDefFoundError
. The affected phones include xioami's MI 5s and Red-mi phones and multiple types of onePlus phones
I tried to look at the output apk (via build -> Analyze APK) and made sure the class is, indeed, there. As you can see from - that the class is actually on the main "classes.dex" file.
Any help will be much appreciated!
log file:
... (custom logging from the app on initiation level)
09-09 13:04:31.667 17365-17365/com.example.orcam.basic_recognition_app I/art: Rejecting re-init on previously-failed class
java.lang.Class<com.example.orcam.logic_myme.ComputedData.ComputedPersonData$calculateMeetingsForPerson$2>
... (custom logging from the app on normal run level)
09-09 13:04:31.762 17365-17365/com.example.orcam.basic_recognition_app E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.orcam.basic_recognition_app, PID: 17365
java.lang.NoClassDefFoundError: com.example.orcam.logic_myme.ComputedData.ComputedPersonData$calculateMeetingsForPerson$2
at com.example.orcam.logic_myme.ComputedData.ComputedPersonData.calculateMeetingsForPerson(ComputedPersonData.kt:45) at com.example.orcam.logic_myme.ComputedData.ComputedData.calculate(ComputedData.kt:7) at com.example.orcam.logic_myme.db.DBManager$init$2.onDbInitAndReady(DBManager.kt:79) at com.example.lib_sync.sync.SyncManager2.(SyncManager2.java:63) at com.example.orcam.logic_myme.db.DBManager.init(DBManager.kt:76) at com.example.orcam.basic_recognition_app.LogicManager.init(LogicManager.java:58) at com.example.orcam.basic_recognition_app.MyMeApplication.initManagers(MyMeApplication.kt:31) at com.example.orcam.basic_recognition_app.MyMeApplication.onCreate(MyMeApplication.kt:13) at android.app. Instrumentation.callApplicationOnCreate(Instrumentation.java:1014) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4782) at android.app.ActivityThread.access$1700(ActivityThread.java:153) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1445) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:5544) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629) 09-09 13:04:31.763 17365-17365/com.example.orcam.basic_recognition_app E/MQSEventManagerDelegate: failed to get MQSService.
build.gradle file:
buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
google()
}
dependencies {
classpath 'io.fabric.tools:gradle:1.+'
}
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
repositories {
maven { url 'https://maven.fabric.io/public' }
google()
}
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.example.orcam.basic_recognition_app"
minSdkVersion 21
targetSdkVersion 27
versionCode 29
versionName "5.0.9"
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
beta {
initWith debug
applicationIdSuffix ""
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
pickFirst 'META-INF/LICENSE'
pickFirst 'META-INF/DEPENDENCIES'
pickFirst 'META-INF/ASL-2.0.txt'
pickFirst 'META-INF/LGPL-3.0.txt'
exclude 'META-INF/main.kotlin_module'
}
dexOptions {
preDexLibraries = false
}
}
ext {
supportLibVersion = '27.1.1'
}
dependencies {
/* ... a lot of dependencies ... */
// multi dex
implementation 'com.android.support:multidex:1.0.3'
// kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
kapt {
generateStubs = true
}
ComputedPersonData.kt file (simplified version with only the "bad" function):
class ComputedPersonData() {
var meetingsByPerson = mapOf<String, ArrayList<String>>()
fun calculateMeetingsForPerson() {
val faces: Map<String: Face?> = getFaces()
val faceToContact: Map<String: String?> = getMapping()
val peopleWithFaces = mutableMapOf<String, ArrayList<Face>>()
faces.values.forEach {
if (it != null) {
val personId = faceToContact[it.imageId] ?: ""
val list = peopleWithFaces[personId] ?: run {
peopleWithFaces[personId] = arrayListOf(it)
return@forEach
}
list.add(it)
}
}
val dictSorted = mutableMapOf<String, ArrayList<Face>>()
peopleWithFaces.forEach { id, item ->
dictSorted[id] = ArrayList(item.sortedBy { it.timestamp })
}
// the "dictSorted.mapValues{}" generates the "bad" $2 class
val dictFaceToString: Map<String, ArrayList<String>> = dictSorted.mapValues {
ArrayList(it.value.map {
it.id
}
)
}
this.meetingsByPerson = dictFaceToString
}
}
application class:
class MyApplication : MultiDexApplication()
well, after MONTHS of investigation apparently the bad lines were -
peopleWithFaces.forEach { id, item ->
dictSorted[id] = ArrayList(item.sortedBy { it.timestamp })
}
There was an issue with old android-OS (6.0.0 specific) and kotlin's decoupled for-each
.
Once the problem found, the solution was easy. All we needed to do was to re-write this fun like that:
peopleWithFaces.forEach {
val id = it.key
val item = it.value
dictSorted[id] = ArrayList(item.sortedBy { it.timestamp })
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.