Search code examples
androidapinullpointerexceptionmapsversions

GetMap() return null on Android API > 15 but works perfectly fine on equal or lower version


I call a map which is inside a fragment. It works on my smartphone which is API 15 (Jelly Bean) but not on higher API. I get a NullPointerException and the application crashes. I think that the problem comes from the layout that is not ready when I try getMap(). I tried all kind of things but nothing worked. I also saw that the getMap() method has been recently deprecated.

Here is the part of my codes

The layout :

<FrameLayout
    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="fr.irseem.ping32.smartp3.fragments.LocationFragment">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:map="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map_view"
        tools:context="fr.irseem.ping32.MapsActivity"
        android:name="com.google.android.gms.maps.MapFragment" />

</FrameLayout>

The LocationFragment where I put the map :

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

    View v = inflater.inflate(R.layout.fragment_location, container, false);

    // Initializing array List
    markerPoints = new ArrayList<LatLng>();

    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    mapFragment = (MapFragment) getFragmentManager()
            .findFragmentById(R.id.map_view);
    mapFragment.getMapAsync(this);

    setUpMapIfNeeded();

    // Inflate the layout for this fragment
    return v;
}

private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the map.
    if (mMap == null) {
        // Try to obtain the map from the SupportMapFragment.
        mMap = ((MapFragment) this.getFragmentManager().findFragmentById(R.id.map_view))
                .getMap();

        mMap.setMyLocationEnabled(true);
        // Check if we were successful in obtaining the map.
        if (mMap != null) {

            mMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {

                @Override
                public void onMyLocationChange(Location arg0) {
                    // TODO Auto-generated method stub

                    LatLng currentLocation = new LatLng(arg0.getLatitude(), arg0.getLongitude());
                    MarkerOptions currentLocationMarkOpt = new MarkerOptions().position(currentLocation).title("My location");

                    // on remplace le marqueur par notre nouvelle position
                    currentLocationMark.setPosition(currentLocation);
                    //currentLocationMark = mMap.addMarker(currentLocationMarkOpt);

                    markerPoints.add(1, currentLocation);

                    updateItinerary();
                }
            });
        }
    }
}

And here is the Logcat :

01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime: FATAL EXCEPTION: main
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime: Process: fr.irseem.ping32.smartp3, PID: 11418
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.MapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object reference
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at fr.irseem.ping32.smartp3.fragments.LocationFragment.onCreateView(LocationFragment.java:149)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.app.Fragment.performCreateView(Fragment.java:2220)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:973)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.app.BackStackRecord.run(BackStackRecord.java:793)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1535)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.app.FragmentManagerImpl$1.run(FragmentManager.java:482)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:739)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
01-20 15:24:25.861 11418-11418/fr.irseem.ping32.smartp3 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Thank you in advance for any help.


Solution

  • Try to use getMapAsync(this) instead of getMap().

    mMap = ((MapFragment) this.getFragmentManager().findFragmentById(R.id.map_view));
    mMap.getMapAsync(this);
    

    Hope this helps!

    EDIT:

    You can probably check the Google documentation on handling maps.

    https://developers.google.com/android/reference/com/google/android/gms/maps/MapFragment?hl=en

    You can try using the below code for creating markers.

    Geocoder geocoder = new Geocoder(context);
    Origin_Map = extras.getString(MainActivity.ORIGIN_MAP);
    Destination_Map = extras.getString(MainActivity.DESTINATION_MAP);
    Addr_Origin = geocoder.getFromLocationName(Origin_Map, 1);
    Addr_Dest = geocoder.getFromLocationName(Destination_Map, 1);
    if (Addr_Origin.size() > 0) {
                latitude_origin = Addr_Origin.get(0).getLatitude();
                longitude_origin = Addr_Origin.get(0).getLongitude();
            }
            if (Addr_Dest.size() > 0) {
                latitude_destination = Addr_Dest.get(0).getLatitude();
                longitude_destination = Addr_Dest.get(0).getLongitude();
            }
            Marker m1 = googleMap.addMarker(new MarkerOptions().position(new LatLng(latitude_origin, longitude_origin)).title(Origin_Map).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)));
            Marker m2 = googleMap.addMarker(new MarkerOptions().position(new LatLng(latitude_destination, longitude_destination)).title(Destination_Map).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
            PolylineOptions flightpath = new PolylineOptions().add(new LatLng(latitude_origin, longitude_origin)).add(new LatLng(latitude_destination, longitude_destination));
            Polyline flightpath_polyline = googleMap.addPolyline(flightpath.width(5).color(Color.BLUE).geodesic(true));