I use the Google Maps API in my Android app and locate the user with
LocationManager and getLongitude(), getLatitude().
But now there have to be strange settings on the mobile phone to get a map. The location setting has to be changed to only use GPS, and even then it's not working all the time, sometimes the map is not loaded. If not loaded the app shuts down at the point the first marker is set because of NullPointerException.
Why is this and how can I prevent it?
I already tried with getMapAsync but it didn't help.
GoogleMap googleMap;
LocationManager locationManager;
String provider;
Criteria criteria;
Location myLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
try {
if(googleMap == null) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
}
googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
googleMap.setMyLocationEnabled(true);
googleMap.setTrafficEnabled(true);
googleMap.setIndoorEnabled(true);
googleMap.setBuildingsEnabled(true);
googleMap.getUiSettings().setZoomControlsEnabled(true);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, true);
myLocation = locationManager.getLastKnownLocation(provider);
double latitude = myLocation.getLatitude();
double longitude = myLocation.getLongitude();
LatLng latLng = new LatLng(latitude, longitude);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
googleMap.animateCamera(CameraUpdateFactory.zoomTo(14));
iconDone = R.drawable.markerdone;
icon = R.drawable.marker;
}
catch(Exception e) {
e.printStackTrace();
}
Marker marker1 = googleMap.addMarker(new MarkerOptions()
.position(new LatLng(49.793012, 9.926201))
.title(getString(R.string.Title1))
.snippet("")
.icon(BitmapDescriptorFactory.fromResource(icon)));
The problem is that you're calling getLastKnownLocation(), which will frequently return a null Location, since it doesn't explicitly request a new location lock.
So, when your app is crashing, it's due to a NullPointerException when trying to de-reference the Location object.
It's best to request location updates, and if you only need one, just un-register for location updates once the first onLocationChanged() callback comes in.
Here is an example using the FusedLocationProvider API, which automatically uses Network Location as well as GPS Location if needed:
Relevant imports for the Activity:
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
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.OnMapReadyCallback;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
Activity:
public class MainActivity extends AppCompatActivity
implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
GoogleMap googleMap;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Marker marker;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildGoogleApiClient();
mGoogleApiClient.connect();
}
#Override
protected void onResume() {
super.onResume();
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
protected synchronized void buildGoogleApiClient() {
Toast.makeText(this,"buildGoogleApiClient", Toast.LENGTH_SHORT).show();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onMapReady(GoogleMap map) {
googleMap = map;
setUpMap();
}
public void setUpMap() {
googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setZoomControlsEnabled(true);
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10);
mLocationRequest.setFastestInterval(10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setSmallestDisplacement(0.1F);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
//unregister location updates
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
//remove previously placed Marker
if (marker != null) {
marker.remove();
}
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
//place marker where user just clicked
marker = googleMap.addMarker(new MarkerOptions()
.position(latLng)
.title("Current Location")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLng).zoom(5).build();
googleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
build.gradle (change to whatever version of Google Play Services you are currently using):
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.google.android.gms:play-services:7.5.0'
}
SupportMapFragment in the layout xml (you can use a MapFragment as well):
<fragment
android:id="#+id/map"
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Using only Network Location:
The Map moves to the current location seconds after launch:
Related
I'm developing an application using Google Maps API.
I'm trying to add a marker where the user press on the map and to draw a line between markers that the user have created.
I'v tried to add the method SetOnMapClickListener but every time I run my application in the virtual device it's immediately crushes.
I've also tried to locate the method in OnCreate method and in OnMapReady, but this is not working either.
I succeeded to add new markers but only by writing them...
On some tutorials that I've found I saw that they assign the google map object with mapFragment.getMap(), but I don't have this method.
Thanks!
Here is my code:
package com.example.user.testmap;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
double lit = latLng.latitude;
double lon = latLng.longitude;
mMap.addMarker(new MarkerOptions().position(new LatLng(lit, lon)));
}
});
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
mMap.addMarker(new MarkerOptions().position(new LatLng(20, 5)));
mMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(20, 5)));
}
}
try to remove your mMap.setOnMapClickListener in onCreate() then implements the GoogleMap.OnMapClickListener
like this.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMapClickListener {
private GoogleMap mMap;
private ArrayList<Marker> arrMarkerList;
private ArrayList<Polyline> arrPolylineList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapClickListener(this);
arrMarkerList = new ArrayList<>();
arrPolylineList = new ArrayList<>();
}
#Override
public void onMapClick(LatLng latLng) {
double lit = latLng.latitude;
double lon = latLng.longitude;
arrMarkerList.add(mMap.addMarker(new MarkerOptions().position(new LatLng(lit, lon))));
// Removing the existing polyline to draw a new.
for (Polyline polyline : arrPolylineList) {
polyline.remove();
}
if (arrMarkerList.size() > 1) {
PolylineOptions polylineOptions = new PolylineOptions();
for (Marker marker : arrMarkerList) {
polylineOptions.add(marker.getPosition());
}
arrPolylineList.add(mMap.addPolyline(polylineOptions));
}
}
}
Instead of LocationManager, I have use LocationServices method to get current gps location and location updates.
this is the code:
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();//PRIORITY_BALANCED_POWER_ACCURACY
mLocationRequest.setInterval(1000*30*1);
mLocationRequest.setFastestInterval(1000*30*1);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest,this);
}
}
public void onLocationChanged(Location location) { mLastLocation = location;
if (mCurrLocationMarker != null)
{
mCurrLocationMarker.remove();
}
//Place current location marker
latLng = new LatLng(location.getLatitude(), location.getLongitude());
lat= location.getLatitude();
log=location.getLongitude();
trim_check_location_change(lat,log);
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(""+s);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
CurrentLocation = latLng;
}
As I move from from one place to another, blue marker moves accordingly.
however onlocationchanged method never gets called.
I've developed fused location api demo application and utility pack here.
General Utilities
Try it if useful for you. To get location using fused location api, you just have to write following snippet...
new LocationHandler(this)
.setLocationListener(new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// Get the best known location
}
}).start();
And if you want to customise it, simply find documentation here...
https://github.com/abhishek-tm/general-utilities-android/wiki/Location-Handler
Update
I've written a sample code according to your need, try this one...
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import in.teramatrix.utilities.service.LocationHandler;
import in.teramatrix.utilities.util.MapUtils;
/**
* Lets see how to use utilities module by implementing location listener.
*
* #author Khan
*/
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, LocationListener {
private GoogleMap map;
private Marker marker;
private LocationHandler locationHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Obtaining an instance of map
FragmentManager manager = getSupportFragmentManager();
SupportMapFragment mapFragment = (SupportMapFragment) manager.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
this.locationHandler = new LocationHandler(this)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(5000)
.setFastestInterval(10000)
.setLocationListener(this);
}
#Override
public void onMapReady(GoogleMap map) {
this.map = map;
this.locationHandler.start();
}
#Override
public void onLocationChanged(Location location) {
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
if (marker == null) {
marker = MapUtils.addMarker(map, latLng, R.drawable.ic_current_location);
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14), 500, null);
} else {
marker.setPosition(latLng);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (locationHandler != null) {
locationHandler.stop();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LocationHandler.REQUEST_LOCATION) {
locationHandler.start();
}
}
}
Hope it will help you.
I'm trying to put a marker at my current location (using the google maps api). While direct input values in the LatLng are working, indirectly calling currentLocation.getLatitude() and currentLocation.getLongitude() is crashing my application for some reason, i know it's this line because the app doesn't crash until i add this line.
Here's my MapsActivity class-
package com.example.shreyass.tourist;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.internal.IGoogleMapDelegate;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.common.api.GoogleApiClient;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener{
private GoogleMap mMap;
private Location currentLocation;
GoogleApiClient googleApiClient;
#Override
protected void onStop() {
super.onStop();
googleApiClient.disconnect();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super`enter code here`.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
googleApiClient.connect();
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker at current location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if(ContextCompat.checkSelfPermission(MapsActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)
!=PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},1);
}
else {
currentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
try this changes..
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener{
private GoogleMap mMap;
private Location currentLocation;
GoogleApiClient googleApiClient;
#Override
protected void onStop() {
super.onStop();
googleApiClient.disconnect();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super`enter code here`.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
googleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if(ContextCompat.checkSelfPermission(MapsActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)
!=PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},1);
}
else {
currentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker at current location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
So for some reason when i try adding a marker to a geopoint, the marker fails to show up at the given location. I tried researching what could be the problem but for some reason my code seems to follow everything that i researched on. Can someone guide me in the right direction?
import android.content.Context;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
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.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.text.DecimalFormat;
public class MapsActivity extends FragmentActivity {
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
/**
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
* installed) and the map has not already been instantiated.. This will ensure that we only ever
* call {#link #setUpMap()} once when {#link #mMap} is not null.
* <p/>
* If it isn't installed {#link SupportMapFragment} (and
* {#link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
* install/update the Google Play services APK on their device.
* <p/>
* A user can return to this FragmentActivity after following the prompt and correctly
* installing/updating/enabling the Google Play services. Since the FragmentActivity may not
* have been completely destroyed during this process (it is likely that it would only be
* stopped or paused), {#link #onCreate(Bundle)} may not be called again so we should call this
* method in {#link #onResume()} to guarantee that it will be called.
*/
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() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker").snippet("Snippet"));
// 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
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);
// 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 toLatLng = new LatLng(40.6937, 73.9859);
mMap.addMarker(new MarkerOptions().position( new LatLng(40.6937, 73.9859)).title("You location is here!").snippet("Consider it located"));
}
}
public void onFinish() {
// Your code here to do something after the Map is rendered
}
}
The main issue you mention:
the marker fails to show up at the given location
It looks like the main reason is that the getLastKnownLocation() is returning null, so it never gets into your code which sets the Marker at the current position.
Instead of calling that method, you can set up a location listener, which will explicitly request a new location.
I cleaned up your code a bit, and got it working. Note that I removed the use of getLastKnownLocation(), and moved the logic you had in there to the onLocationChanged() callback.
I also added functionality to remove the previous "current location" Marker, and add a new one every time the location changes.
Also note that the one Marker showing up at the equator near Africa was due to this line, so I just commented that out:
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker").snippet("Snippet"));
Here is the full updated class code:
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
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.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import android.location.Criteria;
public class MapsActivity extends FragmentActivity implements LocationListener {
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
LocationManager locationManager;
Marker marker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
#Override
protected void onPause() {
super.onPause();
//remove location listener
if (locationManager != null){
locationManager.removeUpdates(this);
}
}
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() {
//This was the Marker at equator near Africa
//mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker").snippet("Snippet"));
// Enable MyLocation Layer of Google Map
mMap.setMyLocationEnabled(true);
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
mMap.getUiSettings().setCompassEnabled(true);
mMap.getUiSettings().setRotateGesturesEnabled(true);
mMap.getUiSettings().setZoomGesturesEnabled(true);
// Get LocationManager object from System Service LOCATION_SERVICE
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
}
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
}
}
public void onFinish() {
// Your code here to do something after the Map is rendered
}
#Override
public void onLocationChanged(Location location) {
double longitude = location.getLongitude();
double latitude = location.getLatitude();
// Create a LatLng object for the current location
LatLng latLng = new LatLng(latitude, longitude);
// Show the current location in Google Map
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(15));
if (marker != null) {
marker.remove();
}
marker = mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude))
.title("You are here!").snippet("Consider yourself located")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
Result:
Edit:
You picked an interesting spot to put your hard-coded Marker.
I replaced the marker code with this:
LatLng toLatLng = new LatLng(40.6937, 73.9859);
// Create a LatLng object for the current location
LatLng latLng = new LatLng(40.6937, 73.9859);
// Show the current location in Google Map
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(15));
if (marker != null) {
marker.remove();
}
marker = mMap.addMarker(new MarkerOptions().position(new LatLng(40.6937, 73.9859))
.title("You are here!").snippet("Consider yourself located")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));
And it placed the marker at the given location. Note that there is some strange effect going on due to different satellite images.
Initial result:
Zoomed out to see where we are!
I was using LocationManager to track the user current location, Now after changing location manager to FusedLocation API, the blue dot and circle is not shown even after setting map.setMyLocationEnabled(true). I can see the current location icon on top right corner in my map fragment but clicking on it does nothing. I reverted my code to LocationManager now i am able to see the blue dot pointing to my current location. what could be wrong using Fused Location API.
For targeting api-23 or higher
See this answer....
For targeting api-22 and lower:
This code works for me, it has the MyLocation blue dot/circle, and it also places a Marker on the current location using the Fused Location Provider.
Here is the entire Activity code I used:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import android.location.Location;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.OnMapReadyCallback;
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
LocationListener,
OnMapReadyCallback {
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
LatLng latLng;
GoogleMap mGoogleMap;
SupportMapFragment mFragment;
Marker mCurrLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setMyLocationEnabled(true);
buildGoogleApiClient();
mGoogleApiClient.connect();
}
#Override
public void onPause() {
super.onPause();
//Unregister for location callbacks:
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
protected synchronized void buildGoogleApiClient() {
Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onConnected(Bundle bundle) {
Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
//place marker at current position
mGoogleMap.clear();
latLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocation = mGoogleMap.addMarker(markerOptions);
}
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000); //5 seconds
mLocationRequest.setFastestInterval(3000); //3 seconds
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setSmallestDisplacement(0.1F); //1/10 meter
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
}
#Override
public void onLocationChanged(Location location) {
//remove previous current location marker and add new one at current position
if (mCurrLocation != null) {
mCurrLocation.remove();
}
latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocation = mGoogleMap.addMarker(markerOptions);
Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show();
//If you only need one location, unregister the listener
//LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<fragment
class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
Result:
You have to add the following permissions in manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
MarkerOptions().position(new LatLng(
location.getLatitude(), location.getLongitude()));
Try this,
if (location!=null) {
googleMap.clear();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(location.getLatitude(), location.getLongitude())).zoom(14).build();
googleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
// create markerOptions
MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(
location.getLatitude(), location.getLongitude()));
// ROSE color icon
markerOptions.icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
markerOptions.position(latLng);
// adding markerOptions
Marker marker = googleMap.addMarker(markerOptions);
dropPinEffect(marker);
}