Android向BroadcastReceiver传递Parcelable列表时接收数据全为null
问题根因
追加列表后所有接收到的数据变为null,是两个典型的Android PendingIntent传值坑叠加导致的:
- PendingIntent复用问题:你创建PendingIntent时用uid作为requestCode,且没有加
FLAG_UPDATE_CURRENT标记。如果之前测试时已经用同一个uid创建过仅传uid、job的PendingIntent,系统会直接返回缓存的旧实例,不会使用你新塞入列表的Intent;同时跨进程传给AlarmManager的PendingIntent如果没有更新标记,序列化自定义Parcelable对象时会丢失类型信息。 - 反序列化类加载器不匹配:AlarmManager是系统服务,触发广播时会在系统进程先对Intent做反序列化,默认的类加载器找不到你项目里自定义的
CharacInfo类,会直接触发反序列化失败,导致整个Bundle内的所有数据都无法正常读取,返回null。
修复方案
按以下步骤修改代码即可解决:
- 修改PendingIntent创建逻辑,追加更新标记,适配高版本系统
替换原有PendingIntent创建代码:
改完首次运行建议先卸载重装应用,清除系统缓存的旧PendingIntent实例,避免旧实例干扰。val pendingIntentFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE } else { PendingIntent.FLAG_UPDATE_CURRENT } val pendingIntent = PendingIntent.getBroadcast(context, uid, intent, pendingIntentFlag) - 修改广播接收端的读取逻辑,提前设置类加载器,适配Android 13+的API变更
替换onReceive内读取数据的代码:override fun onReceive(context: Context?, intent: Intent) { // 给Bundle设置当前类加载器,解决自定义Parcelable反序列化失败问题 intent.extras?.classLoader = javaClass.classLoader val uid = intent.getStringExtra(UID_KEY) val job = intent.getStringExtra(JOB_KEY) // 适配Android 13的类型安全API,避免泛型擦除问题 val lists: ArrayList<CharacInfo>? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { intent.getParcelableArrayListExtra(LIST_KEY, CharacInfo::class.java) } else { @Suppress("DEPRECATION") intent.getParcelableArrayListExtra(LIST_KEY) } Log.d("list_key","broadcastreceiver uid : ${uid}") Log.d("list_key","broadcastreceiver job : ${job}") Log.d("list_key","broadcastreceiver list : ${lists}") val serviceIntent = Intent(context, EmptyService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// context?.startForegroundService(serviceIntent)
} else {
// context?.startService(serviceIntent)
}
}
- 额外注意:Android Binder事务缓冲区有1MB的大小限制,不要通过Intent传递过大的列表。如果列表数据量多,建议先把数据存入Room数据库,广播里仅传递主键id,收到后再从数据库查询完整数据,避免传输失败。 内容的提问来源于stack exchange,提问作者luullu
相关产品推荐
相关产品推荐

