Отсутствуют дополнительные функции намерения Android 7

Кто-нибудь знает, есть ли какие-либо изменения в том, как Android 7.0 (Nougat) обрабатывает дополнительные намерения по сравнению с Android 6.0 (Lollipop)?

Короче говоря: мое приложение работает, как задумано, на всех версиях от 4.1(16) до 6.0(23), но вылетает на Android 7.0(24)!

Приложение создает ожидающее намерение с намерением для пользовательского широковещательного приемника, который имеет дополнительные функции. Однако на Android 7 ни одно из дополнений не присутствует в намерении, полученном приемником вещания.

MainActivity.java

Intent intent = new Intent(context, PollServerReceiver.class);

// TODO:  Remove after DEBUGGING is completed!
intent.putExtra("TESTING1", "testing1");
intent.putExtra("TESTING2", "testing2");
intent.putExtra("TESTING3", "testing3");

 // PendingIntent to be triggered when the alarm goes off.
 final PendingIntent pIntent = PendingIntent.getBroadcast(context,
            PollServerReceiver.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);

// Setup alarm to schedule our service runs.
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, firstRun, freqMilis, pIntent);

PollServerReceiver.java

Bundle extras = intent.getExtras();
Log.d(TAG, "onReceive: TESTING1 = " + extras.getString("TESTING1")); // null here

// None of the three "TESTING*" keys are there!
for (String key : extras.keySet()) {
    Object value = extras.get(key);
    Log.d(TAG, String.format("onReceive extra keys: %s %s (%s)", key, value.toString(), value.getClass().getName()));
}

Трассировка стека, очевидно, указывает на NullPointerException как на причину сбоя. Было бы не так странно, если бы он вылетал во всех версиях, но в данном случае это только последний андроид. У кого-нибудь есть идеи, пожалуйста?

Примечание. Я пытался создать ожидающие намерения с разными флагами, включая (0, PendingIntent.FLAG_UPDATE_CURRENT, PendingIntent.FLAG_CANCEL_CURRENT), но все равно получил тот же результат.


comment
Я не могу воспроизвести вашу проблему, используя код из вашего вопроса, поэтому я предполагаю, что, возможно, реальный код не соответствует коду вопроса. Есть ли в вашем реальном коде какие-либо дополнения в виде пользовательских Parcelable классов?   -  person CommonsWare    schedule 19.09.2016
comment
Да, помимо трех тестовых дополнений String, я также храню объект Parcelable с тем же намерением. Конечно, он также отсутствует в намерении, полученном получателем, а также в дополнительных строках дерева.   -  person Konaras    schedule 19.09.2016
comment
24 не позволяет передать объект Parcelable в AlarmManager , stackoverflow.com/questions/38466080/   -  person Pavneet_Singh    schedule 19.09.2016
comment
О Боже. (┛◉Д◉)┛彡┻━┻   -  person Konaras    schedule 19.09.2016
comment
В случае, если это полезно для других: помещение значения перечисления в дополнительные функции намерения вызывает такое же поведение. Решение состоит в том, чтобы воссоздать значение перечисления в приемнике; простым способом было бы передать порядковое значение, а не само перечисление. (Если перечисление может измениться, было бы лучше использовать более долгосрочный стабильный идентификатор, такой как константа, связанная с перечислением в его конструкторе.)   -  person Steve Haley    schedule 19.10.2016


Ответы (2)


Помещение пользовательского Parcelable в PendingIntent никогда не было особенно надежным, и оно не будет работать в AlarmManager PendingIntent на Android 7.0. Другим процессам может потребоваться заполнить значения в Intent, и это включает в себя манипулирование дополнительными функциями, и это невозможно сделать ни в одном процессе, кроме вашего собственного, поскольку ни в одном другом процессе нет вашего пользовательского класса Parcelable.

Этот ответ SO имеет обходной путь в виде самостоятельного преобразования Parcelable в/из byte[].

person CommonsWare    schedule 19.09.2016
comment
То же самое с сериализуемым - person Roman Nazarevych; 21.02.2018

У меня была аналогичная проблема, но я думаю, что нашел простое решение. Поместите свои данные в пакет и отправьте этот пакет с вашим намерением. В моем случае я хотел отправить сериализуемый объект с моим намерением.

Настройте сигнализацию:

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("example", 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);

Получите сигнал тревоги:

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");
    }

}

Это сработало для меня. Надеюсь, поможет :)

person Martin the Martian    schedule 07.06.2017