15

少し変更した Google マップの例を実行BadParcelableExceptionすると、Google マップのコードがスローされます。クラスはパーセル可能ですが、LatLng見つかりません。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.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
4

6 に答える 6

30

ここで既存の回答に追加するために、電話をかける前に保存された状態から区画を削除していましたが、mapView.onCreate正常に機能していました。

ただし、 Fragment に a を追加した後、が返され、コードが本番環境に移行したことにViewPager気づきませんでした。BadParcelableExceptionもその状態を保存しているViewPagerことがわかりました。これはサポート ライブラリの一部であるため、Google マップはそれを展開するクラスを見つけることができません。

そこで、私が知っているバンドルからパーセルを削除する代わりに、プロセスを逆にすることを選択しました。マップの状態のみをコピーするマップ用の新しいバンドルを作成することにしました。

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;
}
于 2014-07-09T10:29:56.993 に答える
12

以前の2つの回答を試してみましたが、成功しませんでしたが、別の回避策を見つけました:

状態を保存するときは、データを 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 で状態を復元するときは、バンドルが null でないかどうかを確認します。そうであれば、小包を取得し、コールを転送する前にバンドルから削除します。

@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();
}
于 2013-03-22T14:06:31.977 に答える
3

この問題は、スターを付けたい場合に備えて、code.google.com に提出されています。

それまでの間、最終的な onSaveInstanceState バンドルに追加する前に、Parcelable をバンドルに追加するだけで、この問題を回避することができました。これが機能するのは、Bundle が MapView の内部 ClassLoader によって既知のクラスであるためです。

これを行うために、2 つの非常に小さな 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);
}

以前の投稿のコードを変更して、一時的な解決策を使用しました。これが私がそれを使用する方法です。

@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 で機能するはずです。

于 2013-07-25T12:40:06.460 に答える
0

アプリを離れるときに、BadParcelableException も発生しました (タブを含む FragmentActivity と各タブに Fragment があります)。mapmpvMap.onSaveInstanceState(outState);最初に電話してから電話することでこれを解決しましたsuper.onSaveInstanceState(outState);

于 2013-04-18T15:27:28.117 に答える
0

回避策を見つけました(ちょっと)。それが起こった場所で、もう一度やってみてください。常に例外をキャッチし、2 回目はこの場所で問題が発生していないようです。それは私のために働いた。

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()));
}
于 2013-01-11T18:05:12.513 に答える
0

これに対するより簡単な回避策を見つけました。そのような操作を実行する前に、フラグメントまたはアクティビティのクラスローダーをバンドルに提供します。

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

ただし、これは MapFragment または MapView の onCreateView または onCreate に直接渡す場合には機能しないようです。そのため、マップの CameraPosition を手動で分割し、それらの関数に null バンドルを渡す必要があります。

于 2013-03-20T17:32:14.110 に答える