27

I have a fragment which is a part of Viewpager, and I want to use Google Map V2 inside that fragment. This is what I have tried so far,

In my fragment,

    private SupportMapFragment map;
      private GoogleMap mMapView;

   @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);

        FragmentManager fm = getChildFragmentManager();
        map = (SupportMapFragment) fm.findFragmentById(R.id.map);
        if (map == null) {
            map = SupportMapFragment.newInstance();
            fm.beginTransaction().replace(R.id.map, map).commit();
        }



    }

    @Override
    public void onResume() {
        super.onResume();
        if (mMapView == null) {
            mMapView = map.getMap();
            Marker hamburg = mMapView.addMarker(new MarkerOptions().position(HAMBURG)
                      .title("Hamburg"));
                  Marker kiel = mMapView.addMarker(new MarkerOptions()
                      .position(KIEL)
                      .title("Kiel")
                      .snippet("Kiel is cool")
                      .icon(BitmapDescriptorFactory
                          .fromResource(R.drawable.ic_launcher)));


                  mMapView.moveCamera(CameraUpdateFactory.newLatLngZoom(HAMBURG, 15));

                  // Zoom in, animating the camera.
           mMapView.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);


        }
    }

and in my layout subfragment_info.xml , I have,

<fragment
            android:id="@+id/map"
            class="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layout_alignParentLeft="true"
            android:layout_below="@+id/tableLayout1" />

I can see the map now. But the markers are not showing. I think my Google map mMapView is null. Please help me to get this problem solved. Thanks in advance.

Basim Sherif
  • 5,384
  • 7
  • 48
  • 90

9 Answers9

50

Create a frame for map in which it will be added in your xml layout

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

<!-- The map fragments will go here --> 
</RelativeLayout>

Don't include class="com.google.android.gms.maps.SupportMapFragment" in xml either in your fragment class do get it manually inside onActivityCreated

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


/***at this time google play services are not initialize so get map and add what ever you want to it in onResume() or onStart() **/
}

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

if you guys face any problem Illegal State Exception Occur just write below code

/* * This issue Is tracked in (Google Bugs) * http://code.google.com/p/gmaps-api-issues/issues/detail?id=5064 Added * Code Due to Illegal State Exception Occur when reclicking on tab * * A short-term workaround that fixed it for me is to add the following to * onDetach() of every Fragment which you call */

