0

I am a bit confused whether or not it is possible to add a button to googlemaps. I tried to create a relative layout where i would put the fragment and a image button in the same layout but for some reason my app keeps on crashing. Here is what my XML looks like:

 <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"
tools:context=".MapsActivity" >

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


<ImageButton
    android:id="@+id/theimagebutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/car"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"/>
  </RelativeLayout>

And I get this Error java.lang.RuntimeException: Unable to resume activity java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.GoogleMap com.google.android.gms.maps.SupportMapFragment.getMap()' on a null object reference

  import android.content.Context;
  import android.graphics.Color;
  import android.location.Criteria;
  import android.location.Location;
   import android.location.LocationManager;
  import android.os.Bundle;
  import android.support.v4.app.FragmentActivity;
  import android.widget.Toast;

 import com.google.android.gms.maps.CameraUpdate;
 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.BitmapDescriptorFactory;
 import com.google.android.gms.maps.model.LatLng;
 import com.google.android.gms.maps.model.MarkerOptions;
 import com.google.android.gms.maps.model.Polyline;
 import com.google.android.gms.maps.model.PolylineOptions;
 import com.parse.ParseGeoPoint;
 import com.parse.ParseObject;

 public class MapsActivity extends FragmentActivity implements RoutingListener {
protected GoogleMap mMap;
protected LatLng start;
protected LatLng end;

/**
 * This activity loads a map and then displays the route and pushpins on it.
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    SupportMapFragment mMap = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

    try {
        setUpMapIfNeeded();

    } catch (Exception e) {
        e.printStackTrace();
    }
}
@Override
protected void onResume() {
    super.onResume();
    setUpMapIfNeeded();
}

private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the map.
    if (mMap == null) {
        // Try to obtain the map from the SupportMapFragment.
        mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                .getMap();
        // Check if we were successful in obtaining the map.
        if (mMap != null) {
            setUpMap();
        }
    }
}

/**
 * This is where we can add markers or lines, add listeners or move the camera. In this case, we
 * just add a marker near Africa.
 * <p/>
 * This should only be called once and when we are sure that {@link #mMap} is not null.
 */

private void setUpMap() {


    // Enable MyLocation Layer of Google Map
    mMap.setMyLocationEnabled(true);

    // Get LocationManager object from System Service LOCATION_SERVICE
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

    // Create a criteria object to retrieve provider
    Criteria criteria = new Criteria();

    // Get the name of the best provider
    String provider = locationManager.getBestProvider(criteria, true);

    // Get Current Location
    Location myLocation = locationManager.getLastKnownLocation(provider);

    // set map type
    mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

    // Get latitude of the current location

    mMap.getUiSettings().setZoomControlsEnabled(true);
    mMap.getUiSettings().setMyLocationButtonEnabled(true);
    mMap.getUiSettings().setCompassEnabled(true);
    mMap.getUiSettings().setRotateGesturesEnabled(true);
    mMap.getUiSettings().setZoomGesturesEnabled(true);


    Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

    if (location != null) {
        double longitude = location.getLongitude();
        double latitude = location.getLatitude();


        // Get longitude of the current location

        // Create a LatLng object for the current location
        LatLng latLng = new LatLng(latitude, longitude);


        ParseObject parkingobject = new ParseObject("Kitchen");
        parkingobject.put("username","Mike");
        ParseGeoPoint point = new ParseGeoPoint(latitude,longitude);  **THINK THE ERROR IS HERE**
        parkingobject.put("Location", point);

        // Show the current location in Google Map
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

        // Zoom in the Google Map
        //LatLng myCoordinates = new LatLng(latitude, longitude);
        //CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(myCoordinates, 20);
        //mMap.animateCamera(yourLocation);
      //  mMap.animateCamera(CameraUpdateFactory.zoomTo(20));
        //mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("You are here!").snippet("Consider yourself located"));




        LatLng fromLatLng = latLng;
        start = latLng;


        Routing routing = new Routing(Routing.TravelMode.DRIVING);
        routing.registerListener(this);
        routing.execute(start, end);
    }
}








    //map = fm.getMap();






@Override
public void onRoutingFailure() {
    // The Routing request failed
}

@Override
public void onRoutingStart() {
    // The Routing Request starts
}

@Override
public void onRoutingSuccess(PolylineOptions mPolyOptions, Route route) {
    PolylineOptions polyOptions = new PolylineOptions();
    polyOptions.color(Color.BLUE);
    polyOptions.width(10);
    polyOptions.addAll(mPolyOptions.getPoints());
    mMap.addPolyline(polyOptions);

    // Start marker
    MarkerOptions options = new MarkerOptions();
    options.position(start);
    //options.icon(BitmapDescriptorFactory.fromResource(R.drawable.home));
    mMap.addMarker(options);

    // End marker
    options = new MarkerOptions();
    options.position(end);
    options.icon(BitmapDescriptorFactory.fromResource(R.drawable.cars));
    mMap.addMarker(options);
}

 }

Can someone guide me in the right direction? Thanks in advance.

2 Answers2

1

The main problem is that you're using getSupportFragmentManager() and you're not using a SupportMapFragment in your xml layout.

Replacing class="com.google.android.gms.maps.MapFragment" with class="com.google.android.gms.maps.SupportMapFragment" made it work for me.

xml layout (Note I just used drawable/common_signin_btn_icon_dark for the button image):

<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"
    tools:context=".MapsActivity" >

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


    <ImageButton
        android:id="@+id/theimagebutton"
        android:text="button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/common_signin_btn_icon_dark"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"/>
</RelativeLayout>

Default code generated by Android Studio:

public class MapsActivity extends FragmentActivity {

    private GoogleMap mMap;

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

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

    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                    .getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }
}

Result:

enter image description here

Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • 1
    Works perfect! Thanks Mate –  Jun 26 '15 at 22:53
  • I have a question, how did you make the map fill the entire screen, meaning I created my map but ontop of the screen there is a Bar with the name MAP, how do i remove that ? –  Jun 26 '15 at 23:06
  • @LexMars That's strange that you get the bar at the top for a FragmentActivity. Do you have a Settings menu? On newer devices that don't have a menu button, the OS adds a bar at the top to access the Settings menu. The screenshot above is from a Samsung S4 that has a menu button, so it makes sense that it would not have an ActionBar. However, I also just now tested my simple version of the code on an HTC One that does not have a menu button, and I didn't get a bar at the top on that device either. – Daniel Nugent Jun 26 '15 at 23:34
  • @LexMars One thing to note is that if you have a Settings menu, you should allow the system to put the ActionBar there for devices that don't have a hardware menu button. But, there are ways to hide the ActionBar if you really need to, see here: http://stackoverflow.com/questions/8500283/how-to-hide-action-bar-before-activity-is-created-and-then-show-it-again – Daniel Nugent Jun 26 '15 at 23:36
  • Oh i see because i have a Nexus 4 and the actionBar shows up, but thanks for the information, thought i was doing something wrong –  Jun 26 '15 at 23:40
0

As @Evan Bashir pointed out in the comments this issue is not related to your layout.

You should use the onMapReady() callback to get a handle to the GoogleMap object.

First implement the callback to your Activity:

public class MainActivity extends FragmentActivity
    implements RoutingListener, OnMapReadyCallback {

Find your MapFragment and set the callback in your onCreate():

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

Finally implement onMapReady() in your MainActivity:

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

This callback is triggered when the map is ready to be used, so you won't get null.

Markus Rubey
  • 5,153
  • 2
  • 21
  • 17
  • I see but i get an error in the onMapReady, The error says that Instance field mMap access is not qualified with *this*.. –  Jun 26 '15 at 22:47