0

I have a strange crash on both the Genymotion Android simulator and my Huawei Nexus 6P. I have a screenshot that I am sending to another Anko Component successfully - obviously it is Parcelable:

@Parcelize
data class ColourBoardScreenShot(var screenshot: @RawValue BitmapDrawable) : Parcelable

However, if I take the screenshot and anytime later quit the app by pressing the circle button at the bottom of the screen the app crashes with the following stack trace:

FATAL EXCEPTION: main
Process: uk.co.davechambers.pegboard, PID: 2292
java.lang.RuntimeException: Parcel: unable to marshal value
android.graphics.drawable.BitmapDrawable@4cdb04c
at android.os.Parcel.writeValue(Parcel.java:1477)
at uk.co.davechambers.pegboard.models.ColourBoardScreenShot.writeToParcel(ColourBoardScreenShot.kt:0)
at android.os.Parcel.writeParcelable(Parcel.java:1496)
at android.os.Parcel.writeValue(Parcel.java:1402)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:724)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1157)
at android.os.Parcel.writeBundle(Parcel.java:764)
at android.support.v4.app.FragmentState.writeToParcel(Fragment.java:154)
at android.os.Parcel.writeTypedArray(Parcel.java:1307)
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:617)
at android.os.Parcel.writeParcelable(Parcel.java:1496)
at android.os.Parcel.writeValue(Parcel.java:1402)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:724)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1157)
at android.os.Parcel.writeBundle(Parcel.java:764)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3633)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3773)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Can anyone tell me where I'm going wrong?

EDIT:

If I try and replace the ColourBoardScreenShot by using a plugin to generate the Parcelize code I get Unresolved reference on read and write:

data class ColourBoardScreenShot(var screenshot: @RawValue BitmapDrawable) : Parcelable {
constructor(source: Parcel) : this(
        source.read[@kotlinx.android.parcel.RawValue] BitmapDrawable ()
)

override fun describeContents() = 0

override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {
    write[@kotlinx.android.parcel.RawValue] BitmapDrawable (screenshot)
}

companion object {
    @JvmField
    val CREATOR: Parcelable.Creator<ColourBoardScreenShot> = object : Parcelable.Creator<ColourBoardScreenShot> {
        override fun createFromParcel(source: Parcel): ColourBoardScreenShot = ColourBoardScreenShot(source)
        override fun newArray(size: Int): Array<ColourBoardScreenShot?> = arrayOfNulls(size)
    }
}
}
Dave Chambers
  • 2,483
  • 2
  • 32
  • 55
  • What makes you say “even though that data was successfully Parcelized”? How do you know? It sure looks like parceling does not succeed. – Ben P. Feb 12 '18 at 15:43
  • @Ben P The data is an image and that image is passed to another view successfully. The problem occurs when the app is quit – Dave Chambers Feb 12 '18 at 16:01
  • How do you pass it to the other view? Parceling in Android involves a number of shortcuts in situations where no IPC needs to be done. For instance, if you put a `Parcelable` object into an activity's `onSaveInstanceState()` bundle and then rotate your device you will find that you can successfully retrieve that `Parcelable` object from the `savedInstanceState` bundle even though it was never actually parceled. I suspect that hitting the phone's home button is the first time your object actually tries to serialize itself into a Parcel. – Ben P. Feb 12 '18 at 16:14
  • @BenP.I just put it in the bundle `bundle.putParcelable ("screenshot", screenShot)` then retrieve it in the other view. – Dave Chambers Feb 12 '18 at 16:29
  • Chances are very good that the system isn't actually serializing the data in that case, and is instead simply keeping it in-memory since you're working within the same process. I know the whole point of `@Parcelize` is that you don't have to manually write out the parceling code, but you can try to intentionally write bad parceling code for this class (maybe just throw an exception) and see if the bundle still works. I suspect it will. – Ben P. Feb 12 '18 at 17:35
  • @BenP.Thanks for the help. I fixed the problem. – Dave Chambers Feb 12 '18 at 17:49

1 Answers1

0

I changed my ColourBoardScreenShot to the following:

@Parcelize
data class ColourBoardScreenShot(var screenshot: ByteArray) : Parcelable

So instead of @RawValue BitmapDrawable I use ByteArray and the crash stopped.

Dave Chambers
  • 2,483
  • 2
  • 32
  • 55