2012-12-16 11 views
14

Laufen leicht modifizierte Beispiel von Google Maps wirft BadParcelableException in der Google Maps-Code. Die Klasse LatLng ist parzellierbar, kann jedoch nicht gefunden werden. Es scheint, dass Google Maps-Code versucht, das Objekt zu entpacken, das nicht von ihm parzelliert wurde. In welchen Fällen ist das Problem?BadParcelableException in Google Maps Code

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.i.b(Unknown Source) 
    at com.google.android.gms.maps.MapView$a.a(Unknown Source) 
    at com.google.android.gms.maps.MapView$a.a(Unknown Source) 
    at com.google.android.gms.internal.c.a(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 
+0

wo ist RawMapViewDemoActivity.java:40 Linie in Ihrem Code –

+0

mMapView.onCreate (savedInstanceState); Entschuldigung, ich habe den Code kurz bearbeitet. – user1611728

+0

Wenn Sie 'mMapView.onCreate (savedInstanceState);' line kommentieren, dann funktioniert es oder nicht? –

Antwort

0

ich eine Abhilfe (ein bisschen) gefunden. An dem Ort, an dem es passiert, versuche es einfach ein zweites Mal. Es fängt immer die Ausnahme und das zweite Mal scheint das Problem an diesem Ort nicht zu passieren. Das hat für mich funktioniert.

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())); 
} 
0

Ich habe eine einfachere Workaround zu diesem gefunden. Die Bereitstellung Ihr Fragments oder Aktivität des Class Loader auf das Bündel, bevor Sie Vorgänge als solches perfoming:

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

Dies nicht zu funktionieren scheint, wenn sie direkt in die MapFragment oder MapView des onCreateView oder onCreate obwohl vorbei, so dass man von Hand haben, würde packen Sie die CameraPosition der Karte aus und übergeben Sie ein Null-Bündel in diese Funktionen.

+0

Haben Sie ein Beispiel für die beschriebene Problemumgehung? – speedynomads

12

Ich habe versucht, die beide bisherigen Antworten ohne Erfolg, aber ich fand eine andere Lösung:

Wenn der Sparzustand, vorsichtig sein, den MapView.onSaveInstanceState Anruf weiterleiten, bevor Sie Ihre Daten an den Bundle Zugabe (du hast es gut) :

@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)); 
} 

wenn der Staat in der onCreate/onRestore wiederherstellen, prüfen sie, ob das Bündel nicht null ist, wenn ja, Ihr Paket erhalten, und es dann aus dem Bündel entfernen, bevor die Anrufumleitung:

@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(); 
} 
+0

Dieser Fix funktioniert für mich! thx – Sulfkain

+0

Sie sparen mein Leben! :) – IlyaEremin

0

Ich hatte auch eine BadParcelableException, als ich meine App verließ (FragmentActivity mit Tabs und einem Fragment in jedem Tab). Ich löste dies, indem zunächst mapmpvMap.onSaveInstanceState(outState); aufrufen und dann super.onSaveInstanceState(outState);

3

Dieses Problem als auf code.google.com here im Fall eingereicht Sie würde es zu spielen.

In der Zwischenzeit habe ich es geschafft, dieses Problem zu umgehen, indem ich einfach mein Parcelable zu einem Bundle hinzufüge, bevor ich es zum finalen onSaveInstanceState Bundle hinzufüge. Dies funktioniert, da ein Bundle eine bekannte Klasse des MapView-internen ClassLoaders ist.

Ich habe zwei sehr kleine util-Methode erstellt, um dies für mich zu tun. Hier ist der Code

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

Ich habe den Code in einem der vorherigen Post geändert, um meine temporäre Lösung zu verwenden. Hier ist, wie ich es benutze.

@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(); 
} 

Dies sollte für jedes benutzerdefinierte Parcelable funktionieren, das Sie in Ihrem Projekt verwenden.

+0

Perfekt, Ihre Antwort hat funktioniert. –

+0

Nun, ich bin froh, dass der Code für jemanden nützlich war. Prost! –

31

Nur um die vorhandenen Antworten hier hinzuzufügen, hatte ich meine Pakete aus dem gespeicherten Zustand vor dem Aufruf mapView.onCreate entfernt und es funktionierte gut.

Jedoch nach dem Hinzufügen einer ViewPager zu meinem Fragment habe ich nicht realisiert, dass die BadParcelableException zurückgekehrt war und der Code es zur Produktion gemacht hat. Es stellt sich heraus, dass die ViewPager ihren Status ebenfalls speichert und Google Map die Klasse nicht finden kann, weil sie Teil der Support-Bibliothek ist.

Also entschied ich mich, den Prozess umzukehren, anstatt Parzellen aus dem Bundle, das ich kannte, zu entfernen, entschied ich mich, ein neues Bündel für die Karte zu erstellen, die nur den Kartenstatus kopiert.

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; 
} 
+0

Es scheint ein laufender Thread darüber zu sein: https://code.google.com/p/gmaps-api-issues/issues/detail?id=6237#c9 Dies ist eine vernünftige Antwort und funktionierte gut für mich –

+0

Vielen Dank! Arbeitete perfekt !! –