安卓7意图附加项丢失。

8

请问有没有人知道Android 7.0(牛轧糖)在处理意图附加项方面与Android 6.0(棒棒糖)相比是否有任何更改?

简而言之:我的应用程序在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()));
}

堆栈跟踪明显表明空指针异常是崩溃的原因。如果在所有版本中都崩溃,那么这并不奇怪,但在这种情况下,只有最新的Android才会崩溃。请问是否有任何想法?

注意:我尝试使用不同的标志创建挂起意图,包括(0PendingIntent.FLAG_UPDATE_CURRENTPendingIntent.FLAG_CANCEL_CURRENT),仍然得到完全相同的结果。


2
我无法使用您问题中的代码重现您的问题,所以我猜想也许真正的代码与问题中的代码不匹配。在您的真实代码中,是否有任何额外的自定义“Parcelable”类形式? - CommonsWare
是的,除了三个测试字符串额外参数之外,我还在同一个意图中存储了一个可序列化对象。当然,在接收器接收到的意图中,它也缺失了这个可序列化对象以及三个字符串额外参数。 - Konaras
1
24不允许将Parcelable对象传递到AlarmManager中,https://dev59.com/nJnga4cB1Zd3GeqPTRMQ - Pavneet_Singh
哦,天啊。 (┛◉Д◉)┛彡┻━┻ - Konaras
2
如果对其他人有帮助的话:将枚举值放入意图附加项中会触发相同的行为。解决方案是在接收器中重新创建枚举值;一种简单的方法是传递序数值而不是枚举本身。(如果枚举可能会更改,则最好使用与其构造函数中的枚举相关联的更长期稳定的标识符,如常量。) - Steve Haley
2个回答

17
将自定义的Parcelable对象放入PendingIntent中从未特别可靠,而且在Android 7.0上的AlarmManager PendingIntent中将根本无法工作。其他进程可能需要填充Intent中的值,并且这涉及操作extras,而这不能在除您自己之外的任何进程中完成,因为没有其他进程有您的自定义Parcelable类。提供了解决方案,即将Parcelable对象自行转换成/从byte[]。此SO回答提供了详细步骤。

与可序列化相同 - Roman Nazarevych

4

我有一个类似的问题,但我认为我找到了一个简单的解决方案。将您的数据放入Bundle中,并使用您的意图发送该Bundle。在我的情况下,我想要通过我的意图发送一个可序列化的对象。

设置闹钟:

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

}

这对我来说很好用,希望能帮到你 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接