Class not found when unmarshalling: android.suppor

2020-02-26 10:06发布

i am using Maps API to create a simple android app and i get a wierd error i can't solve. It usually happens when i rotate my device. I'm using google services 8.4.0

4-23 15:39:47.503 9419-9419/com.licenta.vladut.mmap E/Parcel: Class not found when unmarshalling: android.support.v7.widget.Toolbar$SavedState
                                                               java.lang.ClassNotFoundException: android.support.v7.widget.Toolbar$SavedState
                                                                   at java.lang.Class.classForName(Native Method)
                                                                   at java.lang.Class.forName(Class.java:308)
                                                                   at android.os.Parcel.readParcelableCreator(Parcel.java:2275)
                                                                   at android.os.Parcel.readParcelable(Parcel.java:2239)
                                                                   at android.os.Parcel.readValue(Parcel.java:2146)
                                                                   at android.os.Parcel.readSparseArrayInternal(Parcel.java:2540)
                                                                   at android.os.Parcel.readSparseArray(Parcel.java:1868)
                                                                   at android.os.Parcel.readValue(Parcel.java:2203)
                                                                   at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
                                                                   at android.os.BaseBundle.unparcel(BaseBundle.java:221)
                                                                   at android.os.Bundle.getBundle(Bundle.java:782)
                                                                   at com.google.android.gms.maps.internal.ao.a(:com.google.android.gms.alldynamite:74)
                                                                   at maps.ei.bu.a(Unknown Source)
                                                                   at maps.ei.n.a(Unknown Source)
                                                                   at com.google.android.gms.maps.internal.i$a.onTransact(:com.google.android.gms.alldynamite:107)
                                                                   at android.os.Binder.transact(Binder.java:380)
                                                                   at com.google.android.gms.maps.internal.IMapFragmentDelegate$zza$zza.onCreateView(Unknown Source)
                                                                   at com.google.android.gms.maps.SupportMapFragment$zza.onCreateView(Unknown Source)
                                                                   at com.google.android.gms.dynamic.zza$4.zzb(Unknown Source)
                                                                   at com.google.android.gms.dynamic.zza.zza(Unknown Source)
                                                                   at com.google.android.gms.dynamic.zza.onCreateView(Unknown Source)
                                                                   at com.google.android.gms.maps.SupportMapFragment.onCreateView(Unknown Source)
                                                                   at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
                                                                   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
                                                                   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230)
                                                                   at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2315)
                                                                   at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:120)
                                                                   at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:357)
                                                                   at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
                                                                   at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:80)
                                                                   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
                                                                   at android.view.LayoutInflater.inflate(LayoutInflater.java:482)
                                                                   at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
                                                                   at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
                                                                   at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:276)
                                                                   at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:136)
                                                                   at com.licenta.vladut.mmap.MainActivity.onCreate(MainActivity.java:54)
                                                                   at android.app.Activity.performCreate(Activity.java:6020)
                                                                   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
                                                                   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
                                                                   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2368)
                                                                   at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
                                                                   at android.app.ActivityThread.access$900(ActivityThread.java:149)
                                                                   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290)
                                                                   at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                   at android.os.Looper.loop(Looper.java:135)
                                                                   at android.app.ActivityThread.main(ActivityThread.java:5292)
                                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                                   at java.lang.reflect.Method.invoke(Method.java:372)
                                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
                                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
                                                                Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v7.widget.Toolbar$SavedState" on path: DexPathList[[zip file "/data/data/com.google.android.gms/app_chimera/m/00000000/DynamiteModules-prod.apk"],nativeLibraryDirectories=[/data/data/com.google.android.gms/app_chimera/m/00000000/n/armeabi-v7a, /vendor/lib, /system/lib]]
                                                                at dalvik.system.BaseDexClassLoader.f
