Android E/Parcel﹕ Class not found when unmarshalling (only on Samsung Tab3)

a 夏天 提交于 2019-11-26 12:24:43

问题


I\'ve been unable to resolve why this error occurs, and only on a Samsung Tab3 device, running 4.4.2? It happens when my MainActivity starts another Activity, and passes a Parcelable class in the intent like so:

    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 gets the parcelable data like so:

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

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

The class 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];
        }
    };
}

Again, I only see this on the Samsung Tab3 device - but that\'s the device we need it to work on. Here\'s the samsung 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)

回答1:


For some strange reason it looks like the class loader isn't set up properly.

Try one of the following in 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");

Alternatively, wrap the parcelable into a bundle:

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

to get:

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



回答2:


In my case, new Intent().putExtra(key,parcelable) which internally auto creates new bundle gives me unmarshall error I don't know why, so I had to create new bundle by myself, add the parcelable on it and add the bundle on the intent. By doing so it solves the problem.




回答3:


Just trying to be more concise and clear of the answer here -

//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");
    }
}



回答4:


The same issue happened to me with a recent Samsung S8 phone. Creating the bundle explicitly worked for me. I used the following code, which doesn't require a string identifier for the bundle:

// 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);

And then read the parcelable back in the activity:

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

I hope this helps.




回答5:


May be useful for people who mix Java with Kotlin. I found an easy solution that allows using only Kotlin and without boilerplate.

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

startActivityForResult(intent, DBG_TEST);

And then to retireve the value you should use:

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



回答6:


For people who are using both Java and Kotlin in your project, you may encounter this kind of error if you are creating a Parcelable Data Class in kotlin and you are using it in Java Class eg Activity or something, it seems to be an issue and its solution is just to use Java POJOs instead if kotlin data class




回答7:


Just found one more cause of this Exception. For some reason, I only got it when activity was restored, but not when it was created for the first time. If your parcelable entity is kotlin data class which is child of some class, and you try to unparcel it, you may get BadParcelableException, Class not found when unmarshalling. Solution is to make such class just class, not data class.



来源:https://stackoverflow.com/questions/28589509/android-e-parcel-class-not-found-when-unmarshalling-only-on-samsung-tab3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!