Android E / Parcel:解组时找不到类(仅限三星Tab3)

时间:2015-02-18 17:07:32

标签: android android-intent classnotfoundexception unmarshalling parcel

我一直无法解决为什么会出现此错误,而且只能在运行4.4.2的三星Tab3设备上解决?它发生在我的MainActivity启动另一个Activity时,并在意图中传递一个Parcelable类,如下所示:

    private void debugTest(TestParcel cfgOptions){
        TestParcel cfgOptions = new TestParcel();
        cfgOptions.setValue(15); //just to verify

        Intent intent = new Intent(MainActivity.this, TestActivity.class);
        intent.putExtra("cfgOptions", cfgOptions);
        startActivityForResult(intent, DBG_TEST);
    }

TestActivity获取类似的可分配数据:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_activity);

    TestParcel cfgOptions = getIntent().getExtras().getParcelable("cfgOptions");
}

TestParcel类:

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

    public class TestParcel implements Parcelable {
    private long l_ucs_value = 0;
    private String s_rx_number = "";

    //constructor
    public TestParcel() {
        l_ucs_value = 0;
        s_rx_number = "";
    }

    public void RxNumber(String s) {
        s_rx_number = s;
    }
    public String RxNumber() {
        return s_rx_number;
    }

    //-----------------------------------------------------------------------
    public void setValue(long v){
        l_ucs_value = v;
    }
    public long getValue(){ return l_ucs_value; }


    protected TestParcel(Parcel in) {
        l_ucs_value = in.readLong();
        s_rx_number = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(l_ucs_value);
        dest.writeString(s_rx_number);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<TestParcel> CREATOR = new Parcelable.Creator<TestParcel>() {
        @Override
        public TestParcel createFromParcel(Parcel in) {
            return new TestParcel(in);
        }

        @Override
        public TestParcel[] newArray(int size) {
            return new TestParcel[size];
        }
    };
}

同样,我只在三星Tab3设备上看到这一点 - 但这是我们需要它的设备。这是三星logcat:

02-18 08:05:55.393    2235-2571/? E/Parcel? Class not found when unmarshalling: com.vms.android.VersatileDEX.TestParcel
java.lang.ClassNotFoundException: com.vms.android.VersatileDEX.TestParcel
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:251)
        at java.lang.Class.forName(Class.java:216)
        at android.os.Parcel.readParcelableCreator(Parcel.java:2133)
        at android.os.Parcel.readParcelable(Parcel.java:2097)
        at android.os.Parcel.readValue(Parcel.java:2013)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
        at android.os.Bundle.unparcel(Bundle.java:249)
        at android.os.Bundle.getString(Bundle.java:1118)
        at android.content.Intent.getStringExtra(Intent.java:5148)
        at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1467)
        at com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:1063)
        at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:4134)
        at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:4032)
        at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:159)
        at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2712)
        at android.os.Binder.execTransact(Binder.java:404)
        at dalvik.system.NativeStart.run(Native Method)
 Caused by: java.lang.NoClassDefFoundError: com/vms/android/VersatileDEX/TestParcel
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:251)
        at java.lang.Class.forName(Class.java:216)
        at android.os.Parcel.readParcelableCreator(Parcel.java:2133)
        at android.os.Parcel.readParcelable(Parcel.java:2097)
        at android.os.Parcel.readValue(Parcel.java:2013)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
        at android.os.Bundle.unparcel(Bundle.java:249)
        at android.os.Bundle.getString(Bundle.java:1118)
        at android.content.Intent.getStringExtra(Intent.java:5148)
        at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1467)
        at com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:1063)
        at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:4134)
        at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:4032)
        at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:159)
        at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2712)
        at android.os.Binder.execTransact(Binder.java:404)
        at dalvik.system.NativeStart.run(Native Method)
 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.vms.android.VersatileDEX.TestParcel" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:67)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:251)
        at java.lang.Class.forName(Class.java:216)
        at android.os.Parcel.readParcelableCreator(Parcel.java:2133)
        at android.os.Parcel.readParcelable(Parcel.java:2097)
        at android.os.Parcel.readValue(Parcel.java:2013)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
        at android.os.Bundle.unparcel(Bundle.java:249)
        at android.os.Bundle.getString(Bundle.java:1118)
        at android.content.Intent.getStringExtra(Intent.java:5148)
        at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1467)
        at com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:1063)
        at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:4134)
        at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:4032)
        at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:159)
        at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2712)
        at android.os.Binder.execTransact(Binder.java:404)
        at dalvik.system.NativeStart.run(Native Method)

8 个答案:

答案 0 :(得分:71)

由于一些奇怪的原因,看起来类加载器没有正确设置。

