OnLocationChanged not fired on some devices - android

I'm aware that there's a lot of 'similar' questions, but none of them provided a useful answer.
I am trying to listen to location updates, both from network and GPS. The LocationListener initialization is pretty standard:
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 15000, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 15000, 0, locationListener);
I tested it on two devices, Samsung Galaxy S4 (SM-N910F) and LG G Flex 2 (H950). On the first device onLocationChanged is called as expected (only from 'network' provider), while the event is never fired on the second.
Both devices are set on 'High Accuracy' mode. I tried the second device on Wi-Fi as well as on 4G LTE connection. Since I use Google Maps API, I can clearly see the user marker moving on map, yet the event is never called.
Any idea why onLocationUpdated is never called on the second device?
Additionally, I read that GPS takes a very long time to fix. Is there any point in requesting updates from the GPS provider?
Thanks!

May I suggest you start using Google Play location APIs.
The Google Play services location APIs are preferred over the Android
framework location APIs (android.location) as a way of adding location
awareness to your app. If you are currently using the Android
framework location APIs, you are strongly encouraged to switch to the
Google Play services location APIs as soon as possible.
https://developer.android.com/training/location/index.html

Related

Best way of setting mocklocaiton on Android

Apparently there are 2 ways of setting mock location in the Android ( currently playing with Android 11 )
One way using FusedLocationProviderClient:
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.setMockMode(true);
mFusedLocationClient.setMockLocation(createLocation(LAT, LNG, ACCURACY));
Another using LocationManager:
LocationManager lm = (LocationManager) ctx.getSystemService(
Context.LOCATION_SERVICE);
lm.addTestProvider(providerName, false, false, false, false, false,
true, true, 1, 1);
lm.setTestProviderEnabled(providerName, true);
Location mockLocation = createLocation(LAT, LNG, ACCURACY);
lm.setTestProviderLocation(providerName, mockLocation);
Wondering what is the right way.
For me second works fine, the first one in not ( still investigating )
But I wondering what is the RIGHT way?
Also wondering why there are 2 distinct ways ?
The difference is LocationManager vs LocationServices.
LocationManager is the built in Android location functionality. It provides access to location via GPS or network identification. Every device has this.
LocationServices is a Google Play Services functionality. It main value is the "fused" provider that uses network, slight GPS use, and other sources of data to provide a location. It tends to be more accurate than network with less battery power than GPS (but not as accurate/precise as GPS). Only devices whose OEMs pay Google for access to Google Play Services have this (this is mainly an issue in Asia and Africa).
Two different systems, two different ways of mocking location. Your top one works if you're getting locations via Google Play Services, the bottom if via LocationManager. Use the one matching the way you get locations normally.

FusedLocationProviderClient.requestLocationUpdates not getting altitudes

I'm experiencing some strange behavior with our Android app using Fused location Provider Api.
In some devices this api is not returning the altitudes
I can check it on Moto G 2d generation but our users report the same behavior at least on Moto G 3d generation, Nexus 6 and Moto X Play. In the great majority of other devices altitudes are returning well so I'm pretty sure that my implementation of the Api is correct.
The funny part is that I realized that if I use android.location.LocationManager
, for example, like this
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 0, locationListener);
the app is starting to receive altitudes, not only on 'LocationListener' subscribed to 'LocationManager' but on LocationCallback of the Fused Location Provider Api as well.
But this breaks the optimization made by Fused location Provider Api and seems silly to use both apis.
I can experience similar behavior if I use both google maps and our app. While using google maps our app is receiving altitudes but when google maps is closed Fused Location Provider Api stops to send altitudes as well.
When I'm talking about not receiving altitudes I mean that location.hasAltitude() == false and location.getAltitude() == 0
This is my implementation to request location updates:
LocationServices.getFusedLocationProviderClient(context);
LocationRequest currentLocationRequest = new LocationRequest();
currentLocationRequest.setInterval(500)
.setFastestInterval(0)
.setMaxWaitTime(0)
.setSmallestDisplacement(0)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
fusedLocationProviderClient.requestLocationUpdates(currentLocationRequest, locationCallback);
It seems to me that FusedLocationProviderClient is not turning on some hardware stuff on this devices, so may be a bug on this Api, but I didn't found any one else reporting that, except this similar behavior:
Nexus 6 Fused Location Provider getSpeed returns 0
Thanks.
Since hasAltitude() returns false there are parameters missing to the FusedLocationProvider that would make it possible to provide a confident altitude. This depends largely on the manufacturers setup and devices capabilities which is one of the reasons the Provider exists.
The reason could also be an insufficient GPS-lock or something else but since you could narrow it down to certain devices I would expect that not to be the issue.
You can try (as you already did) other location data sources and check if their results return an altitude, but keep in mind that that might be less consistent. My first try would be the old Location provider.
But there is no way for you to fix the misbehavior of the FusedLocationProvider it is a manufacturer config fail.

