Android PendingEvent getbroadcast丢失的包裹数据

Android PendingEvent getbroadcast丢失的包裹数据,android,android-intent,broadcast,android-pendingintent,parcelable,Android,Android Intent,Broadcast,Android Pendingintent,Parcelable,问题就在这里。我的程序在安卓6.0中运行得很好。将设备更新到android 7.0后。PendingEvent无法将包裹数据传递给boradcast reveiver。这是代码 拉响警报 public static void setAlarm(@NonNull Context context, @NonNull Todo todo) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.

问题就在这里。我的程序在安卓6.0中运行得很好。将设备更新到android 7.0后。PendingEvent无法将包裹数据传递给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是一个可打包的类,而Todo是我在通知中需要的实例

在Broadcastreceiver中,我无法获取包裹数据

public void onReceive(Context context, Intent intent) {

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

}
下面是我调试时的意图结果

我不知道为什么意图只包含一个整数,我从来没有把它放进去。待办事项的包裹在哪里。 此代码在android 6.0中没有问题,但无法在7.0中运行引用:

自定义
Parcelable
类-应用程序特有的类,而不是部分 Android框架的一部分——在过去几年中出现了间歇性问题 用作
Intent
extra的年份。基本上,如果一个核心操作系统进程 需要修改
Intent
extras,该进程将结束尝试 在设置 额外的
用于修改。这个过程没有你的优势 类,因此它会获得一个运行时异常

出现这种情况的一个区域是
AlarmManager
。使用的代码 带有
AlarmManager
的自定义
Parcelable
对象可能已经工作 在旧版本的Android上

据我所知,最有效的解决方法是手动将
可包裹的
转换为
字节[]
,并将其放入
意图
额外,根据需要手动将其转换回
可包裹的
。 显示了该技术,并提供了完整的工作示例

关键位是
Parcelable
字节[]
之间的转换:

/***
 Copyright (c) 2016 CommonsWare, LLC
 Licensed under the Apache License, Version 2.0 (the "License"); you may not
 use this file except in compliance with the License. You may obtain a copy
 of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
 by applicable law or agreed to in writing, software distributed under the
 License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
 OF ANY KIND, either express or implied. See the License for the specific
 language governing permissions and limitations under the License.

 From _The Busy Coder's Guide to Android Development_
 https://commonsware.com/Android
 */

package com.commonsware.android.parcelable.marshall;

import android.os.Parcel;
import android.os.Parcelable;

// inspired by https://stackoverflow.com/a/18000094/115145

public class Parcelables {
  public static byte[] toByteArray(Parcelable parcelable) {
    Parcel parcel=Parcel.obtain();

    parcelable.writeToParcel(parcel, 0);

    byte[] result=parcel.marshall();

    parcel.recycle();

    return(result);
  }