04-23 15:39:47.503 9419-9419/com.licenta.vladut.mmap D/AndroidRuntime: Shutting down VM
04-23 15:39:47.505 9419-9419/com.licenta.vladut.mmap E/AndroidRuntime: FATAL EXCEPTION: main
                                                                       Process: com.licenta.vladut.mmap, PID: 9419
                                                                       java.lang.RuntimeException: Unable to start activity ComponentInfo{com.licenta.vladut.mmap/com.licenta.vladut.mmap.MainActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
                                                                           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306)
                                                                           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2368)
                                                                           at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
                                                                           at android.app.ActivityThread.access$900(ActivityThread.java:149)
                                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                           at android.os.Looper.loop(Looper.java:135)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5292)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at java.lang.reflect.Method.invoke(Method.java:372)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
                                                                        Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
                                                                           at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
                                                                           at android.view.LayoutInflater.inflate(LayoutInflater.java:482)
                                                                           at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
                                                                           at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
                                                                           at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:276)
                                                                           at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:136)
                                                                           at com.licenta.vladut.mmap.MainActivity.onCreate(MainActivity.java:54)
                                                                           at android.app.Activity.performCreate(Activity.java:6020)
                                                                           at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
                                                                           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
                                                                           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2368) 
                                                                           at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947) 
                                                                           at android.app.ActivityThread.access$900(ActivityThread.java:149) 
                                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290) 
                                                                           at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                           at android.os.Looper.loop(Looper.java:135) 
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5292) 
                                                                           at java.lang.reflect.Method.invoke(Native Method) 
                                                                           at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908) 
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703) 
                                                                        Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.v7.widget.Toolbar$SavedState
                                                                           at android.os.Parcel.readParcelableCreator(Parcel.java:2289)
                                                                           at android.os.Parcel.readParcelable(Parcel.java:2239)
                                                                           at android.os.Parcel.readValue(Parcel.java:2146)
                                                                           at android.os.Parcel.readSparseArrayInternal(Parcel.java:2540)
                                                                           at android.os.Parcel.readSparseArray(Parcel.java:1868)
                                                                           at android.os.Parcel.readValue(Parcel.java:2203)
                                                                           at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
                                                                           at android.os.BaseBundle.unparcel(BaseBundle.java:221)
                                                                           at android.os.Bundle.getBundle(Bundle.java:782)
                                                                           at com.google.android.gms.maps.internal.ao.a(:com.google.android.gms.alldynamite:74)
                                                                           at maps.ei.bu.a(Unknown Source)
                                                                           at maps.ei.n.a(Unknown Source)
                                                                           at com.google.android.gms.maps.internal.i$a.onTransact(:com.google.android.gms.alldynamite:107)
                                                                           at android.os.Binder.transact(Binder.java:380)
                                                                           at com.google.android.gms.maps.internal.IMapFragmentDelegate$zza$zza.onCreateView(Unknown Source)
                                                                           at com.google.android.gms.maps.SupportMapFragment$zza.onCreateView(Unknown Source)
                                                                           at com.google.android.gms.dynamic.zza$4.zzb(Unknown Source)
                                                                           at com.google.android.gms.dynamic.zza.zza(Unknown Source)
                                                                           at com.google.android.gms.dynamic.zza.onCreateView(Unknown Source)
                                                                           at com.google.android.gms.maps.SupportMapFragment.onCreateView(Unknown Source)
                                                                           at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
                                                                           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
                                                                           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230)
                                                                           at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2315)
                                                                           at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:120)
                                                                           at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:357)
                                                                           at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
                                                                           at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:80)
                                                                        at android.view.LayoutInf

My MainActivity.java is

package com.licenta.vladut.mmap;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;

public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, OnMapReadyCallback {
    GoogleMap mMap;
    private static  final double BM_LAT = 47.6595076, BM_LNG = 23.5631243;
    private Toolbar toolbar;
    private GoogleApiClient mGoogleApiClient;
    private static final String TAG = "SignInActivity";
    private static final int ERROR_DIALOG_REQUEST = 9001;
    private static final int RC_SIGN_IN = 9002;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .addApi(AppIndex.API).build();
        if (checkPlayServices()) {
            setContentView(R.layout.activity_map);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            (MainActivity.this).setSupportActionBar(toolbar);
            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
        } else {
            setContentView(R.layout.activity_main);

        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        //noinspection SimplifiableIfStatement
        if (id == R.id.sign_out) {
            signOut();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void signOut() {
        Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        toSignIn();
                    }


                });
    }

    private void toSignIn() {
        Intent i = new Intent(this, SignInActivity.class);
        startActivity(i);
    }


    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // An unresolvable error has occurred and Google APIs (including Sign-In) will not
        // be available.
        Log.d(TAG, getString(R.string.onConnectionFailed) + connectionResult);
    }

    private boolean checkPlayServices() {
        GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
        int result = googleAPI.isGooglePlayServicesAvailable(this);
        if (result != ConnectionResult.SUCCESS) {
            if (googleAPI.isUserResolvableError(result)) {
                googleAPI.getErrorDialog(this, result,
                        ERROR_DIALOG_REQUEST).show();
            } else {
                Toast.makeText(this, "Nu se poate conecta la Google Play Services!", Toast.LENGTH_SHORT).show();
            }

            return false;
        }

        return true;
    }


    @Override
    public void onMapReady(final GoogleMap map) {
        this.mMap = map;
        gotoLocation(BM_LAT,BM_LNG,18);
    }
    private void gotoLocation(double lat, double lng, float zoom){
        LatLng latLng = new LatLng(lat, lng);
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(latLng,zoom);
        mMap.moveCamera(update);
    }
}

