getParcelableExtra always null on Pending Intent,

2019-07-28 16:21发布

I'm new to Java let alone Android development. I have no coding background, but thought I'd start with something 'simple' like an alarm clock. So now I'm writing an alarm clock, and I want to update the alarms to be inactive if they aren't repeating after they go off. When I pass a parcelable AlarmClass (my alarm object) to the alarm set screen with an intent, it passes just fine. When I pass the same AlarmClass to an intent, and put it in a PendingIntent in the Alarm Manager and then try to get it from the screen where you can dismiss the alarm, the AlarmClass object that I'm calling and populating the exact same way is always null.

Here's my alarm class:

package com.example.wakeme;

import java.util.Calendar;

import android.os.Parcel;
import android.os.Parcelable;

public class AlarmClass implements Parcelable{
    Calendar cal = Calendar.getInstance();
    private long id = 1;
    private int active = 1;
    private long time = cal.getTimeInMillis();
    private int repeating = 0;
    private int skipweekends = 0;
    private int skipweekdays = 0;
    private int alarmnumber = -1;


    public long getId(){
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public int getActive(){
        return active;
    }

    public void setActive(int active) {
        this.active = active;
    }

    public int getRepeating(){
        return repeating;
    }

    public void setRepeating(int repeating){
        this.repeating = repeating;
    }

    public void setTime(long time){
        this.time = time;
    }

    public long getTime(){
        return time;
    }

    public int getSkipWeekends(){
        return skipweekends;
    }

    public void setSkipWeekends(int skipweekends){
        this.skipweekends = skipweekends;
    }

    public int getSkipWeekdays(){
        return skipweekdays;
    }

    public void setSkipWeekdays(int skipweekdays){
        this.skipweekdays = skipweekdays;
    }

    public void setAlarmNumber(int alarmnumber){
        this.alarmnumber = alarmnumber;
    }

    public int getAlarmNumber(){
        return alarmnumber;
    }

    @Override
    public int describeContents(){
        return 0;
    }

    private AlarmClass(Parcel in){
        this.id = in.readLong();
        this.active = in.readInt();
        this.repeating = in.readInt();
        this.skipweekdays = in.readInt();
        this.skipweekends = in.readInt();
        this.time = in.readLong();
        this.alarmnumber = in.readInt();
    }

    AlarmClass() {
        return;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeLong(this.id);
        out.writeInt(this.active);
        out.writeInt(this.repeating);
        out.writeInt(this.skipweekdays);
        out.writeInt(this.skipweekends);
        out.writeLong(this.time);
        out.writeInt(this.alarmnumber);
    }

    public static final Parcelable.Creator<AlarmClass> CREATOR = new Parcelable.Creator<AlarmClass>(){
        public AlarmClass createFromParcel(Parcel in){
            return new AlarmClass(in);
        }
        public AlarmClass[] newArray(int size) {
            return new AlarmClass[size];
        }
    };

From here, I can pass my object to an alarm setter to update it just fine:

public void startSet(View view){
        Intent set = new Intent(this, SetAlarm.class);
        set.putExtra("alarm", new AlarmClass());
        startActivity(set);
    }

And I recieve it on my time setter right here just fine. It's non-null:

public class SetAlarm extends MainActivity {
    AlarmClass passAlarm = new AlarmClass();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.alarm_set);
        setAlarmSetListener();
        setDeleteListener();
        passAlarm = (AlarmClass) getIntent().getParcelableExtra("alarm");
        if(passAlarm.getAlarmNumber() != -1){
            TimePicker picker = (TimePicker) findViewById(R.id.timePicker1);
            Calendar passedTime = Calendar.getInstance();
            passedTime.setTimeInMillis(passAlarm.getTime());
            picker.setCurrentHour(passedTime.get(Calendar.HOUR_OF_DAY));
            picker.setCurrentMinute(passedTime.get(Calendar.MINUTE));
            String ampm = (passedTime.get(Calendar.HOUR_OF_DAY) > 12 ? "pm" : "am");
            String message = "Passed Time is: " + (passedTime.get((Calendar.HOUR_OF_DAY)%12)!=0?(passedTime.get(Calendar.HOUR_OF_DAY)%12):12) + ":" + passedTime.get(Calendar.MINUTE) + " " + ampm;
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
        }
        else{
        // Do Nothing
        }

    }

But when sent via PendingIntent as so:

private void newAlarm(AlarmClass alarmclass){
        Intent intent = new Intent(getBaseContext(), Alarm.class);
        intent.putExtra("alarm", alarmclass);
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(alarmclass.getTime());
        AlarmsDataSource alarm =  new AlarmsDataSource(this);
        alarm.open();
        AlarmClass alarmObject = new AlarmClass();
        alarmObject = alarm.createAlarm(true, cal.getTimeInMillis(), false, false, false);
        PendingIntent torpedo = PendingIntent.getBroadcast(this,alarmObject.getAlarmNumber(),intent,PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager goOff = (AlarmManager) getSystemService(ALARM_SERVICE);
        goOff.set(AlarmManager.RTC_WAKEUP, alarmObject.getTime() ,torpedo);
        Toast.makeText(getApplicationContext(), "Alarm Number " + alarmObject.getAlarmNumber(), Toast.LENGTH_LONG).show();
        alarm.close();
    }

And received in the same way on the alarm activity as so:

public class Boom extends MainActivity{
AlarmClass boomAlarm = new AlarmClass();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            final Window wake = getWindow();
            wake.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
            setContentView(R.layout.boom);
            setTheme(R.style.AlarmStyle);
            overridePendingTransition(android.R.anim.fade_in,5000);
            boomAlarm = (AlarmClass) getIntent().getParcelableExtra("alarm");
    //      Vibrator buzz = (Vibrator) getSystemService(VIBRATOR_SERVICE);
    //      buzz.vibrate(1000);
            snoozeListener();
            dismissListener();
        }

The passed parcelable object that I'm passing into boomAlarm is always null.

Does anyone know why a parcelable object would work just fine in an intent, but come out null on the other side of a PendingIntent?

4条回答
乱世女痞
3楼-- · 2019-07-28 16:48

try

boomAlarm = (AlarmClass) getIntent().getExtras().get("alarm");

instead of

boomAlarm = (AlarmClass) getIntent().getParcelableExtra("alarm");

if it does not work

make AlarmClass extends Serializable rather than Parceable.

查看更多
混吃等死
4楼-- · 2019-07-28 17:00

It turns out that the ParcelableExtra was getting dropped at the broadcast receiver! I was indeed passing it, BUT, when the broadcast receiver fired off the activity, it did not re-attach the extras; resulting in a null in the activity when it tried to getParcelableExtras.

查看更多
Explosion°爆炸
5楼-- · 2019-07-28 17:02

EDIT: I think your problem is in this line:

PendingIntent torpedo = PendingIntent.getBroadcast(this,alarmObject.getAlarmNumber(),intent,PendingIntent.FLAG_UPDATE_CURRENT);

You are not starting an activity here, but a BroadCast try changing it as follows:

PendingIntent torpedo = PendingIntent.getActivity(this,alarmObject.getAlarmNumber(),intent,PendingIntent.FLAG_UPDATE_CURRENT);

Change PendingIntent.getBroadcast() to PendingIntent.getActivity();

And try changing the following:

Intent intent = new Intent(getBaseContext(), Alarm.class);

to

Intent intent = new Intent(this , Alarm.class);

or

Intent intent = new Intent(getApplicationContext(), Alarm.class);
查看更多
登录 后发表回答