Google Map Android API v2 : GoogleMap is null
Asked Answered
G

6

3

I'm trying to explore using the MapView class for GoogleMap display, with no luck, as most codes examples are using MapFragment which I do not want.

I am using Google Maps Android API v2.

At first, just for testing with here from Google's example, I managed to get the typical normal map to display.

public class POnlineMapView extends Activity {

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

The code above works perfectly which show that everything has been set up properly.

I am now trying to use the MapView class to manipulate the display settings such as the center point, but it seems like I am obtaining a null object everytime I try to obtain the GoogleMap object. Why is this so?

public class POnlineMapView extends Activity {

    private MapView myMapView;
    private GoogleMap map;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myMapView = new MapView(getApplicationContext());
        Bundle b = getIntent().getExtras();
        double longitude = b.getDouble("longitude");
        double latitude = b.getDouble("latitude");

        setContentView(R.layout.online_map_activity);
        map = myMapView.getMap();

        CameraUpdate center= CameraUpdateFactory.newLatLng(new LatLng(latitude,longitude));
        CameraUpdate zoom=CameraUpdateFactory.zoomTo(17);

        map.moveCamera(center); //this gives a NullPointerException, probably due to the myMapView.getMap() method?
        map.animateCamera(zoom);    
    }
}
Gagliardi answered 25/1, 2013 at 8:28 Comment(2)
even if you don't want a mapfragment, you still need a mapactivity...Postboy
What do you mean by that? You mean the class should not be extending from Activity?Gagliardi
D
3

Check whether Google Play Service are installed (and updated)

See Google Maps Android API v2 throws GooglePlayServicesNotAvailableException, out of date, SupportMapFragment.getMap() returns null

Please also read https://developers.google.com/maps/documentation/android/map (section Verify Map availability)

Dizzy answered 25/1, 2013 at 9:43 Comment(0)
E
3

This seems like an old question, but I was having the same problem trying to use MapView.

Assuming you have properly imported the Google Play Services lib, you have to check if you have access to Google Services, you can do this in your onCreate method, and you have to initialize the Google Maps Android AP. you can do this by adding the following code to your onCreate method

try {
        MapsInitializer.initialize(this);
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e("Address Map", "Could not initialize google play", e);
    }

switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) )
{
  case ConnectionResult.SUCCESS:
      Toast.makeText(getApplicationContext(), "SUCCESS", Toast.LENGTH_SHORT).show();
      break;
  case ConnectionResult.SERVICE_MISSING: 
      Toast.makeText(getApplicationContext(), "SERVICE MISSING", Toast.LENGTH_SHORT).show();
      break;
  case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: 
      Toast.makeText(getApplicationContext(), "UPDATE REQUIRED", Toast.LENGTH_SHORT).show();
      break;
  default: Toast.makeText(getApplicationContext(), GooglePlayServicesUtil.isGooglePlayServicesAvailable(this), Toast.LENGTH_SHORT).show();
}

If you get SUCCESS, then everything is working so far. You also have to implement the mothods of the Activity lyfecycle and call the corresponding methond of your map view inside every one of these methods:

@Override
protected void onResume() {
    myMapView.onResume();
    super.onResume();

}

@Override
protected void onPause() {
    myMapView.onResume();
    super.onPause();

}

@Override
protected void onDestroy() {
    myMapView.onDestroy();
    super.onDestroy();
   //((MapView)findViewById(R.id.mapView)).onDestroy();
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    myMapView.onLowMemory();
}

Finally, you have to check that you have added your Google Maps API key to your Manifest file:

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

you can find instructions to get your key here: https://developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api

Edit: Forgot to mention, you also have to set your applications permissions on the manifest file

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

This has to be set inside the application block ...

Epidemiology answered 17/10, 2013 at 6:1 Comment(0)
P
3

Thanks, you finally gave me a clue to initialize the Map programatically, how stupid I oversaw it :)

Well, sometimes there is no option to use MapFragment (or SupportMapFragment alike), i.e. when you want to use the map from a fragment! This is actually a very common case when working with tabs (ActionBar) where the pattern is to use fragments. So you've got your own fragment per tab and in that fragment for a map you want to inflate your layout which contains a fragment for the MapFragment, et voila - good luck!

Now, according to the MapView specs it is no way said that using of the MapView is discouraged or deprecated, so why should I not use it? I did not want hacks in maintaining nested fragments without having support from SDK ( even the recent support lib v13 seems to have bugs and nested fragments from layout are not supported ), so using MapView turned for me into KISS.

Below is my CustomMapFragment I use with layout inflation (allowing complex layout) and embedded map, you're welcome to use it. You may also want to extend the Fragment from support-lib rather than SDK.

