private class MediaControlCallback extends MediaControllerCompat.Callback {
@Override
public void onSessionEvent(String event, Bundle extras) {
if (event.equals(“playing_list_event”)) {
int count = extras.getInt("count");
ArrayList<MediaSessionCompat.QueueItem> nowPlayingList = extras.getParcelableArrayList("playing_list");
代码功能很简单,利用MediaSession的SessionEvent机制,Application 1 将一个Integer对象和ArrayList对象跨进程传递给Application 2,其中,MediaSessionCompat.QueueItem是一个可序列化的类:
public class MediaSessionCompat {
* A single item that is part of the play queue. It contains a description
* of the item and its id in the queue.
public static final class QueueItem implements Parcelable {
代码运行结果如下,在Application 2 的进程中出现异常:
02-02 18:08:38.162 8892 8892 E AndroidRuntime: FATAL EXCEPTION: main
02-02 18:08:38.162 8892 8892 E AndroidRuntime: Process: com.xx.xx.xx.xx, PID: 8892
02-02 18:08:38.162 8892 8892 E AndroidRuntime: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.v4.media.session.MediaSessionCompat$QueueItem
异常产生的原因
既然遇到问题,那咱们就想办法解决。
异常很明显,说是QueueItem这个类无法找到,到底是什么原因呢?
要解决这个问题,首先需要了解一个重要的类ClassLoader,对Java反射比较熟悉的童鞋对该类应该不会陌生。对于该类官方给出的说法是:
A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a “class file” of that name from a file system.
类加载器是负责加载类的对象。 ClassLoader类是一个抽象类。 给定一个类的二进制名称,类加载器应尝试去定位或生成定义一个类所需的数据。 一个典型的策略是将名称转换为文件名,然后从文件系统中读取该名称的“类文件”。
Every Class object contains a Class#getClassLoader() to the ClassLoader that defined it.
每个Class对象都包含一个Class#getClassLoader(),用于定义它的ClassLoader。
Class objects for array classes are not created by class loaders, but are created automatically as required by the Java runtime. The class loader for an array class, as returned by Class#getClassLoader() is the same as the class loader for its element type; if the element type is a primitive type, then the array class has no class loader.
数组类的类对象不是由类加载器创建的,而是根据Java运行时的需要自动创建的。 Class#getClassLoader()返回的数组类的类加载器与其元素类型的类加载器相同; 如果元素类型是基本类型,则数组类没有类加载器。
在对ClassLoader有了较清楚的认识后,我们再回到问题本身。本例中需要从Application 1 传递一个Integer对象和一个ArrayList对象到Application 2,而ArrayList中的成员是MediaSessionCompat.QueueItem对象。对于Integer对象,它是一个基础类型,如官方文档说明,它是不需要class loader的,而MediaSessionCompat.QueueItem并不是一个基础类型,它是需要对应的class loader来加载类的。严谨起见,我做了一个实验,对Application 2 的代码做了如下修改:
public void onSessionEvent(String event, Bundle extras) {
if (event.equals(“playing_list_event”)) {
Log.d("TEST_TAG", "onSessionEvent, extras class loader:" + extras.getClassLoader()):
//int count = extras.getInt("count");
//ArrayList<MediaSessionCompat.QueueItem> nowPlayingList = extras.getParcelableArrayList("playing_list");
运行后,日志打印如下:
05-15 18:32:24.913 7315 7315 D xx: TEST_TAG__onSessionEvent, extras class loader:null
看明白了吧,这里Bundle对象并没有class loader,所以找不到MediaSessionCompat.QueueItem。
如何解决异常
很明显,需要给extras对象设置一个MediaSessionCompat.QueueItem的class loader,对Application 2 的代码又做了如下修改:
public void onSessionEvent(String event, Bundle extras) {
if (event.equals(“playing_list_event”)) {
Log.d("TEST_TAG", "onSessionEvent, extras class loader before:" + extras.getClassLoader()):
extras.setClassLoader(MediaSessionCompat.QueueItem.class.getClassLoader()); //设置class loader
Log.d("TEST_TAG", "onSessionEvent, extras class loader after:" + extras.getClassLoader()):
int count = extras.getInt("count");
ArrayList<MediaSessionCompat.QueueItem> nowPlayingList = extras.getParcelableArrayList("playing_list");
运行成功,看看运行结果:
05-15 21:31:54.796 12918 12918 D xx: TEST_TAG__onSessionEvent, bundle class loader before:null
05-15 21:31:54.796 12918 12918 D xx: TEST_TAG__onSessionEvent, bundle class loader after:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.xx.xx-l_YWuWr6nbgqjHNoz_5vmw==/base.apk"],nativeLibraryDirectories=[/data/app/com.xx.xx-l_YWuWr6nbgqjHNoz_5vmw==/lib/x86_64, /system/lib64, /vendor/lib64]]]
问题解决。
1. 从类加载机制入手
E/Parcel: Class not found when unmarshalling: xxx.ItemDataBean
java.lang.ClassNotFoundException: xxx.ItemDataBean
原因分析:
- Android有两种不同的classloaders:framework classloader和apk classloader
- framework classloader知道怎么加载android classes
- apk classloader知道怎么加载你自定义的类,apk classloader继承自framework classloader,所以也知道怎么加载android classes。
- 在应用刚启动时,默认class loader是apk classloader,但在系统内存不足应用被系统回收会再次启动,这个默认class loader会变为framework classloader了,所以对于自己的类会报ClassNotFoundException。
解决办法
1、【推荐】Client端接收Bundle的时候进行处理
bundle.setClassLoader(getClass().getClassLoader());
2、需要传递的JavaBean继承自Parcelable,成员变量进行一定处理
//原方法
//rect = in.readParcelable(null);
config = in.readParcelable(Rect.class.getClassLoader());
本文基于本人在项目开发中遇到的实际问题,对ClassNotFoundException异常发生的原因和解决办法做了探究。定位异常首先看看出问题的代码。Application 1 的部分代码:private MediaSessionCompat mMediaSession = new MediaSessionCompat(this, TAG); private void s...
Application 1 的部分代码:
private MediaSessionCompat mMediaSession = new MediaSessionCompat(this, TAG);
private voi...
这个报错的原理可以查看
https://blog.csdn.net/SCHOLAR_II/article/details/104329011
这位博主写的很清楚,这类问题都是ClassLoader的问题
但是很有趣的是,在某些情况下,我们的Parcelable实现类没有复杂的数据结构,只是一些int,boolean的时候,在一些机型上也会出现这个问题(笔者是发生在三星s7上)。
这个问题原因暂时不是很了解,但是提供一下目前的解决办法:
原来传递的时候是
E/Parcel: Class not found when unmarshalling: android.support.v4.app.FragmentManagerState
java.lang.ClassNotFoundException: android.support.v4.app.FragmentManagerState
at java.l
转自:http://www.trinea.cn/android/android-os-badparcelableexception-classnotfoundexception-unmarshalling/
本文主要分析android.os.BadParcelableException: ClassNotFoundException when unmarshalling这个异常的原因及解决方
疑难问题:android.os.BadParcelableException
ClassNotFoundException when unmarshalling: androidx.fragment.app.FragmentManagerState 问题分析
-----------------------Crash 1 Message-----------------------
完整log: logcat.txt
02-20 21:08:32.727 E/AndroidRuntime(32306
1 AlarmManager alarmMgr = (AlarmManager) mContext
2 .getSystemService(Context.ALARM_SERVICE);
3 Intent intent = new Intent(ALARM_ALERT);
4 ...
低端机上intent使用bundle传递parcelable对象,一直crash,报错android.os.BadParcelableException: ClassNotFoundException when unmarshalling
只要将下面的写法
Bundle bundle = new Bundle();
bundle.putParcelable(BUNDLE_L...
repositories {
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
google()
mavenCentral()
java中关于JSONObject顺序排序的问题
a648x:
IdleHandler 是什么?怎么使用,能解决什么问题?
落叶孤尘:
Flutter Provider 最深、最全、最新的源码分析
一叶飘舟:
Flutter Provider 最深、最全、最新的源码分析