I don't think it is possible w/out actually using a LocationProvider, but figured I would see if anyone had any thoughts.
Basically I have an app which has a PageView w/ a fragment which contains a the new MapView 2.0
I can easily pull the my Location by way of getMyLocation from the GoogleMap object.
I have had issues in past; across some devices, using both NetworkLocation & GpsLocation providers at the same time. Since I can just pull my location from the GoogleMap, I get a simple way to check my location.
My only issue is that I can watch for map panning to update the map by handling onCameraChanged, but it does not handle the location changing inside the map.
My current implementation is that I have a MapView and LocationProvider.. The location provider is in a service, and is set to update based on a user determined time (1,5,10,15,30,60 seconds). The activities connect to the service via AIDL, if there is >0 connected activities the locationProvider is enabled, if not, it turns off. This really has little bearing to the Google Map though, if we don't handle loss of GPS signal the same as Google maps, the location we get is different than the Google maps.
My first of 3 options:
get a provider, and pass that in where I could get a callback on location change (did not really want to do this). This would involve be by way of LocationSource..
Second option
get the current location provider that I am using in my current service, and each time it updates, just grab the location from the map. I suppose this would work, but seems a bit redundant, and still have issue of managing LocationProviders when screen is turned off etc.. (Don't have to do that w/ google map)
The other option would be to have a service that is passed an interface to the map object which can query the current location. And do so every x seconds that the user has indicated.. I can reuse most of the service for this, would just have to set it up to keep calling.
The other thing I was thinking of was maybe just using a passive provider to update the current location, from using the current MapView.
My only other consideration is Spoofing: I want to try and prevent location spoofing. I can make it so we don't allow Mock Locations. But that does not mean it can't be spoofed still.
So... Any thoughts would be greatly appreciated. Thanks.
Google introduced the new LocationClient and associated LocationListener (the previously introduced OnMyLocationChangeListener interface is now deprecated).
Related
I am using FusedLocationProviderClient to get location updates in a foreground service. On testing and observing for few days, I found wrong locations which was far away from my actual location by around 4 kms similar to this, but the LocationResult had an accuracy of 24 meters. How is this even possible?
It can be eliminated if the accuracy was around 4 kms. This behavior does not occur very often but occurs atleast once in 4 among 10 devices. It becomes a problem when I calculate distance traveled.
I can tell it's not a cached location because I used to turn off and on Location Services everyday. (As per docs, turning off Location Services clears cache location.)
Any idea why it's giving wrong location and how to eliminate it? And also clearing cache locations without turning off Location Services?
FusedLocationProvider CAN give incorrect results like that when gps connectivity for device is down(or insufficient satellites are in "view" to provide accurate data). It will use the nearest cell tower/location data provided by the wifi router(google tracks this automatically) giving WILDLY incorrect results in places where google doesn't have a strong location mapping presence - which is anywhere outside an urban center.
You have imho two options:
Use the non googleplay based solution based on location service - this has an option for ignoring non-gps location data(wifi/cellular).
LocationManager locationManager = (LocationManager)
getApplicationContext().getSystemService(LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_Provider);
You can even specify the number of satellites required for acceptable data so you can get REALLY accurate location data. You will lose information when the gps doesn't receive coordinates (like indoors), but in exchange will have less "noise" from incorrectly mapped location, as per your requirement.
Use a "snap to roads" API. There is a free version using open street map data called Project OSRM(Open Source Routing Machine) that provides a backend when hosted (locally or in cloud) using docker or building source yourself (details in link).
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
This request will return a location that is "snapped" to the nearest road. There are various options such as giving priority to highways etc. You can then discard the points that are not on the "path" that the user was previously on as rapidly shifting to a road 4km away and then coming back again is not likely.
I've been working on an app that needs to be location-aware, and I've noticed that there are two (or more) methods of receiving location: with Google Play services (as seen here developer.android.com/training/location/retrieve-current.html#GetLocation) and with Location Manager, Providers etc. (as seen here http://www.vogella.com/tutorials/AndroidLocationAPI/article.html#locationapi_criteria).
What is the difference between these methods (if there is any)? Which one is more accurate?
edit: ok, I see that I sent the wrong link on the first thing. Won't this code (http://developer.android.com/training/location/receive-location-updates.html) give me location updates? Generally, what's the most accurate way to get my location?
The one with the GPS is accurate and that which is based on Network is not. Google Play Service use FUSE api to get the GPS location first, if the location is found (that's great), otherwise it will try to get location fix from Network Tower. In Short the one with GPS is accurate
The first method provides the details of LastKnownLocation. ie. the last location received from GPS or network provider when you or other apps accessed the location services. After that there are chances you moved a lot and it need not be your current location. So if You are planning to create an application that requires accurate location tracing, You should fetch the location as in the "Vogella" method. If the current location is unavailable, you can try using the last known location (As a plan B :-)).
I am currently showing the user's current location on the map with
setMyLocationEnabled(true);
Is there a callback or another way I can tell when the blue dot showing the current location appears on the map. I can setup a LocationListener and assume that when onLocationChanged is called that the blue dot is showing on the map but I don't need location updates in my app so implementing a LocationListener seems like overkill. I couldn't find any interfaces to implement in the documentation for a callback such as this. Does anyone know of any other approaches I can use?
You can add a listener to location change directly on the GoogleMap object. Then remove it after the first callback if you're not interested in further updates.
Check setOnMyLocationChangeListener().
It's deprecated, but it works (or at least it did work - I haven't used it recently).
Seems like most of the location methods are depreciated for android. The one under development is the Location client. And from the documentation
This interface is deprecated. use LocationClient instead. LocationClient provides improved location finding and power usage and is used by the "My Location" blue dot. See the MyLocationDemoActivity in the sample applications folder for example example code, or the Location Developer Guide.
And as for the interface LocationClient.requestLocationUpdates() seems to be the way to go.
I have two different classes in my application that implement LocationListener. One of them is only used as needed to get the user's current location, while the other is constantly run in the background to keep data on the user's speed.
On my test device, this causes no problems. Some other people testing however have said that their device "locks" (I have not seen this occur, so I'm unsure what they truly mean by this) when trying to acquire the location.
Is it possible that this is just their phone having a weak GPS fix, or could this be some weird hardware issue that occurs when two different threads are trying to gain the location via GPS? If so, what's the best way to work around this? Thanks.
I would suggest you use the new fused provider that is part of Google Play Services. I would not set two LocationListeners. Since you will be constantly tracking the user's location, by using the new LocationClient you can use its getLastLocation() to retrieve the most recent best, cached location the device has, which is really likely to be one from the constant updates you are already retrieving. The fused provider will also determine which one is the best provider to take the location from, you do not need to worry about that logic.
I am using Google-Play-Services to track user activities. In case of a walking activity or bicycle activity I want to calculate the rough speed the user is moving. Is there any simple method? Location updates by Google-Play-Services are sometimes quite inaccurate since there is no good GPS signal in particular areas.
By the way, I realised the GPS location is getting very accurate when I start the google maps navigation application. I wonder how to get a location with the same percision without starting Google Navigation.
If the Location was created by GPS, then use location.getSpeed().