Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
177 views
in Technique[技术] by (71.8m points)

java - How to pass custom Serializable object to BroadcastReceiver via PendingIntent

I am trying to pass a custom Serialized object from my IntentService to a BroadcastReceiver using PendingIntent.

Here is my custom object:

Row.java

public class Row implements Serializable {
    private String name;
    private String address;

    public Row(BluetoothDevice device) {
        this.name = device.getName();
        this.address = device.getAddress();
    }
}

Here is my IntentService

MyIntentService.java

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    protected void onHandleIntent(Intent workIntent) {
        AlarmManager alarmMgr;
        PendingIntent alarmPendingIntent;
        Intent alarmIntent;
        // The object "RowsList" is passed from my MainActivity and is correctly received by my IntentService.
        // NO PROBLEMS HERE
        Row[] arrRows = (Row[])workIntent.getSerializableExtra("RowsList");

        Log.i(TAG, "Inside Intent Service...");

        int interval = 2;
        try{
            if(interval != 0) {
                alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
                alarmIntent = new Intent(this, AlarmReceiver.class);
                alarmIntent.putExtra("IntentReason", "Reason"); // THIS GETS PASSED
                alarmIntent.putExtra("RowsList", arrRows); // THIS DOES NOT GET PASSED
                alarmPendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);

                alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + (interval * 1000), alarmPendingIntent);
                }
        }
        catch (Exception ignored){}
    }
}

MainActivity.java

// NO PROBLEMS HERE
private Intent myIntent;
myIntent = new Intent(getApplicationContext(), MyIntentService.class);
Log.i(TAG, "Starting Intent Service...");

myIntent.putExtra("RowsList", arrRows);
getApplicationContext().startService(intentListenBT);

Here is my BroadcastReceiver:

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver {

    Row[] arrRows;

    @Override
    public void onReceive(Context context, Intent intent) {
        this.context = context;
        String str = intent.getStringExtra("IntentReason"); // RECEIVED AS "Reason"
        arrRows = (Row[])intent.getSerializableExtra("RowsList"); // HERE IT IS null
    }
}

The most annoying part is that this code was working previously on my Nexus 6P (Lollipop 6.0 API23). It stopped working once I updated the same phone to Android 7.0(Nougat). Is there anything that has changed in Nougat that is causing this problem?

NOTE:

I ran my code using an emulator on Nexus 6P with API 23 and it works fine.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Most likely, you are running into the same sort of problem that you see with custom Parcelable implementations. Paraphrasing myself from that blog post: basically, if a core OS process needs to modify the Intent extras, that process winds up trying to recreate your Serializable objects as part of setting up the extras Bundle for modification. That process does not have your class and so it gets a runtime exception.

The most annoying part is that this code was working previously on my Nexus 6P (Lollipop 6.0 API23).

The behavior will vary by Android version, by how you are using the PendingIntent, and possibly by firmware/ROM. Do not assume that your current implementation will be reliable on any Android version.

Your only option is to not put the Serializable directly in an Intent extra. Use something other than Serializable (e.g., a nested Bundle), convert the Serializable into a byte[], etc.

This sample app demonstrates the latter approach, applied to a Parcelable object. The same basic technique should work for Serializable. (hat tip to AyeVeeKay for the link in the comments).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...