MapFragment return null
Asked Answered
E

6

6
mMapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentByTag(MAP_FRAGMENT_TAG);

        // We only create a fragment if it doesn't already exist.
        if (mMapFragment == null) {
          mMapFragment = SupportMapFragment.newInstance();


            // Then we add it using a FragmentTransaction.
            FragmentTransaction fragmentTransaction =
                    getSupportFragmentManager().beginTransaction();
            fragmentTransaction.add(MapLay.getId(), mMapFragment, MAP_FRAGMENT_TAG);
             fragmentTransaction.commit();


            mMap=mMapFragment.getMap();

By this code map is visible but unable to access the map

mMap=mMapFragment.getMap(); show null value error how to fix this

Eraeradiate answered 1/10, 2013 at 5:46 Comment(3)
it should be like that mMap=mMapFragment.getMap()Reddy
sorry sir this is typing mistake here but i have write correct in codeEraeradiate
@RanaRaman I have a favor for you, just want to analyze. Can you extend the SupportMapFragment? Put a Log in onCreate(). Put also a log before mMap=mMapFragment.getMap(). Let me know the Log to be called first.Presidio
P
17

Update 1: getMap() is deprecated

It is better to use getMapAsync() method of MapFragment/SupportMapFragment. The example how to use the method shown below (copied from their documentation).

import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.*;
import android.app.Activity;
import android.os.Bundle;

public class MapPane extends Activity implements OnMapReadyCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map_activity);

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

    @Override
    public void onMapReady(GoogleMap map) {
        LatLng sydney = new LatLng(-33.867, 151.206);

        map.setMyLocationEnabled(true);
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 13));

        map.addMarker(new MarkerOptions()
                .title("Sydney")
                .snippet("The most populous city in Australia.")
                .position(sydney));
    }

}

Quoting Google's MapFragment/SupportMapFragment

A GoogleMap can only be acquired using getMap() when the underlying maps system is loaded and the underlying view in the fragment exists. This class automatically initializes the maps system and the view; however you cannot be guaranteed when it will be ready because this depends on the availability of the Google Play services APK. If a GoogleMap is not available, getMap() will return null.

On your code, you immediately retrieve GoogleMap AFTER Committing MapFragment. Wait until the MapFragment is fully loaded on activity so you can get the GoogleMap.

Perhaps, you can deliver the GoogleMap from MapFragment to Activity using interface, like this.

public class MyMapFragment extends SupportMapFragment
{
  private MapCallback callback;

  public void setMapCallback(MapCallback callback)
  {
    this.callback = callback;
  }

  public static interface MapCallback
  {
     public void onMapReady(GoogleMap map);
  }

  @Override public void onActivityCreated(Bundle savedInstanceState)
  {
     super.onActivityCreated(savedInstanceState);
     if(callback != null) callback.onMapReady(getMap());     
  }
}


public class MyActivity extends Activity implements MyMapFragment.MapCallback
{
   // .........
  @Override
  public void onCreate(Bundle onsavedInstanceState)
  {
        mMapFragment = (MyMapFragment) getSupportFragmentManager()
                .findFragmentByTag(MAP_FRAGMENT_TAG);

        // We only create a fragment if it doesn't already exist.
        if (mMapFragment == null) {
               mMapFragment = MyMapFragment.newInstance();

               mMapFragment.setMapCallback(this); // This activity will receive the Map object once the map fragment is fully loaded

               // Then we add it using a FragmentTransaction.
               FragmentTransaction fragmentTransaction =
                    getSupportFragmentManager().beginTransaction();
               fragmentTransaction.add(MapLay.getId(), mMapFragment, MAP_FRAGMENT_TAG);
               fragmentTransaction.commit();

         }
         else
         {
               mMapFragment.setMapCallback(this); // This activity will receive the Map object once the map fragment is fully loaded
         }

  @Override
  public void onMapReady(GoogleMap map)
  {
     // Do what you want to map
  }

}
Presidio answered 1/10, 2013 at 6:5 Comment(4)
how about if I did onCreate method, setContentView(R.layout.activity_map); in the layout there is a fragment which will be loaded? Does it work that wayBerck
mMapFragment = MyMapFragment.newInstance(); - required MyMapFragment(), found SupportMapFragment(). I can't cast the new instance to a MyMapFragment either, anyone know why?Genesia
@DanielWilson you need to extend your MyMapFragment to SupportMapFragmentPresidio
yeah that code doesn't compile since newInstance() returns a new instance of SupportMapFragment, and it will only throw ClassCastException if you try to cast it. You need to use new MyMapFragment()Cordilleras
R
3

import part

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;

inside the oncreate

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

And Xml Part

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

Make sure you have put in

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

inside your <application></application> tags.

and give these permission in manifet file

<permission
          android:name="packagename.permission.MAPS_RECEIVE"
          android:protectionLevel="signature"/>
    <uses-permission android:name="packagename.permission.MAPS_RECEIVE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <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"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true"/>
Reddy answered 1/10, 2013 at 5:50 Comment(0)
M
1

Your xml should have SupportMapFragment

<fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Monoicous answered 1/10, 2013 at 5:51 Comment(1)
Sir i am not using XML Createing fragment at runtimeEraeradiate
S
1

I solved this problem when I put this code:

@Override
public void onPause() {

    Fragment fragment = (getFragmentManager().findFragmentById(R.id.map_tab));  
    FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
    ft.remove(fragment);
    ft.commit();
    super.onPause();
}

or I put this code in onCreate

if (mView != null) {
     ViewGroup parent = (ViewGroup) mView.getParent();
     if (parent != null) {
         parent.removeView(mView);
     }
 }
 try {
  mView = inflater.inflate(R.layout.tab_map_layout, container, false);
 } catch (InflateException e) {

 }
Samaveda answered 2/4, 2014 at 10:22 Comment(0)
N
1

Following the @Glenn-- comment from Oct 1 '13 at 6:05 to create this piece of source code.

My Implementation is replacing the SupportMapFragment with MapFragment and support Google Maps Version 2

I want to remember again:

A GoogleMap can only be acquired using getMap() when the underlying maps system is loaded and the underlying view in the fragment exists. This class automatically initializes the maps system and the view; however you cannot be guaranteed when it will be ready because this depends on the availability of the Google Play services APK. If a GoogleMap is not available, getMap() will return null.

My Implementation:

AndroidManifest.xml

<!-- Permissions -->

<!-- Used by the Google Maps API to download map tiles from Google Maps servers. -->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

<!-- Allows the Google Maps API to check the connection status in order to determine whether data can be downloaded. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<!-- Allows the Google Maps API to cache map tile data in the device's external storage area. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<!-- Allows the Google Maps API to use WiFi or mobile cell data (or both) to determine the device's location. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

<!-- Allows the Google Maps API to use the Global Positioning System (GPS) to determine the device's location to within a very small area. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- Permissions -->

<!-- Required OpenGL ES 2.0. for Maps V2 -->
<!-- 
    The Google Maps Android API uses OpenGL ES version 2 to render the map. 
    If OpenGL ES version 2 is not installed, your map will not appear. 
    sWe recommend that you add the following <uses-feature> element as a child of the <manifest> element in AndroidManifest.xml:
 -->
 <uses-feature
    android:glEsVersion="0x00020000"
    android:required="true"/>

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <!-- Google Play Services -->
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

