I start an Intent with some extras and read the passed extras in the Activity's onCreate
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val extras: Bundle? = intent.extras // <-- crash
val someInt = extras?.getInt(EXTRA_SOME_INT, -1) ?: -1
// ...
}
companion object {
const val EXTRA_SOME_INT = "someInt"
fun createIntent(context: Context, someInt: Int) =
Intent(context, MyActivity::class.java).apply {
putExtra(EXTRA_SOME_INT, someInt)
}
}
}
// Activity started like this:
fun startMyActivity(context: Context) {
context.startActivity(MyActivity.createIntent(context, 1234))
}
This works fine, however, in production, the marked line sometimes causes the app to crash when getExtras()
is called. According to documentation it can be nullable, but it shouldn't throw an exception.
The crashlog is not always the same, but either this happens in BaseBundle
:
java.lang.NullPointerException
Attempt to invoke virtual method 'int android.os.Parcel.dataSize()' on a null object reference
BaseBundle.java line 164 in android.os.BaseBundle.<init>()
Bundle.java line 106 in android.os.Bundle.<init>()
Intent.java line 6580 in android.content.Intent.getExtras()
... or this happens:
java.lang.IllegalArgumentException
Duplicate key in ArrayMap:
BaseBundle.java line 126 in android.os.BaseBundle.<init>()
Bundle.java line 102 in android.os.Bundle.<init>()
Intent.java line 5756 in android.content.Intent.getExtras()
The crash happens only on Android 5, 6 or 7. I haven't found a way to reproduce it on my own device.
Is there something I do wrong, or what would be the best way to avoid this crash? Without the extra bundle, I cannot display my Activity.
This was a bug in AOSP which was fixed after Android 7. Here is the reason in the commit message:
Fix for race in writeToParcel and unparcel
Don't access the parcelled data while it might be recycled by another thread.
Also make a local reference of mMap, which could be modified by another thread.