我使用Maps API创建一个简单的Android应用程序,我得到一个我无法解决的奇怪错误。它通常发生在我旋转设备时。我正在使用谷歌服务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
我的MainActivity.java是
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是
<?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是
<?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>
最后,toolbar.xml是
<?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>
答案 0 :(得分:9)
我不喜欢提供的解决方案,因为它强加于我的布局和架构。
这就是我做的工作。如果查看堆栈跟踪,ClassNotFoundException将来自GoogleMaps上的一行。因此,如果我们解决这个问题,问题就会消失。
GoogleMaps pukes /在savedInstanceState中包含其他项目时会抛出错误。解决方案是给GoogleMaps自己专用的捆绑包。
// 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);
}
需要注意的一点是我没有使用SupportMapFragment。我正在使用MapView。您可能必须扩展SupportMapFragment,以便捕获钩子方法并提供空白/清理包
答案 1 :(得分:3)
轮换后,您的SupportMapFragment
会被销毁并重新创建。在它被销毁之前,它会将其当前状态写入Parcel
,以便在重新创建时用于恢复其状态。 Fragment
已保存状态将包含其子View
的状态,并且由于您已在其中嵌套了Toolbar
,因此它也会尝试保存和恢复该状态。 Toolbar
类没有必要的内部类SavedState
,因此尝试从Toolbar
恢复Parcel
实例时此过程失败。
解决方案是不在Toolbar
元素内嵌套View
- 或任何其他<fragment>
。相反,将<include>
拉出<fragment>
,并将它们放在另一个ViewGroup
中;例如,垂直LinearLayout
或RelativeLayout
。
答案 2 :(得分:2)
将activity_map.xml更改为此工作,再次感谢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 :(得分:0)
我的自定义视图存在类似的问题,并找到了this解决方案。 我注意到,当我扩展 RecyclerView 或 AppCompatSpinner 并需要保存状态时,就会发生此崩溃。崩溃也可能发生在其他视图上。
基本上,崩溃是由here中提到的AbsSavedState中的错误引起的。 只有在没有类加载器的情况下调用SavedState的构造函数时,才会发生崩溃。看来这是一个老问题,但是我开始获取Android 9和10的崩溃报告。
所以解决方法是更改:
public SavedState(Parcel source) {
super(source);
//...
}
收件人:
public SavedState(Parcel source) {
super(source, LinearLayoutManager.class.getClassLoader());
//...
}
修改 我在正确的轨道上,但是随后我看着一些Android code,发现实际上缺少构造函数,导致崩溃。因此,我为SavedState使用了以下构造函数:
SavedState(Parcel in)
{
super(in);
//...
}
我需要添加以下内容:
@RequiresApi(Build.VERSION_CODES.N)
SavedState(Parcel in, ClassLoader loader)
{
super(in, loader);
//...
}
然后我需要更改创建者:
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];
}
};