getMapAsync() in Fragment
Asked Answered
S

4

20

I having trouble implementing Google Map in Fragment.

This is my the part of my fragment class:

public class FragmentStoreFinderMap extends Fragment implements OnMapReadyCallback {

// Google Map
private GoogleMap googleMap;
private int i;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

        googleMap = ((SupportMapFragment)getActivity().getSupportFragmentManager().findFragmentById(
              R.id.map)).getMapAsync(this);

I am getting an error in getMapAsync(this). I tells Incompatible type.

it says:

required: com.google.android.gms.map.GoogleMap

found: void

BTW here is my xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment class="com.google.android.gms.maps.SupportMapFragment"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</LinearLayout>
Steinman answered 19/2, 2016 at 2:54 Comment(0)
A
61

In your XML layout you should do like this

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

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

</FrameLayout>

inside your fragment implement this

private MapView mapView;
private GoogleMap googleMap;

override onCreateView if there is no onCreateView just like the code below

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.your_layout, container, false);
}

override onViewCreated() inside that onViewCreated() put this

mapView = (MapView) view.findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
mapView.onResume();
mapView.getMapAsync(this);//when you already implement OnMapReadyCallback in your fragment

when you already implement OnMapReadyCallback in your fragment put this/code like this

@Override
public void onMapReady(GoogleMap map) {
    googleMap = map;
}

hope this helps you.

Antitoxic answered 19/2, 2016 at 3:15 Comment(5)
You should override onCreateView and inflate your layout like this. @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.your_layout, container, false); }Antitoxic
Did you override the onViewCreated in your fragment ?Antitoxic
why do you need to invoke onCreate(savedInstanceState); and onResume(); ?Vickers
Why are you calling mapView.onResume(); in onViewCreated()? Why not in onResume()?Creep
I am unable to implement onMapReadyCallBack ..it shows unable to resolveBerryberryhill
M
3

After a few overheats in my head, thanks to this post and https://mcmap.net/q/661775/-mapfragment-causing-nullpointerexception-at-getmapasync-this-method, I would say that currently there are two ways of adding a MapFragment to your app:

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

By this way, you have to use a standard fragment and implement this inside. Actually you are inserting a fragment into another:

    @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    
    SupportMapFragment supportMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
    supportMapFragment.getMapAsync(this);
}

The other way would be extending the real SupportMapFragment and implement it in this manner without the need of an xml:

    @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    getMapAsync(this);
}

And they work without having to set a layout in onCreateView neither call mapView.onCreate(savedInstanceState); and mapView.onResume(); manually inside onViewCreated(), what is not recommended anyway.

Hope it helps!

Manchu answered 22/12, 2017 at 12:28 Comment(2)
Your onViewCreated method worked for me. The important part here is to use the Child Fragment-Manager, not the Parent Fragment-ManagerMarkham
But what I said is that I recommend the second case. If your fragment extends SupportMapFragment you don't need a FragmentManager and you don't have to inflate a fragment inside another using a layout.Manchu
C
2
 SupportMapFragment mMapFragment = SupportMapFragment.newInstance();
 FragmentTransaction fragmentTransaction =
 getChildFragmentManager().beginTransaction();
 fragmentTransaction.add(R.id.flMap, mMapFragment);
 fragmentTransaction.commit();
 mMapFragment.getMapAsync(this);
Candor answered 8/3, 2019 at 6:31 Comment(0)
T
0

Your code is returning this error because getMapAsync() does not return anything. If you look at the documentation for this function:

public void getMapAsync (OnMapReadyCallback callback)

Sets a callback object which will be triggered when the GoogleMap instance is ready to be used.

Note that:

This method must be called from the main thread. The callback will be executed in the main thread. In the case where Google Play services is not installed on the user's device, the callback will not be triggered until the user installs it. In the rare case where the GoogleMap is destroyed immediately after creation, the callback is not triggered. The GoogleMap object provided by the callback is non-null.

OnMapReadyCallback is an interface that needs implemented and passed to through this function. Nothing is currently assigned to your googleMap variable you should instead set its value in this block of code which implements OnMapReadyCallback

@Override
    public void onMapReady(GoogleMap googleMap) {
        this.googleMap = googleMap;


    }

This code should be in your Fragment somewhere. Since your Fragment already implements this interface you do pass it in as this.

Tellus answered 19/2, 2016 at 3:9 Comment(1)
I already have the onMapReady on my class. thanks for the answer btw,Steinman

© 2022 - 2024 — McMap. All rights reserved.