The onCreateView() method inflates the layout (just provide you're own) and expects the layout to have viewgroup (relativelayout,linearlayout,etc) with id "mapViewHolder" where the mapView will be attached to upon layout creation. The activity has to implement CustomMapFragment.Handler interface, otherwise ClassCastException will be thrown.

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import R;

public class AppMapFragment extends Fragment {
  /*
   * to interact with activity
   */
  public static interface Handler {
    void onMapResume(GoogleMap map);
  }

  private Handler handler;
  private MapView mapView;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {
      // initialize explicitely, since we're working with MapView (not MapFragment)
      MapsInitializer.initialize(getActivity());
      this.mapView = new MapView(getActivity());
      this.mapView.onCreate(savedInstanceState);
    } catch (GooglePlayServicesNotAvailableException e) {
      Toast.makeText(getActivity(), "Please install Google Play Store and retry again!", Toast.LENGTH_LONG).show();
      getActivity().finish();
    }
  }

  @Override
  public void onResume() {
    super.onResume();
    this.mapView.onResume();
    this.handler.onMapResume(this.mapView.getMap());
  }

  @Override
  public void onPause() {
    super.onPause();
    this.mapView.onPause();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    this.mapView.onDestroy();
  }

  @Override
  public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    this.mapView.onSaveInstanceState(outState);
  }

  @Override
  public void onLowMemory() {
    super.onLowMemory();
    this.mapView.onLowMemory();
  }

  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
      this.handler = (Handler) activity;
    } catch (ClassCastException e) {
      throw new ClassCastException("Your activity has to implement the interface " + this.handler.getClass().getName());
    }
  }

  public AppMapFragment() {
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_results_map, container, false);

    ((ViewGroup) rootView.findViewById(R.id.mapViewHolder)).addView(this.mapView);

    return rootView;
  }
}
Peruse answered 10/12, 2013 at 21:9 Comment(0)
R
1

One difference between MapFragment and MapView is that you have to manually manage the lifecycle of MapView, while MapFragment takes care of it by itself.

You must call the following methods from the parent Activity/Fragment's corresponding methods.

onCreate(Bundle)
onResume()
onPause()
onDestroy()
onSaveInstanceState()
onLowMemory()

I verified this with RawMapViewDemoActivity in samples of Google Play Services, which can be installed in the Extras section of Android SDK Manager.

The sample showed the map at first, and it showed a blank page once I commented out the 6 lines of mMapView.onXXX().

Maybe the lifecycle is the reason why most examples we see everywhere use MapFragment.

Rigby answered 6/7, 2014 at 15:12 Comment(1)
Why they have excluded MapActivity from v1 of v2?Hopping
R
0

Try out this way:

  private MapView myMapView;   
  private GoogleMap map;  
      myMapView = (MapView) findViewById(R.id.map);     
      if (map == null) {     
                map = ((MapView) findViewById(R.id.map)).getMap();     
       }
Ringtailed answered 25/1, 2013 at 8:41 Comment(8)
Sadly doesn't work :( It gives this error "01-25 16:44:20.063: E/AndroidRuntime(20332): Caused by: java.lang.ClassCastException: android.widget.FrameLayout cannot be cast to com.google.android.gms.maps.MapView" and this points to the myMapView = (MapView) findViewById(R.id.map); lineGagliardi
Can you tell me that which minimum api are you using ?Ringtailed
I believe you are referring to this? android:minSdkVersion="9"Gagliardi
Then you should use SupportMapFragment because the MapFragment is for the api 12 or above. Thatz why its throwing this exception.Ringtailed
I am using MapView, not MapFragment. Because the map will be taking up the full screen, it is not required for me to implement MapFragment. Does the sdk version affect usage of MapView class?Gagliardi
Try to use SupportMapFragment instead of MapView.Ringtailed
Yes the SDK effects the MapView thatz why . I think you should extends android.support.v4.app.FragmentActivity in your POnlineMapView activity instead of ActivityRingtailed
I'm really trying to avoid Fragments as I'm not familiar with it... but I guess I have to explore to see how it works... So can I still use MapView if i extend Fragment Activity instead?Gagliardi
B
0

I didn't have luck with the map view either.
I did have luck with the MapFragment.

Try this:

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

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

public class TestActivity extends FragmentActivity {

  SupportMapFragment mapFragment;
  GoogleMap map;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (mapFragment == null) {
      mapFragment = new SupportMapFragment();
      getSupportFragmentManager().beginTransaction()
          .add(android.R.id.content, mapFragment).commit();
    }
  }

  @Override
  protected void onResume() {
    super.onResume();
    setupMap();
  }

  private void setupMap() {
    if (map != null)
      return;
    map = mapFragment.getMap();
    if (map == null)
      return;

    doZoom();
  }

  private void doZoom() {
    if (map != null) {
      map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(45.424900,
          -75.694968), 17));
    }
  }
}
Bowlds answered 31/1, 2013 at 21:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.