Neutrino
Neutrino

Reputation: 781

mapFragment.getMapAsync(this) - NullPointerException

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>

Upvotes: 40

Views: 81321

Answers (16)

Harsh Bhavsar
Harsh Bhavsar

Reputation: 39

use this instead of SupportMapFragment:)

 GoogleMap gooleMap;

   ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap map) {
                googleMap = map;
            }
        });

Upvotes: 1

Mark Nashat
Mark Nashat

Reputation: 768

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"

Upvotes: 0

Devenom
Devenom

Reputation: 975

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

Upvotes: 13

Darksymphony
Darksymphony

Reputation: 2683

Try this code in onCreate

if (mapFragment != null) {
    mapFragment.getMapAsync(this);
}

Upvotes: 0

Tarun Umath
Tarun Umath

Reputation: 910

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);

Upvotes: 3

Naveed Ahmad
Naveed Ahmad

Reputation: 6737

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"

Upvotes: 3

Rayan Teixeira
Rayan Teixeira

Reputation: 89

this works for me:

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

Upvotes: 8

badarshahzad
badarshahzad

Reputation: 1297

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.

Upvotes: 3

varotariya vajsi
varotariya vajsi

Reputation: 4041

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 .

Upvotes: 2

Nagendra
Nagendra

Reputation: 121

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);

Upvotes: 12

fanjavaid
fanjavaid

Reputation: 1738

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

Upvotes: 0

Mina Fawzy
Mina Fawzy

Reputation: 21452

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" />

Upvotes: 130

jan_013069
jan_013069

Reputation: 21

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

Upvotes: 2

Arun kumar
Arun kumar

Reputation: 1894

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

like:

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

Upvotes: 22

Mujtaba Zaidi
Mujtaba Zaidi

Reputation: 629

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);

    }

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1006674

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.

Upvotes: 14

Related Questions