@Override
    public void onDetach() {
        super.onDetach();

        try {
            Field childFragmentManager = Fragment.class
                    .getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);

        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

//If you want to show map in activity just extend your Activity by //FragmentActivity write code mention below

In onCreate

FragmentManager fm = getSupportFragmentManager();
        fragment = (SupportMapFragment) fm.findFragmentById(R.id.map_container);
        if (fragment == null) {
            fragment = SupportMapFragment.newInstance();
            fm.beginTransaction().replace(R.id.map_container, fragment)
                    .commit();
    }

In onResume

@Override
    protected void onResume() {
        super.onResume();
        if (googleMap == null) {
            initilizeMap();

        }
    }

private void initilizeMap() {
        if (googleMap != null) {

            googleMap = fragment.getMap();
            googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
            googleMap.getUiSettings().setMyLocationButtonEnabled(true);
            googleMap.getUiSettings().setCompassEnabled(true);
            googleMap.getUiSettings().setRotateGesturesEnabled(true);

            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(new LatLng(latitude, longitude)).zoom(10).build();
            googleMap.animateCamera(CameraUpdateFactory
                    .newCameraPosition(cameraPosition));

            // create marker
            MarkerOptions marker = new MarkerOptions().position(new LatLng(
                    latitude, longitude));
            // ROSE color icon
            marker.icon(BitmapDescriptorFactory
                    .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
            // adding marker
            googleMap.addMarker(marker);

            // check if map is created successfully or not
            if (googleMap == null) {
                Toast.makeText(getApplicationContext(),
                        "Sorry! unable to create maps", Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }

Additional help can get from these links
https://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1 https://developers.google.com/maps/documentation/android/map

Ashish Dwivedi
  • 8,048
  • 5
  • 58
  • 78
DeepakPanwar
  • 1,389
  • 14
  • 22
  • Thanks for supporting for my answer. I only answer those questions which i had implemented on my journey of Developing apps. @ Happy developing – DeepakPanwar Aug 15 '14 at 11:53
  • 1
    cannot find getMap(); – Sagar Devanga Jul 01 '15 at 18:37
  • @SagarDevanga this is the code when we want to show map in fragment. Are you doing in fragment ? – DeepakPanwar Jul 01 '15 at 19:13
  • Yup and i found the answer also why getMap is not available. Its because the map is generated dynamically so the the getMap method is not available till the map is available. Since it is not available while we write the code thats why getMap is not available. – Sagar Devanga Jul 02 '15 at 06:02
  • @SagarDevanga yes absolutely map is generated dynamically. Thanks for posting useful comments. – DeepakPanwar Jul 02 '15 at 16:45
12

You have to decide if you create your fragment in code new SupportMapFragment() or inflate from xml class="com.google.android.gms.maps.SupportMapFragment".

Actually you cannot have a Fragment in xml for another Fragment. Read about nested Fragments.

You may follow this comment on how to add nested SupportMapFragment.

MaciejGórski
  • 22,187
  • 7
  • 70
  • 94
8

I had more or less the same problem. I had a Navigation Drawer and I wanted to put the map in a fragment.

I followed this thread (but it is in Spanish): https://groups.google.com/forum/#!msg/desarrolladores-android/1cvqPm0EZZU/Q801Yvb2ntYJ

The clue was (in my opinion) to change the layout.xml file: Instead of a "fragment" inside your "layout subfragment_info.xml" you would need to change to this:

<com.google.android.gms.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />`

Here it is the code inside the thread (you could use it and adapt): https://groups.google.com/d/msg/desarrolladores-android/1cvqPm0EZZU/9srw_9feamUJ

Ignacio Rubio
  • 1,354
  • 14
  • 25
  • 1
    Thank your for this solution. I was also using an navigation drawer and i wanted an separate fragment for the map. Using your solution I managed to make it work ok. This solution also fixes some weird bug when changing the screen orientation(the map is not displayed/rendered, but only the markers on it) – Ionut Negru Jun 08 '14 at 14:41
1

my approach is:

Bundle bundle = new Bundle();
bundle.putInt(MY_ID, id);

FragmentManager fm  = getFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.customer_details_fragment);

fragment = new SalesFragment();
fm.beginTransaction()
  .add(R.id.customer_details_fragment, fragment)
  .commit();

fragment.setArguments(bundle);  
bofredo
  • 2,348
  • 6
  • 32
  • 51
1

For MapFragment

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

In your Fragment Class

map = ((MapFragment) getActivity().getFragmentManager()
            .findFragmentById(R.id.map)).getMap();
    map.addMarker(new MarkerOptions().position(
            new LatLng(13.031902, 80.278823)).title("Marker Title"));

For SupportMapFragment

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

In your Fragment Class

map = ((SupportMapFragment) getActivity().getSupportFragmentManager()
            .findFragmentById(R.id.map)).getMap();
    map.addMarker(new MarkerOptions().position(
            new LatLng(13.031902, 80.278823)).title("Marker Title"));

Note - SupportMapFragment map render once user touchs the map

Rajeshwar
  • 1,471
  • 1
  • 12
  • 13
1

In link , answer for you:

"The problem is that what you are trying to do shouldn't be done. You shouldn't be inflating fragments inside other fragments. From Android's documentation:

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

While you may be able to accomplish the task with the hacks presented here, I highly suggest you don't do it. Its impossible to be sure that these hacks will handle what each new Android OS does when you try to inflate a layout for a fragment containing another fragment.

The only Android-supported way to add a fragment to another fragment is via a transaction from the child fragment manager."

For this problem:

Duplicate ID, tag null, or parent id with another fragment for com.google.android.gms.maps.MapFragment

For me, the best solution are of @DeepakPanwar

Community
  • 1
  • 1
Cícero Moura
  • 2,027
  • 1
  • 24
  • 36
1

For Load map into fragment:

<fragment
    android:id="@+id/fragmentMap1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.SupportMapFragment"/>

For .java:

public class PathFragment extends Fragment {
    View view;
    GoogleMap mMap;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view=inflater.inflate(R.layout.fragment_path,null);
         setupMap();
        return view;
    }

    private void setupMap()
    {
        if (mMap == null)
        {
            mMap = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.fragment_map1)).getMap();
            mMap.getUiSettings().setZoomControlsEnabled(true);
        }

        mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
            @Override
            public void onMapLoaded() {
                getlocation();
            }
        });
    }

    public void getlocation()
    {
        try
        {
            /*Collect Source and destination latitude and longitude
            * To draw Polyline
            * */

            LatLng src = new LatLng(Double.parseDouble(AppGlobal.WorkerHistory.getOrder_lat()),Double.parseDouble(AppGlobal.WorkerHistory.getOrder_lng()));
            LatLng dest =new LatLng(Double.parseDouble(AppGlobal.WorkerHistory.getWorker_lat()),Double.parseDouble(AppGlobal.WorkerHistory.getWorker_lng()));

            //Add Marker
            mMap.addMarker(new MarkerOptions()
                .position(src)
                .title("Source")
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.srcicon)));


            mMap.addMarker(new MarkerOptions()
                .position(dest)
                .title("Destination")
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.desticon)));



            Polyline line = mMap.addPolyline(
                new PolylineOptions().add(
                    new LatLng(src.latitude, src.longitude),
                    new LatLng(dest.latitude, dest.longitude)
                ).width(5).color(Color.RED).geodesic(true)
            );

            //set zoom level
            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            builder.include(src);
            builder.include(dest);
            LatLngBounds bounds = builder.build();

            int padding = 0; // offset from edges of the map in pixels
            CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
            mMap.animateCamera(cu);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
krlzlx
  • 5,752
  • 14
  • 47
  • 55
0

This is how I did it

in layout:

<fragment 
    android:id="@+id/map"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_weight=".90"
      class="com.google.android.gms.maps.SupportMapFragment"
      />

in code:

public class GPS extends FragmentActivity {

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

private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the map.
    if (supportMap == null) {
        // Try to obtain the map from the SupportMapFragment.
        supportMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                .getMap();
        // Check if we were successful in obtaining the map.
        if (supportMap != null) {
            MarkerOptions mo = new MarkerOptions().position( new LatLng( latitude, longitude ) );
            supportMap.addMarker( mo );
        }
    }
}
}

Took me a lot of fiddling, you need just the right combination of things, make sure your class extends FragmentActivity

Patrick
  • 472
  • 2
  • 8
0

If I replace the fragment, where the map fragment is in (in this code example MyFragment) with a different fragment and then come back, I get an IllegalStateException

public class Home_Map extends Fragment {

GoogleMap googleMap;
FragmentManager myFragmentManager;
SupportMapFragment mySupportMapFragment;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
     View rootView = inflater.inflate(R.layout.fragment_home__map, container, false);

     //googleMap.setMyLocationEnabled(true);

        try {
            // Loading map
            initilizeMap();
            googleMap.setMyLocationEnabled(true);

        } catch (Exception e) {
            e.printStackTrace();
        }
    return rootView;
}
 private void initilizeMap() {

        try
        {
        if (googleMap == null) {
            myFragmentManager = getFragmentManager();
            mySupportMapFragment = (SupportMapFragment)myFragmentManager.findFragmentById(R.id.map2);
            googleMap = mySupportMapFragment.getMap();

            if (googleMap == null) {
                Toast.makeText(getActivity().getApplicationContext(),
                        "Sorry! unable to create maps", Toast.LENGTH_SHORT)
                        .show();
            }
        }
        } catch (Exception e) { Toast.makeText(getActivity().getApplicationContext(), ""+e, 1).show();
            // TODO: handle exception
        }
    }

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

        initilizeMap();

    }

   @Override
    public void onDetach() {
        // TODO Auto-generated method stub
        super.onDetach();
          try {
                Field childFragmentManager = Fragment.class
                        .getDeclaredField("mChildFragmentManager");
                childFragmentManager.setAccessible(true);
                childFragmentManager.set(this, null);

            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
    }

    }
Suraj Singh
  • 316
  • 4
  • 10