Pendingintent getbroadcast丢失了可分配的数据

时间:2016-09-13 20:23:40

标签: android android-intent broadcast android-pendingintent parcelable

这是问题所在。我的程序在Android 6.0中运行完美。将设备更新到android 7.0后。 Pendingintent无法将可分配的数据传递给boradcast reveiver。这是代码。

触发警报

public static void setAlarm(@NonNull Context context, @NonNull Todo todo) {
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
    Intent intent = new Intent(context, AlarmReceiver.class);
    intent.putExtra("KEY_TODO", todo);
    PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager.set(AlarmManager.RTC_WAKEUP, todo.remindDate.getTime(), alarmIntent);
}

Todo是一个Parcelable类,而todo是我在通知中需要的实例。

在Broadcastreceiver中,我无法获取可用数据。

public void onReceive(Context context, Intent intent) {

    Todo todo = intent.getParcelableExtra("KEY_TODO");

}

以下是调试时的意图结果 enter image description here

我不知道为什么意图只包含一个我从未放入的Integer.Parcelable todo在哪里。 此代码在Android 6.0中没有问题,但无法在7.0中运行

2 个答案:

答案 0 :(得分:16)

引用myself

  

自定义Parcelable课程 - 您的应用程序独有的课程,而非部分课程   Android框架 - 已经出现了间歇性问题   用作Intent额外内容的年份。基本上,如果是核心操作系统进程   需要修改Intent额外内容,这个过程最终会尝试   在设置时重新创建Parcelable个对象   额外的Bundle用于修改。那个过程没有你的   类,因此它获得运行时异常。

     

可能发生这种情况的一个方面是AlarmManager。使用的代码   具有Parcelable的自定义AlarmManager对象可能有效   在早期版本的Android will not work on Android N上。

我所知道的最有效的解决方法是手动将Parceable自己转换为byte[]并将其放入Intent额外内容,手动将其转换回{{1} }} 如所须。 This Stack Overflow answer 显示了该技术,this sample project提供了完整的工作样本。

关键位是ParcelableParcelable之间的转换:

byte[]

答案 1 :(得分:0)

在问题下方的评论中,按照@David Wasser的建议,我能够解决类似的问题:

    public static void setAlarm(@NonNull Context context, @NonNull Todo todo) {

      ...

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

      Bundle todoBundle = new Bundle();
      todoBundle.putParcelable("KEY_TODO", todo);

      intent.putExtra("KEY_TODO", todoBundle); // i just reuse the same key for convenience

      ...

    }

然后在广播接收器中按以下方式提取包:

    public void onReceive(Context context, Intent intent) {

        Bundle todoBundle = intent.getBundleExtra("KEY_TODO");

        Todo todo;

        if (todoBundle != null ) {
            todo = todoBundle.getParcelable("KEY_TODO");
        }

    }