Mark Kuczmarski
Mark Kuczmarski

Reputation: 173

Pass Serializable Object to Pending Intent

I am trying to send a serializable object to a pending Intent. The problem is the alarm being received is returning as null. Even though the Alarm implements the serializable interface.

//AlarmService.java

Intent myIntent = new Intent(getApplicationContext(), AlarmAlertBroadcastReciever.class);
Bundle bundle = new Bundle();
bundle.putSerializable("alarm", alarm);
myIntent.putExtras(bundle);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);

AlarmManager alarmManager = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);

alarmManager.set(AlarmManager.RTC_WAKEUP, alarm.getAlarmTime().getTimeInMillis(), pendingIntent);

The alarm being received is null.

//AlarmAlertBroadcastReceiver.java

public class AlarmAlertBroadcastReciever extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Alarm alarm = (Alarm)intent.getExtras().getSerializable("alarm");
    }
}

Edit: Some more things I've tried is as follows, but it doesn't seem to work:

//AlarmService.java

Intent myIntent = new Intent(getApplicationContext(), AlarmAlertBroadcastReciever.class);
myIntent.putExtra("alarm", alarm);
myIntent.setAction("abc.xyz");

PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager alarmManager = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);

alarmManager.set(AlarmManager.RTC_WAKEUP, alarm.getAlarmTime().getTimeInMillis(), pendingIntent);

The alarm being received is null.

//AlarmAlertBroadcastReceiver.java

public class AlarmAlertBroadcastReciever extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Alarm alarm = (Alarm)intent.getExtras().getSerializable("alarm");
      //Alarm alarm = (Alarm)intent.getSerializableExtra("alarm");
    }
}

Upvotes: 8

Views: 4478

Answers (7)

Mark Kuczmarski
Mark Kuczmarski

Reputation: 173

I am using android Nougat so none of these answers quite worked. I ended up passing the objects in a byte array.

//AlarmService.java

Intent myIntent = new Intent(getApplicationContext(), AlarmAlertBroadcastReciever.class);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
    out = new ObjectOutputStream(bos);
    out.writeObject(alarm);
    out.flush();
    byte[] data = bos.toByteArray();
    myIntent.putExtra("alarm", data);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        bos.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);

AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, alarm.getAlarmTime().getTimeInMillis(), pendingIntent);

Then I received the Byte[]

//AlarmAlertBroadcastReceiver.java

@Override
public void onReceive(Context context, Intent intent) {
   ByteArrayInputStream bis = new ByteArrayInputStream(intent.getByteArrayExtra("alarm"));
    ObjectInput in = null;
    Alarm alarm = null;
    try {
        in = new ObjectInputStream(bis);
        alarm = (Alarm)in.readObject();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (in != null) {
                in.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Upvotes: 3

David Wasser
David Wasser

Reputation: 95626

There are known issues with putting custom objects into an Intent that is then passed to AlarmManager or NotificationManager or other external applications. You can try to wrap your custom object in a Bundle, as this will sometimes work. For example, change your code to:

Intent myIntent = new Intent(getApplicationContext(), 
                             AlarmAlertBroadcastReciever.class);
Bundle bundle = new Bundle();
bundle.putSerializable("alarm", alarm);
myIntent.putExtra("bundle", bundle);

and in AlarmAlertBroadcastReciever.onReceive():

Bundle bundle = intent.getBundleExtra("bundle");
if (bundle != null) {
    Alarm alarm = (Alarm)bundle.getSerializable("alarm");
}

If this does not work (and this should work on most Android versions/devices, but not all, especially very new ones), you will need to convert your Serializeable object into a byte[] and put the byte[] into the extras.

There are dozens of examples of how to do that on Stackoverflow.

Upvotes: 20

Nas
Nas

Reputation: 2198

Have you tried with any other request id other than 0

for eg

int requestID = (int) System.currentTimeMillis();

PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), requestID , myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

 public void onReceive(Context context, Intent intent) {

        if(intent!=null && intent.hasExtra("alarm")){
        Alarm alarm = (Alarm)intent.getExtras().getSerializable("alarm");
        }

    }

Upvotes: -1

Kingfisher Phuoc
Kingfisher Phuoc

Reputation: 8200

There are 2 things I want to suggest:

  1. You need to set Action to your intent, such as: yourIntent.setAction("abc.xyz")
  2. You should use FLAG_UPDATE_CURRENT instead of FLAG_CANCEL_CURRENT

Hope it helps.

Upvotes: 0

vikas kumar
vikas kumar

Reputation: 11018

It's a suggestion, you can try parcelabler which is more efficient and tailored for android specific needs. so get your model class parceled here. after that paste in into your project and then pass it to another activity using either bundle

bundle.putParcelable(KEY_PARCEL, detailModelsList.get(position));

or

intent.putParcelableArrayListExtra("Parcelaber",myList);

Upvotes: 0

Mr. Borad
Mr. Borad

Reputation: 391

You have putSerializable in Bundle. And you are try to getSerializable from intent.

For set : `myIntent.putExtra("alarm", alarm);` 
For get : `(Alarm)intent.getExtras().getSerializableExtra("alarm");` 
Also make sure your `Alarm` calss have `implements` with `Serializable`.

try that.

Upvotes: 0

IMXQD
IMXQD

Reputation: 341

Intent putExtra (String name, Parcelable value)

Add extended data to the intent. The name must include a package prefix, for example the app com.android.contacts would use names like "com.android.contacts.ShowAll".

Reference

Upvotes: 0

Related Questions