1

I received a null pointer exception when getting android google maps in a fragment. The error is at the line findFragmentById.I tried using if (mMap != null) and it indicates that the map is still null. What can I do to resolve this?

In MapActivity.java,

//Relevant imports
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
enter code here
public class MapView extends Fragment {

GoogleMap mMap;
LatLng mLocation = new LatLng(1.379348, 103.849876);

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

        View rootView = inflater.inflate(R.layout.map_view, container, false);

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

        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        //Zoom
        mMap.getUiSettings().setZoomControlsEnabled(true);

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLocation, 17));
        Marker mMarker = mMap.addMarker(new MarkerOptions()
        .position(mLocation)
        .title("School")
        .snippet("NTU")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));

        mMap.setOnMarkerClickListener(new OnMarkerClickListener()
        {
            public boolean onMarkerClick(Marker marker){
                Toast.makeText(getActivity().getApplicationContext(), "Welcome to " + marker.getTitle(), Toast.LENGTH_LONG);

                return false;
            }
        });

        mMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener(){

            @Override
            public void onInfoWindowClick(Marker arg0) {
                // TODO Auto-generated method stub

            }
        });

        return rootView;
    }

}

In map_view.xml,

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.MapFragment" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />
</RelativeLayout>
Enovyne
  • 195
  • 1
  • 7
  • 20
  • when you inflate the view, it is not added to the hierarchy yet. therefore, findFragmentById cannot work. You'll notice that the tutorial is using an activity, and finding the fragment only after the content view is set. – njzk2 Jul 19 '15 at 04:03
  • if you really want to put it in a fragment, use child fragment manager, and move the map init code to `onActivityCreated` or `onStart` – njzk2 Jul 19 '15 at 04:06

2 Answers2

2

In order to have a SupportMapFragment nested inside a Fragment, you need to use getChildFragmentManager() instead of getFragmentManager().

So, you would change this:

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

To this, and also move all of the code referencing mMap to onResume():

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

If you go this route you will also need to fix your layout xml to use a SupportMapFragment:

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

However, it would be best to not have nested Fragments if you don't need to, since it can lead to other problems.

A better approach is just to make the Fragment extend SupportMapFragment. Doing it this way, you don't even need a layout xml file.

Example:

public class MapView extends SupportMapFragment 
                                    implements OnMapReadyCallback {

    private GoogleMap mMap;
    private Marker marker;


    public MapView() {
    }

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

        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        if (mMap == null) {

            getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        mMap = googleMap;
        setUpMap();
    }

    private void setUpMap() {

        mMap.setMyLocationEnabled(true);
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        mMap.getUiSettings().setMapToolbarEnabled(false);

    }


}
Community
  • 1
  • 1
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
0

Can you please try this way ?

 <com.google.android.gms.maps.MapView
      android:id="@+id/mapView"
      android:layout_width="match_parent"
      android:layout_height="match_parent" />

Activity or Fragment:

private GoogleMap mMap;
private MapView mapView;

on onCreate():

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

on onResume()

@Override
    public void onResume() {
       if(mapView!=null){
            mapView.onResume();
        }
        super.onResume();

    }

on onDestroy()

    @Override
    public void onDestroy() {

        if(mapView!=null){
            mapView.onDestroy();
        }

        super.onDestroy();
    }

on onLowMemory()

@Override
    public void onLowMemory() {

        if(mapView!=null){
            mapView.onLowMemory();
        }

        super.onLowMemory();
    }

Add new method:

private void initializaMap(View rootView, Bundle savedInstanceState){
        MapsInitializer.initialize(getActivity());
        switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity())) {
            case ConnectionResult.SUCCESS:
                mapView = (MapView) rootView.findViewById(R.id.mapView);
                mapView.onCreate(savedInstanceState);

                if (mapView != null) {
                    mMap = mapView.getMap();
                    mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                    UiSettings mUiSettings = mMap.getUiSettings();
                    mMap.setMyLocationEnabled(true);
                    mMap.animateCamera(CameraUpdateFactory.zoomTo(zoomLevel));
                    mUiSettings.setCompassEnabled(true);
                    mUiSettings.setMyLocationButtonEnabled(false);
                    mMap.setOnMarkerClickListener(this);
                }
                break;
            case ConnectionResult.SERVICE_MISSING:
                break;
            case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
                break;
            default:
        }
    }

Hope this will help you.

Hiren Patel
  • 52,124
  • 21
  • 173
  • 151