juliano.net
juliano.net

Reputation: 8177

App crashes with FragmentManager Replace when using GoogleMaps

I'm using the following code to load fragments depending on which item has been selected on NavigationDrawer, however the MapFragment contains Google Maps fragment inside of it and it crashes after trying to open it for the second time.

Here's the code I'm using:

@Override
    public void onNavigationDrawerItemSelected(int position) {
        // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
        if (position == 0) {
            fragmentManager.beginTransaction()
                    .replace(R.id.container, MapFragment.newInstance("a", "b"))
                    .commit();

        }
        else {
            fragmentManager.beginTransaction()
                    .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
                    .commit();
        }
    }

And here's the log:

03-01 14:18:25.870  27175-27175/com.br.appname E/﹕ Device driver API match
    Device driver API version: 23
    User space API version: 23
03-01 14:18:25.870  27175-27175/com.br.appname E/﹕ mali: REVISION=Linux-r3p2-01rel3 BUILD_DATE=Wed Oct 30 09:36:10 KST 2013
03-01 14:19:12.655  27175-27175/com.br.appname E/AndroidRuntime﹕ FATAL EXCEPTION: main
    android.view.InflateException: Binary XML file line #13: Error inflating class fragment
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:719)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:769)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
            at com.br.appname.fragments.MapFragment.onCreateView(MapFragment.java:74)
            at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
            at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
            at android.os.Handler.handleCallback(Handler.java:730)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5419)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.IllegalArgumentException: Binary XML file line #13: Duplicate id 0x7f070055, tag null, or parent id 0x7f070054 with another fragment for com.google.android.gms.maps.MapFragment
            at android.app.Activity.onCreateView(Activity.java:4971)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:695)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:769)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
            at com.br.appname.fragments.MapFragment.onCreateView(MapFragment.java:74)
            at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
            at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
            at android.os.Handler.handleCallback(Handler.java:730)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5419)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
            at dalvik.system.NativeStart.main(Native Method)

This happens only with the MapFragment. PlaceholderFragment works just fine.

UPDATE

fragment_map.xml

<RelativeLayout 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.br.remotepark.fragments.MapFragment">

    <com.sothree.slidinguppanel.SlidingUpPanelLayout
        android:id="@+id/sliding_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom">

        <fragment
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name="com.google.android.gms.maps.MapFragment" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#eee"
            android:orientation="vertical"
            android:clickable="true"
            android:focusable="false">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="68dp"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/name"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:textSize="14sp"
                    android:gravity="center_vertical"
                    android:paddingLeft="10dp" />

                <Button
                    android:id="@+id/follow"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:textSize="14sp"
                    android:gravity="center_vertical|right"
                    android:paddingRight="10dp"
                    android:paddingLeft="10dp" />

            </LinearLayout>
        </LinearLayout>

    </com.sothree.slidinguppanel.SlidingUpPanelLayout>

</RelativeLayout>

Upvotes: 1

Views: 2903

Answers (1)

MaciejG&#243;rski
MaciejG&#243;rski

Reputation: 22232

Duplicate ID issue is related to incorrect way of using nested fragments.

From: http://developer.android.com/about/versions/android-4.2.html#NestedFragments

Note: You cannot inflate a layout into a fragment when that layout includes a <fragment>. Nested fragments are only supported when added to a fragment dynamically.

So your fragment_map.xml cannot directly contain com.google.android.gms.maps.MapFragment. Replace it with FrameLayout with id map_container and try something like this:

public class MyFragmentWithMap extends Fragment {

    private MapFragment fragment;
    private GoogleMap map;

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

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

    @Override
    public void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    // ...
}

Note the use of getChildFragmentManager.

Upvotes: 3

Related Questions