谷歌地图代码中的BadParcelableException

运行稍微修改的Google地图示例会在Google地图代码中引发BadParcelableExceptionLatLng类是可以分类的,但是不能被find。 看来,Google地图代码正试图对未被其分割的对象进行拆解。 什么情况下的问题?

 package com.example.mapdemo; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import android.os.Bundle; public class RawMapViewDemoActivity extends android.support.v4.app.FragmentActivity { private MapView mMapView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.raw_mapview_demo); mMapView = (MapView) findViewById(R.id.map); mMapView.onCreate(savedInstanceState); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mMapView.onSaveInstanceState(outState); outState.putParcelable("marker", new LatLng(0, 0)); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); LatLng ll = savedInstanceState.getParcelable("marker"); } } 

 FATAL EXCEPTION: main java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mapdemo/com.example.mapdemo.RawMapViewDemoActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.google.android.gms.maps.model.LatLng at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2832) at android.app.ActivityThread.access$1600(ActivityThread.java:117) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:130) at android.app.ActivityThread.main(ActivityThread.java:3683) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at dalvik.system.NativeStart.main(Native Method) Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.google.android.gms.maps.model.LatLng at android.os.Parcel.readParcelable(Parcel.java:1958) at android.os.Parcel.readValue(Parcel.java:1846) at android.os.Parcel.readMapInternal(Parcel.java:2083) at android.os.Bundle.unparcel(Bundle.java:208) at android.os.Bundle.getBundle(Bundle.java:1078) at com.google.android.gms.maps.internal.MapStateHelper .getParcelableFromMapStateBundle(MapStateHelper.java:41) at maps.y.ae.a(Unknown Source) at maps.y.bm.onCreate(Unknown Source) at com.google.android.gms.maps.internal.IMapViewDelegate$Stub .onTransact(IMapViewDelegate.java:66) at android.os.Binder.transact(Binder.java:279) at com.google.android.gms.maps.internal.IMapViewDelegate$a$a .onCreate(Unknown Source) at com.google.android.gms.maps.MapView$b.onCreate(Unknown Source) at com.google.android.gms.internal.c$3.a(Unknown Source) at com.google.android.gms.internal.ib(Unknown Source) at com.google.android.gms.maps.MapView$aa(Unknown Source) at com.google.android.gms.maps.MapView$aa(Unknown Source) at com.google.android.gms.internal.ca(Unknown Source) at com.google.android.gms.internal.c.onCreate(Unknown Source) at com.google.android.gms.maps.MapView.onCreate(Unknown Source) at com.example.mapdemo.RawMapViewDemoActivity .onCreate(RawMapViewDemoActivity.java:40) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611) ... 12 more 

Solutions Collecting From Web of "谷歌地图代码中的BadParcelableException"

只是添加到现有的答案,在调用mapView.onCreate之前,我一直从保存的状态中删除我的包裹,它工作正常。

然而,添加一个ViewPager到我的片段后,我没有意识到BadParcelableException已经返回,代码使它生产。 事实certificate, ViewPager保存了它的状态,因为它是支持库的一部分,所以Google Map找不到类来解开它。

