40

I am using com.google.android.gms:play-services-maps:7.5.0 version of Google Maps services. When trying to call the below I get java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.SupportMapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object reference.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    SupportMapFragment mapFragment = (SupportMapFragment) getActivity().getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this); //error

    return inflater.inflate(R.layout.fragment_example_map, container, false);
}

fragment_example_map.xml file:

<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="app.ExampleMap">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</FrameLayout>
Neutrino
  • 781
  • 2
  • 9
  • 19

16 Answers16

130

My comment in maps with fragment , first you should refrenece your view as you will call something from it , this is why I inflate my view first
View view = inflater.inflate(R.layout.activity_maps, null, false);

Second call child fragment manager this.getChildFragmentManager() instead of getActivity().getSupportFragmentManager()

Here is the full example to view map

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class ClinicFragment extends Fragment implements OnMapReadyCallback {

    private GoogleMap mMap;

    public static ClinicFragment newInstance() {
        ClinicFragment fragment = new ClinicFragment();
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_maps, null, false);

        SupportMapFragment mapFragment = (SupportMapFragment) this.getChildFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        return view;
    }


    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }
}

required permission

<permission
    android:name="your.package.name.permission.MAPS_RECEIVE"
    android:protectionLevel="signature" />
<uses-permission android:name="your.package.name.permission.MAPS_RECEIVE"/>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

plus feature element

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true"/>

most import google maps key

<meta-data
    android:name="com.google.android.maps.v2.API_KEY"
    android:value="your_key_here" />

Update add this meta data if you face Error inflating class fragment

<meta-data 
      android:name="com.google.android.geo.API_KEY"  
      android:value="your_key_here" />

summery for mainfest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="your.package.name" >
// permission here

 <application
        android:name=".Activities.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

    // feature element 
    // maps key

  </application>

</manifest>

activity_maps.xml

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.imaadv.leaynik.ClinicFragment" />
Community
  • 1
  • 1
Mina Fawzy
  • 20,852
  • 17
  • 133
  • 156
21

use getChildFragmentManager() in place of getActivity().getSupportFragmentManager() in the fragment.

like:

SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this); 
Arun kumar
  • 1,894
  • 3
  • 22
  • 28
14

You are attempting to find a fragment before it exists. You indicate that the layout that has the fragment is fragment_example_map.xml. However, you are trying to find the map fragment before you inflate that layout file. This will not work.

Beyond that, you appear to be trying to get at the map fragment from inside another fragment, in that fragment's onCreateView() method. I do not know why you are nesting fragments here, as it seems like it will make your code more complex and more fragile for no obvious benefit.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    Where would be a proper place to call the `getMapAsync()` then? Basically my app has 3 fragments, 1 activity and a ViewPager to slide between these fragments. Should it be the activity's `onCreate()`? – Neutrino Jun 22 '15 at 22:57
  • @Neutrino: "Basically my app has 3 fragments, 1 activity and a ViewPager to slide between these fragments" -- you do not need nested fragments for that. Your activity has a `ViewPager`. Your `PagerAdapter` creates three fragments. No nesting is required. Have the `FragmentPagerAdapter` just create a new instance of `SupportMapFragment` directly; you do not need to inflate a layout. This sample shows a `ViewPager` with ten map fragments: https://github.com/commonsguy/cw-omnibus/tree/master/MapsV2/Pager – CommonsWare Jun 22 '15 at 23:00
  • Sorry, I'm kind of lost. My `ViewPagerAdapter`'s `getItem()` checks the position and calls `return new Example()` in this case - I guess inflating the layout is in such case required? And then I'm not so sure where I should be doing my operations: in fragments code, activities code, or anywhere else. – Neutrino Jun 22 '15 at 23:09
  • @Neutrino: I supplied a link to a sample app in my previous comment that demonstrates how to set up an activity, with a `ViewPager`, with a map (in my case, 10 maps) as pages via fragments. You may wish to review this sample app, to see how I did it. – CommonsWare Jun 22 '15 at 23:34
  • 2
    Got rid of `onCreateView`, class now extends `SupportMapFragment`, added `onActivityCreated` and it seems to be working now, thanks – Neutrino Jun 23 '15 at 00:25
  • We can also use that MAP FRAGMENT as a root element in XML in order to avoid NULL EXCEPTION. But if I put it inside a RELATIVE OR LINEAR layout then only it's throwing that NULL EXCEPTION. Why? – Subhojit Halder Sep 16 '20 at 15:40
  • @SubhojitHalder: I recommend that you ask a separate Stack Overflow question, where your [mcve] shows what you are trying and provides the complete stack trace of your crash. – CommonsWare Sep 16 '20 at 17:05
13

Faced the same problem. Since you are using the Map fragment within a Fragment use getChildFragmentManager() instead of getActivity().getFragmentManager() or getFragmentManager().

Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
Devenom
  • 915
  • 1
  • 9
  • 20
