Error opening SupportMapFragment for second time
Solution 1
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();
Solution 2
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.
Solution 3
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 :-(
}
}
Solution 4
I had passed all this day looking for the solution to this problem, reading all the workaroung here, and I found this way to solve the problems. I will post all the code, because this question lacks a complete answer, just some tiny snippet that does match a full scenario and does help anybody.
public class LocationFragment extends Fragment implements View.OnClickListener {
private GoogleMap googleMap;
private static View rootView;
private SupportMapFragment supportMapFragment;
public LocationFragment() {
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
@Override
public void onCreate(Bundle savedInstanceState) {
setRetainInstance(true);
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(savedInstanceState == null) {
if (rootView != null) {
ViewGroup parent = (ViewGroup) rootView.getParent();
if (parent != null)
parent.removeView(rootView);
}
try{
if(rootView == null)
{
rootView = inflater.inflate(R.layout.fragment_location, container, false);
}
supportMapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.map);
LocationUtility locationUtility = LocationUtility.getInstance(context);
GoogleMap googleMap = locationUtility.initilizeMap(supportMapFragment);
//More code
} catch (Exception e)
{
e.printStackTrace();
}
}
return rootView;
}
}
By debugging this, you will notice that it does not matter how the fragment operates, you dont need botter for the onDestroyMethod, etc, since the validation of null, just operates with the current instance of the object.
Enjoy! ;)
Solution 5
I ran into this issue and found in my android logs that my hardware acceleration was not turned on. After I turned it on in my AndroidManifest I was displaying the maps multiple times was no longer an issue. I was using an x86 emulator.
Klaasvaak
Updated on July 13, 2022Comments
-
Klaasvaak almost 2 years
When opening my SupportMapFragment (Android maps v2) for a second time (calling setContentView) I get the following error:
01-28 16:27:21.374: E/AndroidRuntime(32743): FATAL EXCEPTION: main 01-28 16:27:21.374: E/AndroidRuntime(32743): android.view.InflateException: Binary XML file line #6: Error inflating class fragment 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.View.inflate(View.java:16119) 01-28 16:27:21.374: E/AndroidRuntime(32743): at mypackage.MyView.<init>(HitsView.java:26) 01-28 16:27:21.374: E/AndroidRuntime(32743): at mypackage.MenuListFragment.onItemClick(MenuListFragment.java:133) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AdapterView.performItemClick(AdapterView.java:298) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AbsListView.performItemClick(AbsListView.java:1086) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2855) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AbsListView$1.run(AbsListView.java:3529) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.os.Handler.handleCallback(Handler.java:615) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.os.Handler.dispatchMessage(Handler.java:92) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.os.Looper.loop(Looper.java:137) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.app.ActivityThread.main(ActivityThread.java:4745) 01-28 16:27:21.374: E/AndroidRuntime(32743): at java.lang.reflect.Method.invokeNative(Native Method) 01-28 16:27:21.374: E/AndroidRuntime(32743): at java.lang.reflect.Method.invoke(Method.java:511) 01-28 16:27:21.374: E/AndroidRuntime(32743): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 01-28 16:27:21.374: E/AndroidRuntime(32743): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 01-28 16:27:21.374: E/AndroidRuntime(32743): at dalvik.system.NativeStart.main(Native Method) 01-28 16:27:21.374: E/AndroidRuntime(32743): Caused by: java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate id 0x7f04003b, tag null, or parent id 0x0 with another fragment for com.google.android.gms.maps.SupportMapFragment 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:285) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) 01-28 16:27:21.374: E/AndroidRuntime(32743): ... 20 more
The XML file:
<?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" > <fragment android:id="@+id/hits_map" android:layout_width="match_parent" android:layout_height="wrap_content" class="com.google.android.gms.maps.SupportMapFragment" map:mapType="normal" map:uiZoomControls="false" map:uiZoomGestures="true" map:cameraZoom="13" map:uiRotateGestures="true" map:uiTiltGestures="true"/> </RelativeLayout>
MyView.class:
public class MyView extends RelativeLayout { private GoogleMap map; public MyView(Context context, FragmentActivity activity) { super(context); inflate(activity, R.layout.activity_hits, this); this.map = ((SupportMapFragment) activity.getSupportFragmentManager() .findFragmentById(R.id.hits_map)).getMap(); } }
I have no idea what this error means. Can someone explain this?
-
CommonsWare about 11 yearsDo you have a
View
trying to inflate a layout containing a fragment? If so, why? -
Klaasvaak about 11 yearsI am. This is not the right way to use it? I am using SlidingMenu. In their docs they say setContentView needs to be called to show the main view. And the main view in this case is a view containing a fragment. link: github.com/jfeinstein10/SlidingMenu#simple-example
-
CommonsWare about 11 yearsI certainly would never do that.
-
Thomas Kaliakos about 11 yearsDid you eventually solve it?
-
Klaasvaak about 11 yearsI used the MapView instead, I actually did not know there was a MapView as well.
-
Trino EGlez over 10 years[This is a link that will help you, I was getting the same problem but this worked for me :)][1] [1]: stackoverflow.com/questions/14083950/…
-
jimbo82 over 10 yearsI think this is the best solution: stackoverflow.com/a/19128882/1932352
-
-
Ben Sewards almost 11 yearsWill this retain the maps instance across all fragments? Or will it be destroyed after onPause()?
-
Murphy over 10 yearsFYI you're not stuck with SupportMapFragment, MapView still exists and is fully functional: developers.google.com/maps/documentation/android/reference/com/…
-
Kaleb over 10 yearsI think if you are using a Fragment you are in-fact stuck with MapFragment, and really SupportMapFragment if you want to support Honeycomb. If you are using an Activity, this is not the case and you can use a MapView (although I have no personally confirmed this). So, in my example, you are basically stuck with that implementation. If you were to use an Activity, you could use the MapView but you would still need to manage the life cycle.
-
alicanbatur over 10 yearsIt does not solve the problem.It still crashes when i run it again.
-
alicanbatur over 10 years@Kaleb yes, but i fixed it. I tried lots of things, and finally i solve it. But, i really don't get how i fixed that.
-
jimpanzer over 10 years@Kaleb, thanks for idea. But really, I think google hate all of us.
-
Valerio Santinelli over 10 yearsThis answer lets you define your child fragments in XML layouts, which I find more manageable than having to replace pieces of layout with fragments programmatically.
-
jiahao over 10 yearsThe code generates an error, which has been solved here: stackoverflow.com/questions/15207305/… (Markus answer)
-
Jaroslav over 10 yearsplease pay attention to exception handling block, because you have risks to loose object's state!! This is why it's called workaround
-
Aiden Fry almost 10 yearsYes, you need to wait for a run before the map gets initialised. I use a delay handler to grab a reference to the map after 10 milliseconds, alternatively use the lifecycle to your advantage. i.e. commit the fragment in onCreate and then grab a reference to the map in onResume.
-
Analizer almost 10 yearsinstead if the try-catch block I use if (f != null && f.isResumed()) {}, it works for me
-
TheDevMan over 9 years@Jaroslav: At what stage will I get an exception?
-
Marcelo over 9 yearsAfter searching like a crazy over the web, this solution worked for me. Thanks!
-
gorbos over 9 yearsThis also works for me and I think the best, based on the answers I saw myself that doesn't requires a MapView.
-
Jaroslav over 9 years@TheDevMan - for instance on display rotation } catch (IllegalStateException e) { //handle this situation because you are necessary will get //an exception here :-( }
-
Jaroslav over 9 yearsPlease use this approach to solve the problem described above. And don't forget to delete setRetainInstance(true) in onCreate method code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1
-
ButterBeast about 9 yearsIt worked for me! Thenk you, this should be the right answer.
-
Gabriel Kaffka about 9 years@juanmeanwhile , you should use getMapAsync() instead. MapFragment
-
Nicks over 8 yearsHi, can you have a look on my problem, Its similar to what you explained, but not working for me. will be a great favor. Here is the link:-- stackoverflow.com/questions/32240138/…
-
Robert over 8 yearsThanks a bunch!! I have been stuck with this issue for over a week. Though I am using Xamarin Android (C#) but your solution worked perfectly!
-
voghDev over 7 yearsHave you managed to add "My location" button in the mapView? and also highlight the current user location in real time?
-
itzhar almost 7 yearsthanks a lot. I have view pager with 3 fragments, and this was exactly what i need