Android 7 BroadcastReceiver onReceive intent.getExtras missing data
Asked Answered
H

3

12

My app isn't working on Android 7. My BroadcastReceiver.onReceive method is called but the contents of the intent.getExtras is missing. I've verified that the data was correctly loaded. Here's a snippet from my onReceive method, where intent is passed as a parameter to onReceive.

Bundle bundle = intent.getExtras();
textMessage = bundle.getString("TEXT_MESSAGE");
ArrayList<MyPhoneNumber> phoneNumbersToText = bundle.getParcelableArrayList("PHONE_NUMBERS");

Both textMessage and phoneNumbersToText are null.

Here's a snippet from my manifest file:

<receiver android:process=":remote" android:name="com.friscosoftware.timelytextbase.AlarmReceiver"></receiver> 

Here's a snippet where the data is loaded:

Intent intent = new Intent(context , AlarmReceiver.class);  
intent.putExtra(Constants.TEXT_MESSAGE, scheduledItem.getMessageToSend());
intent.putExtra(Constants.PHONE_NUMBERS, scheduledItem.getPhoneNumbersToText());    

PendingIntent sender = PendingIntent.getBroadcast(context, getRequestCodeFromKey(key), intent, PendingIntent.FLAG_UPDATE_CURRENT);

// Get the AlarmManager service
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, selectedDateTime.getTimeInMillis(), sender);

The same code works fine in Android 6.

Any thoughts on what changes are required here for Android 7?

Thank you

Hoofed answered 4/8, 2016 at 18:55 Comment(1)
Intent has the setAction(String action) method. You can paste the serializable object here. It works. Set extras won't work in Android 7. I had the same problem. Here is the sample - https://mcmap.net/q/938412/-android-7-broadcastreceiver-onreceive-intent-getextras-missing-dataTorsi
K
1

+1, it looks like you're having the same issue as me. I logged it on the tracker, (https://code.google.com/p/android/issues/detail?id=216581) which you commented on.

My solution was to use SharedPreferences to store my custom object. Then, when the alarmmanager fires, I run the following to get the object out. tl;dr, I use GSON to serialize/deserialize my custom POJO in/out of SharedPrefs as a String. For example:

 String json = getSharedPrefs(context).getString(NotificationUtility.NEXT_REMINDER_KEY, "No reminder found");
    try {
        Gson gson = new Gson();
        Reminder reminder = gson.fromJson(json, Reminder.class);
        if (reminder != null) {
            return reminder;
        }
    } catch (Exception error) {
        Log.i(TAG, "Error parsing json: " + error.getMessage(), error);
        return null;
    }
    return null;

Hope this helps you out!

Know answered 5/8, 2016 at 17:26 Comment(3)
Thanks, I'll try it out your suggestion. Hopefully, a fix will be forthcoming.Hoofed
Your solution worked, but for other reasons I decided to store the data in a database and simply pass the key.Hoofed
So according to the bug report it's intended behaviour... Wait what?Melvin
T
10

Android O version doesn't get extras properly in BroadcastReceivers. But the one great solution is to use an intent's setAction(String action) method to send the serializable Alarm object. Then get it back to object in onReceive. Here is the sample:

    Intent intent = new Intent(context, AlarmReceiver.class);
    intent.setAction(new Gson().toJson(alarm));

Then in your Alarm's receiver

public void onReceive(Context context, Intent intent) {

    String alarmSerializable = intent.getAction();
    if (alarmSerializable != null)
        alarm = new Gson().fromJson(alarmSerializable, Alarm.class);

    //TODO next, send notification
}

This is the common way for Android O and others.

Torsi answered 15/2, 2019 at 23:49 Comment(0)
K
1

+1, it looks like you're having the same issue as me. I logged it on the tracker, (https://code.google.com/p/android/issues/detail?id=216581) which you commented on.

My solution was to use SharedPreferences to store my custom object. Then, when the alarmmanager fires, I run the following to get the object out. tl;dr, I use GSON to serialize/deserialize my custom POJO in/out of SharedPrefs as a String. For example:

 String json = getSharedPrefs(context).getString(NotificationUtility.NEXT_REMINDER_KEY, "No reminder found");
    try {
        Gson gson = new Gson();
        Reminder reminder = gson.fromJson(json, Reminder.class);
        if (reminder != null) {
            return reminder;
        }
    } catch (Exception error) {
        Log.i(TAG, "Error parsing json: " + error.getMessage(), error);
        return null;
    }
    return null;

Hope this helps you out!

Know answered 5/8, 2016 at 17:26 Comment(3)
Thanks, I'll try it out your suggestion. Hopefully, a fix will be forthcoming.Hoofed
Your solution worked, but for other reasons I decided to store the data in a database and simply pass the key.Hoofed
So according to the bug report it's intended behaviour... Wait what?Melvin
C
1

I had a similar problem but I think I found an easy solution. Put your data inside a Bundle and send that Bundle with your alarm intent. In my case I wanted to send a serializable object with my intent.

Setup the alarm:

AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
`
Intent intent = new Intent(context, AlarmReciever.class);
Bundle bundle = new Bundle();

// creating an example object
ExampleClass exampleObject = new ExampleClass();

// put the object inside the Bundle
bundle.putSerializable("exapmle", exampleObject);

// put the Bundle inside the intent
intent.putExtra("bundle",bundle);

PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);

// setup the alarm
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);

Receive the alarm:

public class AlarmReciever extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        // get the Bundle
        Bundle bundle = intent.getBundleExtra("bundle");
        // get the object
        ExampleClass exampleObject = (ExampleClass)bundle.getSerializable("example");
    }

}

It worked fine for me. Hope it helps :)

Colas answered 7/6, 2017 at 10:21 Comment(2)
Looks promising but since the data was already being stored in a database I decided to simply pass the key. ThanksHoofed
Worked for me too, thanks. Very clear and straight forward.Acrocarpous

© 2022 - 2024 — McMap. All rights reserved.