12

If your are using android:name="com.google.android.gms.maps.MapFragment" in your fragment then change your code with:

MapFragment mapFragment1 = (MapFragment)getFragmentManager().findFragmentById(R.id.map);
        mapFragment1.getMapAsync(this);

However if your are using android:name="com.google.android.gms.maps.SupportMapFragment" in your fragment then use this code:

SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
Nagendra
  • 121
  • 2
  • 6
8

this works for me:

SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this); 
3

The simple answer is if you want to add Map Fragment this

<fragment 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:layout="@layout/fragment_home" />

In to your fragment : like this layout

 <android.support.constraint.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
tools:context="com.example.android.earthreport.fragments.HomeFragment"
        tools:layout_editor_absoluteX="8dp"
        tools:layout_editor_absoluteY="81dp">

     <fragment 
xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@id/guideline4"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@id/guideline3"
            tools:layout="@layout/fragment_home" />
        </android.support.constraint.ConstraintLayout>

Then you have to to add this line after the inflating the fragment like this

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

        // Find a reference to the {@link ListView} in the layout
        // Inflate the layout for this fragment
        // To get the referance we don't have findviewbyId 
        // method in fragment so we use view
        View view = inflater.inflate(R.layout.fragment_home, container, false);


          SupportMapFragment mapFragment = (SupportMapFragment) 
                  this.getChildFragmentManager()
                  .findFragmentById(R.id.map)
          mapFragment.getMapAsync(this);
.....

Into your Activity: like this layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:context="package com.example.android.map" />

</android.support.constraint.ConstraintLayout>

then you have to add this chunk of code.

  @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        setContentView(R.layout.map_activity);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
      }

Correct me if im wrong but always add map fragment after inflating the layout or set the content view.

badarshahzad
  • 1,227
  • 16
  • 25
3

I was using SupportMapFragment and in XML I defined MapFragment name attribute

android:name="com.google.android.gms.maps.MapFragment"

so I replaced the code with SupportMapFragment and it started working fine

android:name="com.google.android.gms.maps.SupportMapFragment"
Naveed Ahmad
  • 6,627
  • 2
  • 58
  • 83
3

If you want use map Fragment in side Fragment use this

SupportMapFragment mMapFragment = SupportMapFragment.newInstance();
FragmentTransaction fragmentTransaction =
getChildFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.flMap, mMapFragment);
fragmentTransaction.commit();
mMapFragment.getMapAsync(this);
Tarun Umath
  • 900
  • 10
  • 7
2

Depending on Android version or SDK version 5 and above use getChildFragmentManager() and below it used getFragmentManager().

jan_013069
  • 21
  • 1
  • Do you have any document or a link about that? In my case getChildFragmentManager() returns for all Android versions a valid FragmentManager. But getFragmentManager returns null for Android 4 and below. – Ralf Wickum Apr 05 '17 at 14:01
  • Can you please provide documentation. This is roughly the solution to my problem but I can't put it into production until I'm sure of those version numbers. Everything I read refers to API 17 and up. – Keith Loughnane Dec 12 '17 at 16:37
2

getFragmentManager() will may not be work when you are using map inside fragment. You have to use getChildFragmentManager().

SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.fragment_track_order_map_fragment);
mapFragment.getMapAsync(this);

and below is my xml declaration

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

also you need to implements OnMapReadyCallback in your fragment .

varotariya vajsi
  • 3,965
  • 37
  • 39
1

use this instead of SupportMapFragment:)

 GoogleMap gooleMap;

   ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap map) {
                googleMap = map;
            }
        });
Sharon Joshi
  • 498
  • 7
  • 19
0

replace this code

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

and

if (googleMap == null) {
        mapFrag =  (MapFragment)getFragmentManager().findFragmentById(R.id.map);
        mapFrag.getMapAsync(this);
    }else{
        GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

    }
Mujtaba Zaidi
  • 629
  • 1
  • 6
  • 14
0

Just Call supportMapFragment.getMapAsync(this); in onResume in your Activity

fanjavaid
  • 1,676
  • 8
  • 34
  • 65
0

Try this code in onCreate

if (mapFragment != null) {
    mapFragment.getMapAsync(this);
}
Tomin B Azhakathu
  • 2,656
  • 1
  • 19
  • 28
Darksymphony
  • 2,155
  • 30
  • 54
0

If you are using Fragment, change this code

SupportMapFragment mapFragment =getActivity().getSupportFragmentManager().findFragmentById(R.id.map);

To

supportMapFragment = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);
  • Check also Change in XML File

    android:name="com.google.android.gms.maps.MapFragment"
    

To

  android:name="com.google.android.gms.maps.SupportMapFragment"
Mark Nashat
  • 668
  • 8
  • 9