¿Cómo sé que el mapa está listo para usarse cuando se usa SupportMapFragment?

En el método onCreate , estoy haciendo uso de SupportMapFragment para mostrar un mapa.

  SupportMapFragment fragment = new SupportMapFragment(); getSupportFragmentManager().beginTransaction() .add(android.R.id.content, fragment).commit(); 

En conjunción con esto, me gustaría agregar un marcador. El problema es cuando la llamada a getMap es nula, ¿cuándo puedo intentar de nuevo? ¿Hay algún evento en el que me pueda registrar o mi enfoque es erróneo?

  mMap = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap(); if(mMap == null) //what do I do here? 

De hecho, el mapa se muestra en el teléfono, pero parece que no tengo suerte en obtener la referencia para agregar marcadores.

ACTUALIZAR:

La razón por la que estaba creando SupportMapFragment través del constructor es porque el setContentView típico se setContentView y no funcionaba. Esto me puso en la situación en la que no pude obtener mi referencia en el método onCreate porque de hecho estaba creando el SupportMapFragment en ese momento. En una investigación posterior, parece que mi problema setContentView fue un subproducto de no tener tanto el jar de Google-play-services COMO el módulo / src configurado como parte del proyecto en general. Al hacer AMBOS de estos, setContentView ahora funciona y puedo obtener la referencia a través de getMap() como era de esperar.

lots.xml …

   

LotsActivity.java …

 public class LotsActivity extends FragmentActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.lots); GoogleMap mMap; mMap = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap(); if(mMap == null) //this should not occur now } 

EDITAR: getMap está en desuso ahora

El problema es cuando la llamada a getMap es nula, ¿cuándo puedo intentar de nuevo?

Eso depende de la naturaleza del problema.

Si configura SupportMapFragment través del elemento en el diseño, puede llamar a getMap() éxito en onCreate() . Pero, si crea el SupportMapFragment través del constructor, eso es demasiado pronto: el GoogleMap aún no existe. Puede extender SupportMapFragment e invalidar onActivityCreated() , ya que getMap() está listo para entonces.

Sin embargo, getMap() también puede devolver null para un problema mayor, como que no se instalen los Servicios de Google Play. Debería usar algo como GooglePlayServicesUtil.isGooglePlayServicesAvailable() para detectar esta condición y tratarla como lo desee.

Terminé extendiendo la clase SupportMapFragment y usando una callback. El código está aquí:

 public class MySupportMapFragment extends SupportMapFragment { public MapViewCreatedListener itsMapViewCreatedListener; // Callback for results public abstract static class MapViewCreatedListener { public abstract void onMapCreated(); } @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); // Notify the view has been created if( itsMapViewCreatedListener != null ) { itsMapViewCreatedListener.onMapCreated(); } return view; } } 

Preferiría haber usado una interfaz y anular el método onAttach (actividad), pero en mi caso, no quería que la callback volviera a mi actividad principal. Quería que volviera a una instancia de Fragment. (El GoogleMap era esencialmente un fragmento dentro de un fragmento) Configuré la callback y programáticamente cargué el mapa con esto. Me gustaría haber configurado suMapViewCreatedListener dentro del constructor de MySupportMapFragment, pero se desaconseja usar cualquier cosa que no sea constructores sin parámetros.

 itsMySupportMapFragment = new MySupportMapFragment(); MapViewCreatedListener mapViewCreatedListener = new MapViewCreatedListener() { @Override public void onMapCreated() { initPlacesGoogleMapCtrl(); } }; itsMySupportMapFragment.itsMapViewCreatedListener = mapViewCreatedListener; FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.mapFragmentContainer, itsMySupportMapFragment); transaction.addToBackStack(null); transaction.commit(); 

Y luego, cuando recibí la llamada, pude obtener el mapa; ¡no más nulo!

 public void initPlacesGoogleMapCtrl() { // Map ready, get it. GoogleMap googleMap = itsMySupportMapFragment.getMap(); // Do what you want... } 

Yo comentaría sobre la respuesta de CommonsWare pero no tengo suficientes representantes para eso. De todos modos, también tenía este problema que getMap () devolvería null en onActivityCreated. Mi configuración es la siguiente: tengo MainActivity que contiene un fragmento. En el método onCreateView de ese fragmento creé SupportMapFragment y luego lo agregué al fragmento a través de childFragmentManager. Mantuve la referencia al SupportMapFragment y esperaba que me diera el mapa en onActivityCreated, que no fue así. La solución a ese problema fue anular el onActivityCreated del SupportMapFragment pero no el fragmento principal. Lo hice así en onCreateView:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_location, container, false); mMapFragment = new SupportMapFragment() { @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mMap = mMapFragment.getMap(); if (mMap != null) { setupMap(); } } }; getChildFragmentManager().beginTransaction().add(R.id.framelayout_location_container, mMapFragment).commit(); return v; } 

El mes pasado (diciembre de 2014), Google brindó una solución oficial para este problema. En los más recientes (6.5) Servicios de Google Play :

El método getMap () en MapView y MapFragment ahora está en desuso en favor del nuevo método getMapAsync ().

Con getMapAsync(OnMapReadyCallback callback) puede configurar el escucha para cuando GoogleMap esté listo. Se pasa en callback y se proporciona para que no sea nulo.

Google proporcionó un código de muestra para esto:

 public class MainActivity extends FragmentActivity implements OnMapReadyCallback { ... } 

y al inicializar el fragmento:

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

cuando el mapa esté listo, se te llamará

 @Override public void onMapReady(GoogleMap map) { map.addMarker(new MarkerOptions() .position(new LatLng(0, 0)) .title("Marker")); } 

También puede usar MapsInitializer.initialize(context); si el problema está relacionado con las bibliotecas que no se han inicializado.

Con los últimos GoogleServices puedes usar MapFragment.getMapAsync . Directamente de los documentos

Establece un objeto de callback que se activará cuando la instancia de GoogleMap esté lista para su uso.

si map == null, busca el mapa

  if (mGoogleMap == null) { SupportMapFragment mapFragment1 = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment1.getMapAsync(this); } 

y luego llama a tu función enMapReady ();