  public static <T> T toParcelable(byte[] bytes,
                                   Parcelable.Creator<T> creator) {
    Parcel parcel=Parcel.obtain();

    parcel.unmarshall(bytes, 0, bytes.length);
    parcel.setDataPosition(0);

    T result=creator.createFromParcel(parcel);

    parcel.recycle();

    return(result);
  }
}
/***
版权所有(c)2016 Commonware,LLC
根据Apache许可证2.0版(以下简称“许可证”)获得许可;你不可以
除非符合许可证,否则请使用此文件。你可以得到一份
许可证的有效期在http://www.apache.org/licenses/LICENSE-2.0. 除非需要
根据适用法律或书面同意,根据
许可证按“原样”分发,无任何保证或条件
任何形式的,无论是明示的还是暗示的。请参阅许可证以了解具体的信息
管理许可证下的权限和限制的语言。
从《忙碌的程序员指南》到Android开发_
https://commonsware.com/Android
*/
包com.commonware.android.parcelable.marshall;
导入android.os.packet;
导入android.os.Parcelable;
//灵感来自https://stackoverflow.com/a/18000094/115145
公共类包裹{
公共静态字节[]toByteArray(可包裹可包裹){
地块=地块。获取();
包裹。可写包裹(包裹,0);
字节[]结果=parcel.marshall();
包裹回收();
返回(结果);
}
公共静态T toParcelable(字节[]字节,
可包裹。创建者(创建者){
地块=地块。获取();
包裹解组(字节,0,字节.长度);
包裹。setDataPosition(0);
T result=creator.createFromParcel(地块);
包裹回收();
返回(结果);
}
}
引用:

自定义
Parcelable
类-应用程序特有的类,而不是部分 Android框架的一部分——在过去几年中出现了间歇性问题 用作
Intent
extra的年份。基本上,如果一个核心操作系统进程 需要修改
Intent
extras,该进程将结束尝试 在设置 额外的
用于修改。这个过程没有你的优势 类,因此它会获得一个运行时异常

出现这种情况的一个区域是
AlarmManager
。使用的代码 带有
AlarmManager
的自定义
Parcelable
对象可能已经工作 在旧版本的Android上

据我所知,最有效的解决方法是手动将
可包裹的
转换为
字节[]
,并将其放入
意图
额外,根据需要手动将其转换回
可包裹的
。 显示了该技术,并提供了完整的工作示例

关键位是
Parcelable
字节[]
之间的转换:

/***
 Copyright (c) 2016 CommonsWare, LLC
 Licensed under the Apache License, Version 2.0 (the "License"); you may not
 use this file except in compliance with the License. You may obtain a copy
 of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
 by applicable law or agreed to in writing, software distributed under the
 License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
 OF ANY KIND, either express or implied. See the License for the specific
 language governing permissions and limitations under the License.

 From _The Busy Coder's Guide to Android Development_
 https://commonsware.com/Android
 */

package com.commonsware.android.parcelable.marshall;

import android.os.Parcel;
import android.os.Parcelable;

// inspired by https://stackoverflow.com/a/18000094/115145

public class Parcelables {
  public static byte[] toByteArray(Parcelable parcelable) {
    Parcel parcel=Parcel.obtain();

    parcelable.writeToParcel(parcel, 0);

    byte[] result=parcel.marshall();

    parcel.recycle();

    return(result);
  }

  public static <T> T toParcelable(byte[] bytes,
                                   Parcelable.Creator<T> creator) {
    Parcel parcel=Parcel.obtain();

    parcel.unmarshall(bytes, 0, bytes.length);
    parcel.setDataPosition(0);

    T result=creator.createFromParcel(parcel);

    parcel.recycle();

    return(result);
  }
}
/***
版权所有(c)2016 Commonware,LLC
根据Apache许可证2.0版(以下简称“许可证”)获得许可;你不可以
除非符合许可证,否则请使用此文件。你可以得到一份
许可证的有效期在http://www.apache.org/licenses/LICENSE-2.0. 除非需要
根据适用法律或书面同意,根据
许可证按“原样”分发,无任何保证或条件
任何形式的,无论是明示的还是暗示的。请参阅许可证以了解具体的信息
管理许可证下的权限和限制的语言。
从《忙碌的程序员指南》到Android开发_
https://commonsware.com/Android
*/
包com.commonware.android.parcelable.marshall;
导入android.os.packet;
导入android.os.Parcelable;
//灵感来自https://stackoverflow.com/a/18000094/115145
公共类包裹{
公共静态字节[]toByteArray(可包裹可包裹){
地块=地块。获取();
包裹。可写包裹(包裹,0);
字节[]结果=parcel.marshall();
包裹回收();
返回(结果);
}
公共静态T toParcelable(字节[]字节,
可包裹。创建者(创建者){
地块=地块。获取();
包裹解组(字节,0,字节.长度);
包裹。setDataPosition(0);
T result=creator.createFromParcel(地块);
包裹回收();
返回(结果);
}
}

根据问题下方评论中@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");
        }

    }
然后在广播接收器中提取