Issue
I have an issue with my custom fragment with MapView
and CoordinatorLayout
. I have made a simple application to illustrate the same. I have also tried to do the same on a standard Google API demo, and no issue occurred there, but probably that is because they are using MapFragment
but not MapView
.
Below, I have uploaded the code and layouts. At the end there is an error trace also been pasted.
public class BlankFragment extends Fragment implements OnMapReadyCallback {
private MapView mapView;
private Bundle BundleForMap;
@Override
public void onMapReady(GoogleMap googleMap) { }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BundleForMap = savedInstanceState;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank, container, false);
mapView = (MapView) view.findViewById(R.id.map_event_mapview);
mapView.onCreate(BundleForMap);
mapView.getMapAsync(this);
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onDestroy() {
mapView.onDestroy();
super.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
mapView.onSaveInstanceState(savedInstanceState);
super.onSaveInstanceState(savedInstanceState);
}
}
Activity simply just calls that fragment and replaces container view with it:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
BlankFragment blankFragment = new BlankFragment();
fragmentTransaction.replace(R.id.container, blankFragment, "");
fragmentTransaction.commit();
}
And here is the fragment layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mapview_test.BlankFragment">
<com.google.android.gms.maps.MapView
android:id="@+id/map_event_mapview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.CoordinatorLayout
android:id="@+id/map_event_bottom_sheet"
android:layout_height="match_parent"
android:layout_width="match_parent" >
<android.support.v4.widget.NestedScrollView
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="175dp"
android:elevation="16dp"
android:outlineProvider="bounds"
android:background="@android:color/white"
>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:textSize="16sp"
android:id="@+id/testText"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
</FrameLayout>
The problem is obviously with Coordinator layout and how it is Parceled.
Process: com.example.alovita.mapview_test, PID: 12989
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.alovita.mapview_test/com.example.alovita.mapview_test.MainActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.design.widget.CoordinatorLayout$SavedState
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2370)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2432)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3992)
at android.app.ActivityThread.access$1000(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5310)
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:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.design.widget.CoordinatorLayout$SavedState
at android.os.Parcel.readParcelableCreator(Parcel.java:2295)
at android.os.Parcel.readParcelable(Parcel.java:2245)
at android.os.Parcel.readValue(Parcel.java:2152)
at android.os.Parcel.readSparseArrayInternal(Parcel.java:2546)
at android.os.Parcel.readSparseArray(Parcel.java:1874)
at android.os.Parcel.readValue(Parcel.java:2209)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.Bundle.getBundle(Bundle.java:733)
at aac.a(:com.google.android.gms.DynamiteModulesB:74)
at maps.ad.u.a(Unknown Source)
at maps.ad.R.a(Unknown Source)
at wc.onTransact(:com.google.android.gms.DynamiteModulesB:66)
at android.os.Binder.transact(Binder.java:380)
at com.google.android.gms.maps.internal.IMapViewDelegate$zza$zza.onCreate(Unknown Source)
at com.google.android.gms.maps.MapView$zza.onCreate(Unknown Source)
at com.google.android.gms.dynamic.zza$3.zzb(Unknown Source)
at com.google.android.gms.dynamic.zza$1.zza(Unknown Source)
at com.google.android.gms.maps.MapView$zzb.zzbow(Unknown Source)
at com.google.android.gms.maps.MapView$zzb.zza(Unknown Source)
at com.google.android.gms.dynamic.zza.zza(Unknown Source)
at com.google.android.gms.dynamic.zza.onCreate(Unknown Source)
at com.google.android.gms.maps.MapView.onCreate(Unknown Source)
at com.example.alovita.mapview_test.BlankFragment.onCreateView(BlankFragment.java:45)
at android.app.Fragment.performCreateView(Fragment.java:2053)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1869)
at android.app.Activity.performCreateCommon(Activity.java:6860)
at android.app.Activity.performCreate(Activity.java:6867)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2323)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2432)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3992)
at android.app.ActivityThread.access$1000(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5310)
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:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
The problem is with this line:
mapView.onCreate(BundleForMap);
When screen configuration changes, this parameter is obviously not null
and app crashed. When passing here null
instead of bundle, it works fine. When I remove CoordinatorLayout
, app works fine.
Here are my dependencies:
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.example.mapview_test"
minSdkVersion 22
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:support-v4:24.2.0'
compile 'com.android.support:recyclerview-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
compile 'com.google.android.gms:play-services-appindexing:9.4.0'
compile 'com.google.android.gms:play-services-maps:9.4.0'
compile 'com.google.android.gms:play-services-location:9.4.0'
}
I am stuck with this from long time. Any help would be appreciated
Solution
It seems this is well known issue: Android Issue 6237
I have implemented my own solution based on this answer: Android Issue 6237 #C9
Implementation is as follows (based on #C9
answer):
I was able to get around it by saving the MapView's saved state on a separate Bundle and then adding it to the outgoing saved state bundle. Then in onCreate(), I would just grab the MapView's saved state from the incoming one and pass it into its onCreate() method, thus stopping the crashes.
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
final Bundle mapViewSaveState = new Bundle(savedInstanceState);
mapView.onSaveInstanceState(mapViewSaveState);
savedInstanceState.putBundle("mapViewSaveState", mapViewSaveState);
Bundle customBundle = new Bundle();
// put custom objects if needed to customBundle
savedInstanceState.putBundle(ARG_CUSTOM_BUNDLE, customBundle);
super.onSaveInstanceState(savedInstanceState);
}
And then, use that mapViewSaveState
in onCreate
(or onCreateView
if it is a fragment):
mapView.onCreate(savedInstanceState != null ? savedInstanceState.getBundle("mapViewSaveState") : null);
Answered By - rofl
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.