I'm trying to display the current location of the user on the google map inside my app but I don't want to keep updating the location as the user moves. His initial location should be recorded and showed until he closes the app. I have written the following code for this:
private GoogleMap mMap;
protected GoogleApiClient mGoogleApiClient;
Location mLastLocation;
double lat =0, lng=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
buildGoogleApiClient();
// 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);
}
private void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
/**
* 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
mMap.setMyLocationEnabled(true);
LatLng loc = new LatLng(lat, lng);
mMap.addMarker(new MarkerOptions().position(loc).title("New Marker"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(loc));
}
#Override
public void onConnected(Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
lat = mLastLocation.getLatitude();
lng = mLastLocation.getLongitude();
}
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
The problem with this code is that I'm getting the lat, lng after the onMapReady function has already finished executing. I thought that one of the ways to correct this would be create an AsyncTask to ensure that the location data is retrieved before the map. However, I'm trying to implement this in a way that won't use AsyncTask.
Just move the code that creates the Markers from onMapReady() to onConnected(), and move the call buildGoogleApiClient() call from onCreate() to onMapReady():
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
//buildGoogleApiClient();
// 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;
// Add a marker in Sydney and move the camera
mMap.setMyLocationEnabled(true);
//add this here:
buildGoogleApiClient();
//LatLng loc = new LatLng(lat, lng);
//mMap.addMarker(new MarkerOptions().position(loc).title("New Marker"));
//mMap.moveCamera(CameraUpdateFactory.newLatLng(loc));
}
#Override
public void onConnected(Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
lat = mLastLocation.getLatitude();
lng = mLastLocation.getLongitude();
LatLng loc = new LatLng(lat, lng);
mMap.addMarker(new MarkerOptions().position(loc).title("New Marker"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(loc));
}
}
Although, note that you will frequently get null from the call to getLastLocation(). You can use requestLocationUpdates(), and call removeLocationUpdates() when the first location comes in.
Take a look at this answer, it has a complete example of exactly what you're trying to do.
Related
I don't know how to follow the user's location using a service with GPS.
1. You have to create the project using Google Maps Activity:
2. You have to create the Google API key following the link in the comment and insert it here:
3. Make sure to add these permissions in your Manifest.xml :
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET"/>
4. This is an example of the Maps Activity code to get the user's current position:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
LocationManager locationManager;
private static final int REQUEST_LOCATION_PERMISSION = 1;
Marker marker;
LocationListener locationListener;
#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);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_PERMISSION);
}
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
//get the location name from latitude and longitude
Geocoder geocoder = new Geocoder(getApplicationContext());
try {
List<Address> addresses =
geocoder.getFromLocation(latitude, longitude, 1);
String result = addresses.get(0).getLocality() + ":";
result += addresses.get(0).getCountryName();
LatLng latLng = new LatLng(latitude, longitude);
if (marker != null) {
marker.remove();
marker = mMap.addMarker(new MarkerOptions().position(latLng).title(result));
mMap.setMaxZoomPreference(20);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12.0f));
} else {
marker = mMap.addMarker(new MarkerOptions().position(latLng).title(result));
mMap.setMaxZoomPreference(20);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 21.0f));
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
/**
* 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;
}
#Override
protected void onStop() {
super.onStop();
locationManager.removeUpdates(locationListener);
}}
I'm trying to set the marker on my current location, so I tried to convert a Location to a LatLng class:
LatLng mCurrentPlace= new LatLng(location.getLatitude(),location.getLongitude());
Then I recalled the addMarker method:
mMap.addMarker(new MarkerOptions()
.title(getString(R.string.default_info_title))
.position(mCurrentPlace)
.snippet(getString(R.string.default_info_snippet)))
But Launching the application by "Run", it arrested.
Where am I goning wrong?
Thanks.
public void moveMap(GoogleMap gMap, double latitude, double longitude) {
Log.v(TAG, "mapMoved: " + gMap);
LatLng latlng = new LatLng(latitude, longitude);
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(latlng, 6);
gMap.addMarker(new MarkerOptions().position(latlng));
gMap.moveCamera(cu);
}
Call this method where you want location and marker and in on mapasync callback method.
#Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(context);
gMap = googleMap;
gMap.getUiSettings().setMapToolbarEnabled(false);
gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
if(items.get(getLayoutPosition())!=null )
moveMap(gMap,latitude, longitude);
}
public void initializeMapView() {
if (mapView != null) {
// Initialise the MapView
mapView.onCreate(null);
// Set the map ready callback to receive the GoogleMap object
mapView.getMapAsync(this);
}
}
Override onMapReadyCallback method and do this.
Call initializeMapView method in onCreate() or In adapter onBindViewHolder
Try using the LatLng.Builder
LatLng.Builder builder = LatLng.newBuilder();
builder.setLatitude(location.getLatitude());
builder.setLongitude(location.getLongitude());
latLng = builder.build();
MAP Activity
public class MapsActivity2 extends FragmentActivity implements
OnMapReadyCallback, GoogleMap.OnMyLocationButtonClickListener {
private GoogleMap mMap;
LatLng loc;
Location location;
private double currentLatitude = 0;
private double currentLongitude = 0;
LocationManager locationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps2);
// 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);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
/**
* 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 atLnmove 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(-34, 151);
// mMap.addMarker(new MarkerOptions().position(sydney).title("Marker
in Sydney"));
// mMap.moveCamera(CameraUpdateFactory.newLg(sydney));
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mMap.setMyLocationEnabled(true);
mMap.setOnMyLocationButtonClickListener(MapsActivity2.this);
}
public double getLatitude(){
if(location != null){
currentLatitude = location.getLatitude();
}
// return latitude
return currentLatitude;
}
public double getLongitude(){
if(location != null){
currentLongitude = location.getLongitude();
}
// return longitude
return currentLongitude;
}
#Override
public boolean onMyLocationButtonClick() {
location=mMap.getMyLocation();
currentLatitude=getLatitude();
currentLongitude=getLongitude();
LatLng currentLocation = new LatLng(currentLatitude, currentLongitude);
mMap.moveCamera(CameraUpdateFactory.newLatLng(currentLocation));
mMap.addMarker(new MarkerOptions().position(currentLocation).title("Marker in Current Location"));
return false;
}
}
Resource XML
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.atziant.parashar.gmapsapi.MapsActivity2" />
I developed an application for Android in Eclipse with Google maps. The problem is that the blue dot indicating my current location appears always parallel to the road where I am driving, on roads outside cities. But if you are within the city the point already on top of the road.
I'm using this to get my location on the start of the app:
locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
Location myLocation = locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, false));
then I add the blue dot to the map:
googleMap.setMyLocationEnabled(true);
and then I start listening for location changes:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, time, 1, this);
My location change function:
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Lat1 = location.getLatitude();
Long1 = location.getLongitude();
if (Lat1 != Lat || Long1 != Long) {
Lat = location.getLatitude();
Long = location.getLongitude();
if (startNav == true) {
googleMap.animateCamera(CameraUpdateFactory
.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 17));
b = new LatLng(Lat, Long);
if (a != null) {
String urlTopass = makeURL(b.latitude, b.longitude, a.latitude, a.longitude);
new connectAsyncTask(urlTopass).execute();
}
}
}
}
}
My question is why does the blue dot appear parallel to the street instead of on top of it?
Use the FusedLocationProviderAPI. It is recommended over using the older open source Location APIs, especially since you're already using a Google Map so you are already using Google Play Services.
Simply set up a Location Listener, and update your current location Marker in each onLocationChanged() callback. If you only want one location update, just un-register for callbacks after the first callback returns.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null || !mGoogleApiClient.isConnected()){
buildGoogleApiClient();
mGoogleApiClient.connect();
}
if (map == null) {
MapFragment mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap retMap) {
map = retMap;
setUpMap();
}
public void setUpMap(){
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
map.setMyLocationEnabled(true);
}
#Override
protected void onPause(){
super.onPause();
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();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
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 onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
//remove previous current location Marker
if (marker != null){
marker.remove();
}
double dLatitude = mLastLocation.getLatitude();
double dLongitude = mLastLocation.getLongitude();
marker = map.addMarker(new MarkerOptions().position(new LatLng(dLatitude, dLongitude))
.title("My Location").icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(dLatitude, dLongitude), 8));
}
}
I am try to write sample code to test Google maps API in my application. Everything looks good, but when I open Google maps from my app it stops working.
Please give me some help.
public class SmarttreenearbyActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smarttreenearby);
// 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.setMyLocationEnabled(true);
// Add a marker in Sydney and move the camera
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
Location location = locationManager.getLastKnownLocation(provider);
double y = location.getLatitude();
double x = location.getLongitude();
LatLng sydney = new LatLng(x,y);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
Try using the FusedLocationApi. It's an official Google API that allows us to get the location without creating complex location logic by ourselves.
My code is totally fine, i want to get user location on the map as soon as the app is opened. But the app just crashes. Also the program is set to update location and add a marker as soon as its changed, nut that's also is not working. Here's the code
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener {
private GoogleMap mMap;
LocationManager locationManager;
String provider;
#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);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
provider = locationManager.getBestProvider(new Criteria(), false);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
Location location= locationManager.getLastKnownLocation(provider);
double lat =location.getLatitude();
double lng =location.getLongitude();
mMap.addMarker(new MarkerOptions().position(new LatLng(lat, lng)).title("Marker"));
// Add a marker and move the camera
}
#Override
public void onLocationChanged(Location location) {
Double lat = location.getLatitude();
Double lng = location.getLongitude();
mMap.addMarker(new MarkerOptions().position(new LatLng(lat, lng)).title("Marker"));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 10));
Log.i("Latitude", lat.toString());
}
try This.
getLastKnownLocation returns if location is there in cache otherwise it returns null
add a check there
if(location!=null)
{
double lat =location.getLatitude();
double lng =location.getLongitude();
mMap.addMarker(new MarkerOptions().position(new LatLng(lat,lng)).title("Marker"));
}
2 solution use google play services fusedlocation api for better management with location refer here http://coderzpassion.com/android-location-using-google-play-services/
3 try this to addMarker
public void drawMarker(double lat,double lon)
{
if (mMap != null) {
MarkerOptions marker = new MarkerOptions().position(new LatLng(lat, lon)).title(" Maps Tutorial").snippet("Android Ruler");
marker.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
// Moving Camera to a Location with animation
CameraPosition cameraPosition = new CameraPosition.Builder().target(new LatLng(latitude, longitude)).zoom(12).build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
mMap.addMarker(marker);
}
}
for more details refer here http://coderzpassion.com/android-google-maps-v2-tutorial-with-markers/