TestActivity.onCreate()中尝试以下其中一项:


TestParcel cfgOptions = getIntent().getParcelableExtra("cfgOptions");

Intent intent = getIntent();
intent.setExtrasClassLoader(TestParcel.class.getClassLoader());
TestParcel cfgOptions = intent.getParcelableExtra("cfgOptions");

Bundle extras = getIntent().getExtras();
extras.setClassLoader(TestParcel.class.getClassLoader());
TestParcel cfgOptions = extras.getParcelable("cfgOptions");

或者,将parcelable包装成一个包:

Bundle b = new Bundle();
b.putParcelable("options", cfgOptions);
Intent intent = new Intent(MDex.this, TestActivity.class);
intent.putExtra("bundle", b);

得到:

Bundle b = getIntent().getBundleExtra("bundle");
TestParcel cfgOptions = b.getParcelable("options");

答案 1 :(得分:8)

在我的情况下,内部自动创建新包的新Intent()。putExtra(key,parcelable)给了我解组错误我不知道为什么,所以我不得不自己创建新包,添加parcelable在它上面并在意图上添加包。通过这样做,它解决了这个问题。

答案 2 :(得分:7)

试着在这里更简洁明了答案 -

//sending a parcelable class to another activity -----------------

MyParcelableOptionsClass mpoc = new MyParcelableOptionsClass();

Bundle b = new Bundle();
b.putParcelable("options", mpoc );

Intent intent = new Intent(MyActivity.this, OtherActivity.class);
intent.putExtra("bundle", b);

startActivityForResult(intent, 1);


//getting the parcelable class from OtherActivity------------------

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.other_activity);

    Bundle b = getIntent().getBundleExtra("bundle");
    MyParcelableOptionsClass mpoc = b.getParcelable("options");
}


//returning the parcelable class back from OtherActivity -----------

 Bundle b = new Bundle();
 b.putParcelable("options", mpoc);

 Intent intent = new Intent();
 intent.putExtra("bundle", b);

 setResult(0, intent);


//and getting the parcelable class back in MyActivity --------------

onActivityResult(int requestCode, int resultCode, Intent data){
    if(null != data){
        Bundle b = data.getBundleExtra("bundle");
        MyParcelableOptionsClass mpoc = b.getParcelable("options");
    }
}

答案 3 :(得分:4)

最新的三星S8手机也发生了同样的问题。创建捆绑包明确地为我工作。我使用了以下代码,它不需要捆绑包的字符串标识符:

// Create the intent to start the activity.
Bundle bundle = new Bundle();
bundle.putParcelable("YOUR_PARCELABLE_ID", yourPacelable);
Intent intent = new Intent(context, YourActivity.class);
intent.putExtras(bundle);

然后阅读活动中的parcelable:

// In your activity, read parcelable back.
YourParcelable p = getIntent().getParcelableExtra("YOUR_PARCELABLE_ID");

我希望这会有所帮助。

答案 4 :(得分:1)

对于将Java与Kotlin混合使用的人可能有用。 我找到了一个简单的解决方案,该解决方案只允许使用Kotlin,而无需样板。

val intent = Intent(this, TestActivity::class.java).apply {
    extras?.putParcellable("cfgOptions", cfgOptions)
}

startActivityForResult(intent, DBG_TEST);

然后要收回该值,您应该使用:

var cfgOptions = intent?.extras?.getParcellable<TestParcel>("cfgOptions")

答案 5 :(得分:0)

对于在项目中同时使用Java和Kotlin的人,如果您在kotlin中创建Parcelable Data Class而在Java Class eg Activity or something中使用它,则可能会遇到这种错误。成为一个问题,如果kotlin数据类

,它的解决方案只是使用Java POJOs

答案 6 :(得分:0)

只是发现了此异常的另一个原因。由于某种原因,我只能在恢复活动时获得它,而在第一次创建它时却没有。 如果您的可包裹实体是科特林data class,它是某个class的子实体,而您尝试取消包裹,则可能会收到BadParcelableException,在解组时找不到类。 解决方案是使此类仅class,而不是data class

答案 7 :(得分:0)

我有同样的问题。就我而言,intent的Extras具有两个具有相同键的可仿冒对象。例如:

val intent = Intent()
val anotherIntent = Intent()

anotherIntent.putExtra("same_extra_key", MyParcelableObj())
intent.putExtra("same_extra_key", MyParcelableObj())

intent.putExtra("another_intent_extra_key", anotherIntent)

// ClassNotFoundError
intent.getParcelableExtra<MyParcelableObj>("same_extra_key")

您必须使用其他键或getParcelableArrayListExtra方法来避免错误。

intent.getParcelableArrayListExtra<MyParcelableObj>("same_extra_key")