web-dev-qa-db-ja.com

Android E / Parcel:マーシャリング解除時にクラスが見つかりません(Samsung Tab3のみ)

4.4.2を実行しているSamsung Tab3デバイスでのみ、このエラーが発生する理由を解決できませんでしたか? MainActivityが別のアクティビティを開始し、次のようにインテントの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];
        }
    };
}

繰り返しになりますが、これはSamsung Tab3デバイスでのみ表示されますが、これが作業に必要なデバイスです。 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)
45
J Avery

何らかの奇妙な理由で、クラスローダーが適切にセットアップされていないようです。

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

または、小包をバンドルにラップします。

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");
72
David Wasser

私の場合、内部的に新しいバンドルを自動作成する新しいIntent()。putExtra(key、parcelable)はアンマーシャルエラーを引き起こします理由はわかりませんので、自分で新しいバンドルを作成し、その上にパーセルを追加して追加する必要がありましたインテントにバンドルします。そうすることで問題を解決します。

8
Flux

ここで答えをより簡潔で明確にしようとしています-

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

最近のSamsung 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);

そして、アクティビティで小包を読み戻します。

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

これがお役に立てば幸いです。

4
crazypeter

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")
1
Blake

この例外のもう1つの原因が見つかりました。何らかの理由で、アクティビティが復元されたときにのみ取得できましたが、初めて作成されたときは取得できませんでした。パーセル可能なエンティティがclassの子であるkotlin data classであり、それをアンパーセルしようとすると、アンマーシャリング時にBadParcelableException、Class not foundが発生する場合があります。解決策は、そのようなクラスをdata classではなくclassにすることです。

0
Shramov

プロジェクトでJavaとKotlinの両方を使用している場合、kotlinでParcelable Data Classを作成し、Java Class eg Activity or somethingで使用していると、この種のエラーが発生する可能性があります問題とその解決策は、kotlinデータクラスの代わりにJava POJOsを使用することです

0
Ahmed Elshaer