3

I have implemented a google map in my android project in a fragment. When I load the fragment the first time it calls an async tasks and loads the markers and displays correctley.

But if I move to another fragment and then come back to the map it crashes once it tries to load again.

My error is:

android.view.InflateException: Binary XML file line #4: Error inflating class fragment
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at com.beerportfolio.beerportfoliopro.BreweryMap.onCreateView(BreweryMap.java:28)
       at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
       at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
       at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:446)
       at android.os.Handler.handleCallback(Handler.java)
       at android.os.Handler.dispatchMessage(Handler.java)
       at android.os.Looper.loop(Looper.java)
       at android.app.ActivityThread.main(ActivityThread.java)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
       at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: java.lang.IllegalArgumentException: Binary XML file line #4: Duplicate id 0x7f09003f, tag null, or parent id 0x0 with another fragment for com.google.android.gms.maps.SupportMapFragment
       at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:296)
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at com.beerportfolio.beerportfoliopro.BreweryMap.onCreateView(BreweryMap.java:28)
       at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
       at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
       at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:446)
       at android.os.Handler.handleCallback(Handler.java)
       at android.os.Handler.dispatchMessage(Handler.java)
       at android.os.Looper.loop(Looper.java)
       at android.app.ActivityThread.main(ActivityThread.java)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
       at dalvik.system.NativeStart.main(NativeStart.java)

In the error it says something about a duplicate so I assumed it was having trouble re-loading the map markers, so I tried to place a clear markers at the start but that doesn't fix it.

My code for my map is:

public class BreweryMap extends Fragment {

    public BreweryMap(){}

    String beerId = "";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.activity_brewmap, container, false);
        setHasOptionsMenu(true);

        //get user information
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        String userName = prefs.getString("userName", null);
        String userID = prefs.getString("userID", null);


        GoogleMap mMap;
        mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();

        mMap.clear();

        //add url
        String url = "myURL";

        //call async to get breweries to add to
        new GetVisitedBreweries(getActivity(), mMap).execute(url);


        return rootView;
    }

The async tasks gets JSON parses the information and loads the map markers onto the map.

Blo
  • 11,903
  • 5
  • 45
  • 99
Mike
  • 6,751
  • 23
  • 75
  • 132
  • Can you please post your manifest too.. – Lal May 15 '14 at 17:14
  • See this [link](http://stackoverflow.com/a/14690441/3168859) and this [link](http://stackoverflow.com/a/19815266/3168859) too..Tell me if they helps..please.. – Lal May 15 '14 at 17:16
  • Yes the answer with 50 votes was super helpful, thank you very very much – Mike May 15 '14 at 17:23
  • 1
    Can you please accept me if i add that as my answer..please... – Lal May 15 '14 at 17:24

3 Answers3

3

From this link..Check it..

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.

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)));
    }
}
}
Community
  • 1
  • 1
Lal
  • 14,726
  • 4
  • 45
  • 70
  • Real quick any ideas on how to center the map on multiple markers? The only help I found on stack seemed to be out of context and I couldnt follow it. – Mike May 15 '14 at 17:29
  • I didnt get you @Mike – Lal May 15 '14 at 17:29
  • Do you know how to center a map on a bunch of markers? – Mike May 15 '14 at 17:30
  • Center a map on a bunch of markers???Why do you want that...You can center a marker on a map..Try that..From what i've understood from ur question.. – Lal May 15 '14 at 17:33
  • I have a bunch of markers, and I want the view to see all of them. http://stackoverflow.com/questions/23685069/center-android-google-map-on-group-of-markers – Mike May 15 '14 at 17:34
0

I recently ran into a nearly identical problem and the code below was my solution. You should be able to just rename things and add in your extra code to do what you want to do.

public class TrackerFragment extends Fragment {

private SupportMapFragment mMap;
private GoogleMap googleMap;
//private boolean chronoRunning = false;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.frag3_action, container, false);

    activityBody();
    return rootView;
}

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

@Override
public void onResume() {
    super.onResume();
    if (googleMap == null) {
        googleMap = mMap.getMap();
        googleMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)));
    }
}
Patr3xion
  • 122
  • 2
  • 15
  • So I need the two overides for onACtivtyCreated and onResume? COuld you explain a little what's going on. I am a bit confused – Mike May 15 '14 at 16:32
  • I just tried this and it didnt work: https://gist.github.com/anonymous/ea1e424b91c2c2814b22 – Mike May 15 '14 at 16:36
  • Mike, as you can see, the answer above that you accepted as correct is almost identical to what I showed. Please refer to that or mine for similar issues in the future. – Patr3xion May 16 '14 at 03:23
0

I am too late, but this worked after lot of search

Do It Programmatically, use normal FrameLayout in xml.

SupportMapFragment mapFragment = SupportMapFragment.newInstance();
    FragmentTransaction fragmentTransaction =
            getChildFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.map, mapFragment);
    fragmentTransaction.commit();
    mapFragment.getMapAsync(this);
architjn
  • 1,397
  • 2
  • 13
  • 30