1
votes

I'm trying to pass an object to Broadcastreceiver. The mechanism works well without passing any data, but when I try to pass an object, the program crashes.

This is the code:

public void SetFutureStartTime(int startHour, int startMin)
{
    Context context = this;

    m_alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, AlarmReceiver_BoilerOn.class);

    Bundle args = new Bundle();
    args.putSerializable("tcpClientObj",(Serializable)m_TcpClient);
    intent.putExtra("DATA",args);

    m_alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // --------------> The code crushes here

    // Set the alarm to start at 21:32 PM
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, startHour);
    calendar.set(Calendar.MINUTE, startMin);

    m_alarmMgr.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), m_alarmIntent);
}

This is the Broadcastreceiver implementation:

public class AlarmReceiver_BoilerOn extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {

    Bundle args = intent.getBundleExtra("DATA");
    final TcpClient tcpClient = (TcpClient) args.getSerializable("tcpClientObj");  
}
}

This is the error log:

11-19 19:35:59.553: D/AndroidRuntime(2389): Shutting down VM
11-19 19:35:59.553: D/AndroidRuntime(2389): --------- beginning of crash
11-19 19:35:59.571: E/AndroidRuntime(2389): FATAL EXCEPTION: main
11-19 19:35:59.571: E/AndroidRuntime(2389): Process: boiler.boiler, PID: 2389
11-19 19:35:59.571: E/AndroidRuntime(2389): java.lang.RuntimeException: Parcelable encountered IOException writing

serializable object (name = boiler.boiler.TcpClient) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeSerializable(Parcel.java:1526) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeValue(Parcel.java:1474) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeArrayMapInternal(Parcel.java:723) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Bundle.writeToParcel(Bundle.java:1133) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeBundle(Parcel.java:763) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeValue(Parcel.java:1392) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeArrayMapInternal(Parcel.java:723) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Bundle.writeToParcel(Bundle.java:1133) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeBundle(Parcel.java:763) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.content.Intent.writeToParcel(Intent.java:8655) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3052) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1518) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.app.Activity.startActivityForResult(Activity.java:4224) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.app.Activity.startActivityForResult(Activity.java:4183) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.app.Activity.startActivity(Activity.java:4507) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.app.Activity.startActivity(Activity.java:4475) 11-19 19:35:59.571: E/AndroidRuntime(2389): at boiler.boiler.MainActivity.SetFutureStartTime(MainActivity.java:414) 11-19 19:35:59.571: E/AndroidRuntime(2389): at boiler.boiler.MainActivity$2$3.onClick(MainActivity.java:185) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.view.View.performClick(View.java:5610) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.view.View$PerformClick.run(View.java:22265) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Handler.handleCallback(Handler.java:751) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Handler.dispatchMessage(Handler.java:95) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Looper.loop(Looper.java:154) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.app.ActivityThread.main(ActivityThread.java:6077) 11-19 19:35:59.571: E/AndroidRuntime(2389): at java.lang.reflect.Method.invoke(Native Method) 11-19 19:35:59.571: E/AndroidRuntime(2389): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 11-19 19:35:59.571: E/AndroidRuntime(2389): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 11-19 19:35:59.571: E/AndroidRuntime(2389): Caused by: java.io.NotSerializableException: boiler.boiler.MainActivity$ConnectTask$1 11-19 19:35:59.571: E/AndroidRuntime(2389): at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224) 11-19 19:35:59.571: E/AndroidRuntime(2389): at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584) 11-19 19:35:59.571: E/AndroidRuntime(2389): at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549) 11-19 19:35:59.571: E/AndroidRuntime(2389): at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472) 11-19 19:35:59.571: E/AndroidRuntime(2389): at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218) 11-19 19:35:59.571: E/AndroidRuntime(2389): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346) 11-19 19:35:59.571: E/AndroidRuntime(2389): at android.os.Parcel.writeSerializable(Parcel.java:1521) 11-19 19:35:59.571: E/AndroidRuntime(2389): ... 31 more 11-19 19:35:59.590: W/ActivityManager(1590): Force finishing activity boiler.boiler/.MainActivity

What am I missing?

Thanks.

1

1 Answers

0
votes

If m_TcpClient implements Parcelable interface, your best option is to pass its instance as an Parcelable via the intent Extras. You don't have to cast it to Serializable or Parcelable explicetly. However, keep in mind, that there is a well-known bug with the AlarmManager. It loses the parcelable extras, so instead of passing it directly, you'll have to marshall the data first. Here are some basic methods of doing it:

fun Parcelable.marshall() : ByteArray {
    val parcel = Parcel.obtain()
    writeToParcel(parcel, 0)
    val bytes = parcel.marshall()
    parcel.recycle()
    return bytes
}

fun <T> ByteArray.unmarshall(creator: Parcelable.Creator<T>): T {
    val parcel = unmarshall()
    val result = creator.createFromParcel(parcel)
    parcel.recycle()
    return result
}

private fun ByteArray.unmarshall(): Parcel {
    val parcel = Parcel.obtain()
    parcel.unmarshall(this, 0, size)
    parcel.setDataPosition(0)
    return parcel
}

Using this methods, you can put ByteArray as an intent extra

intent.putExtra(Receiver.EXTRA, m_TcpClient.marshall())

and then get it in the BroadcastReceiver like this:

intent.getByteArrayExtra(EXTRA)?.run {
    val m_TcpClient = unmarshall(TcpClient.CREATOR)
}