    <!-- Goolge Maps API Key -->
    <meta-data
        android:name="com.google.android.maps.v2.API_KEY"
        android:value="AIzaSyATC4WBLLewjdwYDFVTnJH8hA18gG_GgvY" />

</application>

activity_main.xml

<RelativeLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="mapa.bg.MapaMainActivity" 
    android:background="#ccc">

    <!-- Google Map Container -->
    <RelativeLayout 
        android:id="@+id/google_map_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <!-- Google Map Container -->
</RelativeLayout>

ApplicationMapFragment.java

public class ApplicationMapFragment extends MapFragment {

    private MapCallback callback;

    public void setMapCallback(MapCallback callback) {
        this.callback = callback;
    }

    public static interface MapCallback {
        public void onMapReady(GoogleMap map);
    }

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if(callback != null) callback.onMapReady(getMap()); 
    }

    /**
     * Initialize default Google Maps Options for our Application
     * @return GoogleMapOptions
     */
    public GoogleMapOptions initializeGoogleMapsOptions() {
        GoogleMapOptions googleMapOptions = new GoogleMapOptions()
            .mapType(GoogleMap.MAP_TYPE_HYBRID);

        return googleMapOptions;
    }
}

MainActivity.java

public class MainActivity extends Activity implements ApplicationMapFragment.MapCallback {

    // Get Class Name
    private static String TAG = MainActivity.class.getName();

    // Create a new Map fragment
    private ApplicationMapFragment mapFragment;

    // Google Map Fragment Name
    private static String MAP_FRAGMENT_TAG = "google_maps_fragment";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        try {
                initilizeMapFragment();
        } catch (Exception e) {
                e.printStackTrace();
                Log.e(TAG, "Google Maps can't be loaded", e);
        }
    }

    /**
     * Initialize a new Map Fragment
     */
    private void initilizeMapFragment() {

        // Try to get Map Fragment
        mapFragment = (ApplicationMapFragment) getFragmentManager()
                .findFragmentByTag(MAP_FRAGMENT_TAG);

        // We only create a fragment if it doesn't already exist.
        if (mapFragment == null) {
            mapFragment = new ApplicationMapFragment();
            mapFragment.initializeGoogleMapsOptions();

            // This activity will receive the Map object once the map fragment is fully loaded
            mapFragment.setMapCallback(this);

            // Then we add it using a FragmentTransaction.
            FragmentTransaction fragmentTransaction =
                    getFragmentManager().beginTransaction();
            fragmentTransaction.add(R.id.google_map_container, mapFragment, MAP_FRAGMENT_TAG);
            fragmentTransaction.commit();
        } else {
            // This activity will receive the Map object once the map fragment is fully loaded
            mapFragment.setMapCallback(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap map) {
        Log.d(TAG, "Google Map is loaded");

        MarkerOptions marker = new MarkerOptions()
            .position(new LatLng(10, 10))
            .title("Hello World");

        map.addMarker(marker);
    }
}
Notation answered 11/9, 2014 at 14:12 Comment(0)
A
0

Really hackish solution but, because given the poor fragment API...

Note that I'm doing this from a custom View and accessing the Activity using (Activity)getContext()

            addOnLayoutChangeListener(new OnLayoutChangeListener(){
                @Override
                public void onLayoutChange(View v, int left, int top,
                        int right, int bottom, int oldLeft, int oldTop,
                        int oldRight, int oldBottom) {

                    GoogleMap map = mapFragment.getMap();

                    if (map != null) {
                         //Do stuff
                    }else{
                         removeOnLayoutChangeListener(this);
                    }
                }
            });
Alwyn answered 15/4, 2014 at 14:37 Comment(3)
could you be a bit more specific? you mean once the map starts loading (meaning it wil return the map, not null), onLayoutChange is called? Is this written on an activity file?Sabadilla
You can add the Layout Change Listener to the view containing the Map Fragment.Alwyn
And yes, it seems like when the map is fully loaded the listener is called. In my case, I was using a custom view and added this code in the onAttachedToWindow method but perhaps you can do the same in the onCreate of an Activity.Alwyn

© 2022 - 2024 — McMap. All rights reserved.