Android location accuracy

I have the following code implemented to retrieve location values on Android:
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
On Android 2.3 and 4.1 this works great and returns updates at 180 samples per hour with a resolution down to 100m or less.
However, on Android 4.3 something has changed so this only provides updates at 5 samples per hour and a resolution at 2km. I haven't tested on later versions.
What has changed? Is it possible to return to the old accuracy levels again? I don't want to force GPS for power reasons. The app has ACCESS_COARSE_LOCATION permissions.
I have been testing this on a Samsung S3 if it makes a difference.
Use Google's LocationServices API instead:
https://developer.android.com/training/location/receive-location-updates.html
LocationManager.NETWORK_PROVIDER do not provide accurate location it provides you the location according to the cell tower you connected,sometimes it provides location with accuracy of 100m sometimes with 2-3km,if you do not want to get the location from gps due to power reasons i would suggest you to use fused location provides as this is an efficient and effective way to get the location on android and Google also recommends this,you can read more here in this example http://www.kpbird.com/2013/06/fused-location-provider-example.html

GPS works better with google maps than my App android

I have an app in android using GoogleMaps API.
When i use google maps, I active gps and it find me so fast.
When i use my app, it takes some seconds, and if I'm in my house, gps dont find me. WHY ?
A short summary of my code:
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
MyLocationListener = new MyLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
7000,
5,
MyLocationListener
);
Thx for answers and sorry for my poor english
EDIT
Thx for answers ! the problem is that i dont want to use network provider. Wifi is exelent, and 3g have a 400 meters error jejeej.
I only want to know, why google maps, using GPS, find me in 1 second with perfect position Although I stay in a house.
Your answer is "use coarse locate". If google maps use network providers befor gps, its impossible he find me so fast. :(
GPS is using satelites, When you are indoor it can't get the signal from the satelites hence it can't find location (can't get a fix).
The GPS needs signals from at least 4 satelites to get a proper fix, that usually takes a few seconds, once you already have a fix you can maintaine it very easly. therfore if you are using google maps it will get you a fix faster.
To get a better understand on how GPS works, check this link
You might want to use different location approachs for getting location indoor (coarse location could be the answer). I would also consider using the fused location by Google play services, it gives you a wrap up on the location providers and get you location based on what avilable at the time (meaning GPS, coarse - wifi or network).
You should try using Coarse locates for a quick locate followed by a fine locate to have a more accurate location. The coarse locate is usually very fast, while the fine one takes more time.
Basically, the idea is to do multiple locates and overriding the less accurate ones by the newer and more accurate locates.
You can find more info on the Android dev doc: http://developer.android.com/guide/topics/location/strategies.html
EDIT: if Google Maps is able to find you so fast, it is because you are not moving and they use the knowledge of the last location. Please read the above link that gives a lot of useful information for Location strategies (and it works very well).

Checking GPS status with Google Play Services

Google recommends now using Google Play Services to manage user location.
But how can we, using this API, check wether GPS is turned on in device or if we still have gps connection?
In com.google.android.gms.location.LocationListener we have only one method abstract void onLocationChanged(Location location) which is called when the location has changed, but we don't know there anything about GPS status.
How to use Google Play Services like "old" LocationManager and LocationListener?
But how can we, using this API, check wether GPS is turned on in device or if we still have gps connection?
You can't, AFAICT. I suppose the argument is that since LocationClient is blending data from several sources, there is no API to determine if any specific source is or is not being used.
You will need to use LocationManager if you want to determine whether GPS is enabled or not.

Categories

Resources