We have some code in our app that is using Java and other that is using Kotlin. We have come across a very strange situation.
The problem shows up on some devices, where it reports platform as being null when passing it to the AutoValue_Session constructor despite us checking whether lastPlatform is not null and providing the constant Platform.MISSING otherwise:
Caused by java.lang.NullPointerException: Null lastPlatform
x.x.x.x.AutoValue_Session.(SourceFile:27)
x.x.x.x.Session.from(SourceFile:28) // from that calls the child constructor
x.x.x.x.Session.(SourceFile:22) // whereNONE_FOUND is defined
x.x.x.x.Session.from(SourceFile:32) // entry point
[...]
Anybody has had this issue with Android and Kotlin interop?
Update: This happens in the wild and with a tiny amount of users. Not being able to replicate it locally yet.
Update 2: The second call to Session.from is caused by the <clinit> of Session which is being loaded into memory for the first time.
Here is the code for the two classes mentioned:
Platform.kt
sealed class Platform {
abstract val name : String
sealed class Local : Platform() {
object Default : Local() {
override val name: String = "android"
}
object Amazon : Local() {
override val name: String = "android-amazon"
}
}
object Missing : Platform() {
override val name: String = "missing"
}
data class Remote(override val name: String) : Platform()
companion object {
@JvmName("from")
@JvmStatic
operator fun invoke(name: String?): Platform = when (name) {
Local.Default.name -> Local.Default
Local.Amazon.name -> Local.Amazon
Missing.name -> Missing
null -> Missing
else -> Remote(name)
}
@JvmField
val LOCAL : Platform = if (BuildConfig.amazon) Local.Amazon else Local.Generic
@JvmField
val MISSING : Platform = Missing
}
}
Session.java
@AutoValue
public abstract class Session implements Serializable {
public static final Session NONE_FOUND = from(0, new DateTime(0), Platform.MISSING);
public static Session from(String id, @Nullable Platform lastPlatform) {
Platform platform = lastPlatform == null ? Platform.MISSING : lastPlatform;
return new AutoValue_Session(id, platform);
}
public static Session from(RemoteSession remote) {
return from(
remote.id(),
remote.lastPlatform()
);
}
public abstract String id();
public abstract Platform lastPlatform();
}