所以我select了颠倒这个过程,而不是从我知道的Bundle中删除Parcel,我select为地图复制一个新的Bundle来仅仅复制地图的状态。

 private final static String BUNDLE_KEY_MAP_STATE = "mapData"; @Override public void onSaveInstanceState(Bundle outState) { // Save the map state to it's own bundle Bundle mapState = new Bundle(); mapView.onSaveInstanceState(mapState); // Put the map bundle in the main outState outState.putBundle(BUNDLE_KEY_MAP_STATE, mapState); super.onSaveInstanceState(outState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_map, container, false); mapView = (MapView) view.findViewById(R.id.mapView); mapView.getMapAsync(this); Bundle mapState = null; if (savedInstanceState != null) { // Load the map state bundle from the main savedInstanceState mapState = savedInstanceState.getBundle(BUNDLE_KEY_MAP_STATE); } mapView.onCreate(mapState); return view; } 

我试了两个以前的答案没有成功,但我发现了另一个解决方法:

在保存状态时,在将数据添加到Bundle之前,请务必转发MapView.onSaveInstanceState调用(您做得很好):

 @Override public void onSaveInstanceState(Bundle outState) { // Forward the call BEFORE adding our LatLng array, else it will crash : _mapView.onSaveInstanceState(outState); // Put your Parcelable in the bundle: outState.putParcelableArray("myLatLng", new LatLng(0, 0) ); } 

在onCreate / onRestore中恢复状态时,请检查捆绑包是否为空,如果是,则获取包裹,然后在转发呼叫之前将其从包中删除:

 @Override public void onCreate(Bundle savedInstanceState) { // If the bundle is not null, get your Parcelable : LatLng myLatLng = null; if(savedInstanceState != null) { myLatLng = (LatLng) savedInstanceState.getParcelable("myLatLng"); // Remove your Parcelable from the bundle, else it will crash : savedInstanceState.remove("myLatLng"); } // Forward the call : _mapView.onCreate(savedInstanceState); setUpMapIfNeeded(); } 

此问题已在code.google.com上提交,以防您想要对其进行升级。

同时我已经设法解决这个问题,只需将我的Parcelable添加到一个Bundle中,然后将其添加到最终的onSaveInstanceState Bundle中。 这是因为Bundle是MapView的内部ClassLoader的已知类。

我已经创build了两个非常小的util方法来为我做这个。 这是代码

 public static Parcelable unbundleParcelable(String key, Bundle src) { Bundle b = src.getBundle(key); if (b != null) { return b.getParcelable("bundle_parcelable_util_key"); } return null; } public static void bundleParcelable(String key, Bundle dest, Parcelable parcelable) { Bundle b = new Bundle(); b.putParcelable("bundle_parcelable_util_key", parcelable); dest.putBundle(key, b); } 

我修改了以前的一篇文章中的代码来使用我的临时解决scheme。 这是我如何使用它。

 @Override public void onSaveInstanceState(Bundle outState) { // Forward the call BEFORE adding our LatLng array, else it will crash : _mapView.onSaveInstanceState(outState); // Put your Parcelable in the bundle: bundleParcelable("myLatLng", outState, new LatLng(0, 0)); } @Override public void onCreate(Bundle savedInstanceState) { // Forward the call : _mapView.onCreate(savedInstanceState); LatLng myLatLng = null; if(savedInstanceState != null) { // Extract your Parcelable myLatLng = (LatLng) unbundleParcelable("myLatLng", savedInstanceState); } setUpMapIfNeeded(); } 

这应该适用于您在项目中使用的任何自定义Parcelable。

我find了一个解决办法(有点)。 在发生的地方只是尝试第二次。 它总是捕捉exception,第二次问题似乎不在这个地方发生。 这对我有效。

 try { mapIntent.putExtra(Intents.EXTRA_LATLNG, new LatLng( store.getLatitude(), store.getLongitude())); } catch (BadParcelableException e) { mapIntent.putExtra(Intents.EXTRA_LATLNG, new LatLng( store.getLatitude(), store.getLongitude())); } 

我find了一个更简单的解决方法。 在执行任何操作之前,将Fragment或Activity的类加载器提供给该包:

 savedInstanceState.setClassLoader(getClass().getClassLoader()); 

当直接传入MapFragment或MapView的onCreateView或onCreate时,这似乎不起作用,因此您必须手动将地图的CameraPosition分块并将空分组传递给这些函数。

我离开我的应用程序(FragmentActivity与选项卡和每个选项卡中的一个片段)时,我也有一个BadParcelableException。 我通过调用第一个mapmpvMap.onSaveInstanceState(outState);来解决这个问题mapmpvMap.onSaveInstanceState(outState); 然后super.onSaveInstanceState(outState);