Error opening SupportMapFragment for second time

Update: As an alternative solution (which I think is much better) you can use a MapView which is described: here

I ran across a similar problem while working with a tabs implementation. With Google Maps V2, you are stuck with the SupportMapFragment, so using the MapView isn't an option. Between juanmeanwhile's post and comment #1 found here (https://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1), I managed to figure out what I was doing wrong.

So, for anyone else getting the Duplicate id error, make sure you declare the fragment programatically, not in XML. This probably means nesting layouts.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="match_parent" >

<!-- Lots of fancy layout -->   

<RelativeLayout
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </RelativeLayout>
</RelativeLayout>

Then you need to create your fragment programatically, but it needs to be done carefully with consideration for the Fragments lifecycle (http://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager()). To ensure everything is created at the right time, your code should look like this (taken from comment #1).

public class MyFragment extends Fragment {

private SupportMapFragment fragment;
private GoogleMap map;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.layout_with_map, container, false);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    FragmentManager fm = getChildFragmentManager();
    fragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
    if (fragment == null) {
        fragment = SupportMapFragment.newInstance();
        fm.beginTransaction().replace(R.id.map, fragment).commit();
    }
}

@Override
public void onResume() {
    super.onResume();
    if (map == null) {
        map = fragment.getMap();
        map.addMarker(new MarkerOptions().position(new LatLng(0, 0)));
    }
}
}

Hopefully this saves some time.


Instead of declaring de SupportMapFragment in layout, do it programatically and be sure you use getChildFragmentMananger instead of the classic getFragmentManager() to create the fragment.

  mMapFragment = SupportMapFragment.newInstance();
    FragmentTransaction fragmentTransaction =
             mMapFragment.getChildFragmentManager().beginTransaction();
     fragmentTransaction.add(R.id.map_root, mMapFragment);
     fragmentTransaction.commit(); 

Keep this SupportMapFragment mMapFragment as you will need it to retrieve the GoogleMap object:

  GoogleMap map = mMapFragment.getMap();

I've spend a half day resolving this trouble and only found a workaround. Override your onCreate method in YourFragment class:

public void onCreate(Bundle savedInstanceState) {
    setRetainInstance(true); 
    super.onCreate(savedInstanceState);     
}

And override your onDestroy method:

@Override
public void onDestroyView() {
    super.onDestroyView();
    try {
        SupportMapFragment fragment = (SupportMapFragment) getActivity()
                                          .getSupportFragmentManager().findFragmentById(
                                              R.id.multi_inns_on_map);
        if (fragment != null) getFragmentManager().beginTransaction().remove(fragment).commit();

    } catch (IllegalStateException e) {
        //handle this situation because you are necessary will get 
        //an exception here :-(
    }
}