Activity_main.xml is

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    tools:context="com.licenta.vladut.mmap.MainActivity">
    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar"
        />
</RelativeLayout>

activity_map.xml is

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar"
        />
    </fragment>

and finally, toolbar.xml is

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    android:background="?attr/colorPrimary"
    android:id="@+id/toolbar"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
     android:minHeight="?attr/actionBarSize"
    android:layout_width="match_parent"
    android:layout_alignParentStart="true"
    android:elevation="4dp"
    app:popupTheme="@style/AppTheme.PopupOverlay"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
</android.support.v7.widget.Toolbar>

4条回答
何必那么认真
2楼-- · 2020-02-26 10:45

Changing activity_map.xml to this worked, thanks again Mike.

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar" />

    <fragment xmlns:map="http://schemas.android.com/apk/res-auto"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </fragment>
</RelativeLayout>
查看更多
我命由我不由天
3楼-- · 2020-02-26 10:46

I didn't like provided solutions as it imposed on my layouts and architecture.

Here's what I did to make it work. If you look at your stacktrace the ClassNotFoundException is coming from the line on GoogleMaps. So if we just fix that, the issue is gone.

GoogleMaps pukes/throw an error when the savedInstanceState has other items in it besides it's own. The solution is to just give GoogleMaps it's own dedicated bundle.

// class property
private static final String KEY_MAP_SAVED_STATE = "mapState";

// class methods
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mapView = findMapView();  // make your own method here
    Bundle mapState = (savedInstanceState != null)
            ? savedInstanceState.getBundle(KEY_MAP_SAVED_STATE): null;
    mapView.onCreate(mapState);
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Bundle mapState = new Bundle();
    mapView.onSaveInstanceState(mapState);
    outState.putBundle(KEY_MAP_SAVED_STATE, mapState);
}

One thing to note is I'm not using the SupportMapFragment. I'm using a MapView directly. You may have to extend the SupportMapFragment so you can catch the hook methods and provide a blank/clean bundle

查看更多
Lonely孤独者°
4楼-- · 2020-02-26 10:53

Upon rotation, your SupportMapFragment gets destroyed and recreated. Before it's destroyed, it writes its current state to a Parcel, to be used in restoring its state when recreated. The Fragment's saved state will include the state of its child Views, and since you've nested a Toolbar within it, it attempts to save and restore that, as well. The Toolbar class does not have an inner class SavedState necessary for that, so this process fails when trying to restore the Toolbar instance from the Parcel.

The solution is to not nest the Toolbar - or any other View, for that matter - within the <fragment> element. Instead, pull the <include> out of the <fragment>, and put them both in another ViewGroup; for example, a vertical LinearLayout, or a RelativeLayout.

查看更多
家丑人穷心不美
5楼-- · 2020-02-26 10:57

I had a similar problem with my custom view and found this solution. I noticed that this crash occurred when I extended RecyclerView or AppCompatSpinner and needed to save the state. The crash will probably happen for other views as well.

Basically the crash is caused by a bug in AbsSavedState as mentioned here. And the crash only occurs when the constructor of the SavedState is called without a class loader. It seemed like this was an old issue however I started getting crash reports for Android 9 and 10.

So the fix was to change:

public SavedState(Parcel source) {
  super(source);
  //... 
}

to:

public SavedState(Parcel source) {
  super(source, LinearLayoutManager.class.getClassLoader());
  //... 
}

Edit I was on the right track, but then I was looking at some Android code and found out that there was actually a constructor missing that caused the crash. So I had the following constructor for the SavedState:

SavedState(Parcel in)
{
    super(in);
    //...
}

And I needed to add the following:

@RequiresApi(Build.VERSION_CODES.N)
SavedState(Parcel in, ClassLoader loader)
{
    super(in, loader);
    //...
}

And then I needed to change the creator:

public static final Creator<SavedState> CREATOR = new ClassLoaderCreator<SavedState>()
{
    @Override
    public SavedState createFromParcel(Parcel source, ClassLoader loader)
    {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new SavedState(source, loader) : new SavedState(source);
    }

    @Override
    public SavedState createFromParcel(Parcel source)
    {
        return createFromParcel(source, null);
    }

    public SavedState[] newArray(int size)
    {
        return new SavedState[size];
    }
};
查看更多
登录 后发表回答