Today when i was trying my code, a few doubtful thing appeared in my mind about gps provider, gps hardware, gps icon and fine location permission.
I observed my code and gps icon on Samsung galaxy s3, Htc one m8. And gps is disabled
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000 * 10, 0, this, Looper.myLooper());
...
#Override
public void onLocationChanged(Location location) {
mListenerRef.get().onLocationChanged(location);
}
Galaxy s3 - Gps icon didn't appear, it didn't fire onLocationChanged method. (Thats okay)
Htc one m8 - Gps icon appeared, blinking, and fired onLocationChanged (But how ?)
At this moment questions pops up
Does ACCESS_FINE_LOCATION permission give the app override gps status on some devices?
So, could the app receive location even gps disabled ?
And then i enabled gps on galaxy s3
(First 2 minutes) Gps icon appeared(but not blinking), fired onLocationChanged method (But how ?)
(After 2 minutes) Gps icon appeared(blinking), fired onLocationChanged method
Again questions pops up
What does gps icon blinking mean ? any extracanonical meaning ?
Does the blinking mean gps hardware trying first fix ?
Or blinking means the provider firing onLocationChanged method ?
What does gps icon blinking mean?
-> Well I hope u r aware that GPS provider dosen't work under roof. So it is completely impossible to get Location update from GPS provider under roof. In such situation if user enables the GPS then the GPS blinking icon appears notifying to user that it is searching for GPS.
-> Once it finds the GPS the icon dosen't blink anymore and u'll get location updates from GPS provider.
-> A still GPS icon means Android system is ready to send location updates from GPS provider.
Htc one m8 - Gps icon appeared, blinking, and fired onLocationChanged (But how ?)
-> It sounds weird getting location updates without enabling it. I'm not sure how u confirmd that u got the Location update.
-> I'll recommend u to check if GPS provider is enabled and then request for location update.
Fine_location permission will enable user to have update from gps, wifi, network. So if gps is unavailable still onlocationChange() can be fired because a recent location may have been fetched via wifi/network.
(quote from the link: http://developer.android.com/guide/topics/location/strategies.html
Note: If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then you need to request only the ACCESS_FINE_LOCATION permission, because it includes permission for both providers. (Permission for ACCESS_COARSE_LOCATION includes permission only for NETWORK_PROVIDER.
)
How your phone showed gps icon without gps being enabled, I doubt it is possible.
With HTC One (M7) the APP has permission to use the GPS and that makes 'GPS' fair game - ('GPS' = 'GPS Spoofer', AGPS [if permitted], an APP that uses WiFi and GPS [thus position is almost always immediately available], and, of course, the Phone's real Hardware GPS / GLONASS / Galileo / etc.).
The HTC UI has an Icon for the Application that uses the GPS (whatever the Phone thinks the Provider IS, a few APPs do check Provider; they don't accept spoofed Locations, EG: Most Subscription APPs, Google Play Store, abrev. GPS;) ).
A second Icon appears for the Hardware GPS. It flashes while it waits for enough Satellites. Indoors, without WiFi, with AGPS, I can get a lock in less than 1/2 min.
You probably want to check the Error when you get your LC Message, since if you're over 100 M off you don't really know where you are and probably don't have a valid position; pending calculations from one more (weak) Satellite may be enough to get you below 50 M Error, at which point you should start accepting the Location as valid (your APP might want to record Error with Coordinates, then Locations can be displayed with a circle representing the uncertainty).
When Developing you want to be certain to buy the most popular Phone (so you have real Hardware to test on, and support the greatest number of Customers), and to buy a FEW Phones with the Hardware that you want your Android APPs to control - in your case buy Phones with different GPS Hardware, for others they may need to buy a few Phones with different Camera Hardware (or WiFi Chip, etc.).
Between the Cell Phone Mfgs version of Android, their UI, and the manner in which their GPS Hardware operates (along with other APPs you have installed, like a Spoofer) you have a LOT of variables that your Program must juggle and many situations (Error Returns) that it must allow for to operate identically on as many Devices as possible.
Related
I'm working on an Android M STB without a GPS chip. In Android settings, Location, I get three choices for Location support -- High Accuracy, Low Bat, GPS Only. The system is defaulting to High Accuracy mode.
The problem here is that when wifi.getScanResults() is called from a background service and one of the location modes needing GPS is enabled, I don't get any results back. The call works fine from a foreground app, only background services are impacted by this. When I change the system over to Location mode Low Bat (which does not require GPS) the background getScanResults() call works as expected.
How do I modify my AOSP build so that the High Accuracy and GPS Only choices won't be presented to the user since there is no GPS chip?
Have you tried modifying the LocationManagerService class so it doesn't load a GPS provider? The following might be what you are looking for.
https://github.com/android/platform_frameworks_base/blob/nougat-release/services/core/java/com/android/server/LocationManagerService.java#L453
The default location mode is set by def_location_providers_allowed in frameworks/base/packages/SettingsProvider/res/values/defaults.xml. Its value can be either gps (GPS only), network (Battery saving) or gps,network (High accuracy).
You could therefore set def_location_providers_allowed to network (e.g. in a device/vendor overlay) and disable or hide the Mode option to the user in Settings → Location since you have only one choice (see packages/apps/Settings/res/xml/location_mode.xml).
Some resources say getLastKnownLocation() merely gives a location of some previous app's Location Change Listener.
But one thing I feel is missing from the conversation -- if the phone has GPS enabled, isn't this GPS tracking/updating as the phone moves? So if I call getLastKnownLocation(), isn't it getting the current GPS from the phone's constantly-updated GPS?
If so, then why do people warn against using it / accuse it of potentially getting a "stale" location? If the GPS is being tracked / updated, and getLastKnownLocation() makes a one-time grab of it's current position, what makes getLastKnownLocation() bad?
What am I mistaken about the Locations service or GPS?
The documentation says: Returns a Location indicating the data from the last known location fix obtained from the given provider.
Also, about the "out of date location": This can be done without starting the provider. Note that this location could be out-of-date, for example if the device was turned off and moved to another location. ("This" refers to getting the last known location).
Also, taken from LocationProvider docs:
Each provider has a set of criteria under which it may be used; for example, some providers require GPS hardware and visibility to a number of satellites; others require the use of the cellular radio, or access to a specific carrier's network, or to the internet. They may also have different battery consumption characteristics or monetary costs to the user.
if the phone has GPS enabled, isn't this GPS tracking/updating as the phone moves?
Well, it is, but not constantly. This has to do with battery consumption, if the phone was constantly updating the GPS location, the battery life would suffer a lot. The GPS location is usually updated when some app requests it. But even that request is not guaranteed to succeed. For example, suppose your going into a tunnel. Some application requests to update the GPS coordinates right before entering the tunnel and it succeeds. Now, you've entered the tunnel, which is 5km long. Most probably your device won't be able to get a GPS fix from the tunnel, so for the next 5km (at least) getLastKnownLocation() will return an outdated value, since the devices last known location was at the entrance of the tunnel.
What you could do is explicitly request to update the GPS location, that however might take some time and there are no guarantees that it will succeed.
You have the assumption "if the phone has GPS enabled, isn't this GPS tracking/updating as the phone moves". This assumption is incorrect. The GPS functionality takes up a lot of battery life so it should be used sparingly and almost certainly not all the time.
I am using the following code for getting the location:
localCriteria = new Criteria();
localCriteria.setAccuracy(Criteria.ACCURACY_FINE);
localCriteria.setAltitudeRequired(false);
localCriteria.setBearingRequired(false);
localCriteria.setCostAllowed(true);
localCriteria.setSpeedRequired(true);
localCriteria.setPowerRequirement(Criteria.POWER_LOW);
mProvider = mLocMan.getBestProvider(localCriteria, true);
mLocMan.requestLocationUpdates(mProvider, 0, 0f, this);
Although my phone settings is set to Medium Accuracy ( meaning network and wifi, no gps), but when I run the application, it displays the GPS icon on the on the notification bar with the location being set by GPS!!
Shouldn't the GPS be disabled and no location acquired as a result? I am not sure what is happening
Thank you
The icon is not only used for GPS-locating but for all location-acquiring. Setting the location settings to 'medium'/ power saving means that GPS isn't used to acquire the location, but wifi and mobile network cells are. The phone can still locate itself, thus the icon appears.
I don't even know though how to completely disable any location services on Android 5.0.
You can check for yourself what Provider (source of locattion) was used when receiving the Location. If the Provider IS Gps, this might be an actual bug in your firmware / Android version.
In my application i need to show Current Lcoation every 30 minutes.To implement this, I have used Timer to trigger every 30 minutes.
It's working fine in some android devices like HTC Wildfire S, Sony Xperia V...
but it's not working in Samsung S Duos and HTC One X...Because when i request GPS it returning NULL as Current Location value.I dont' know why that devices are not support my application can anyone help with profe.
You should check for provider availability like this:
List<String> providers = locationManager.getProviders(true);
and then you start listening to available sensors:
if (providers.contains(LocationManager.GPS_PROVIDER))
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,...);
}
If the sensors you want are not available you should popup a dialog to user to ask him to activate the GPS, or what you want.
Also, I have a recommendation to you: you should not start requesting location updates with Timer, you should pass to requestLocationUpdates() the minimum time & distance you want location updates.
I have code that successfully gets location updates from multiple providers and filters them to give a current best estimate.
I added code to check for the returned Location.hasSpeed() and .hasBearing() values to do some bearing related calculations when the user is actually moving.
It all works fine on a Huawei Sonic running 2.3.3, but on the Google Nexus S running 4.0.4 the GPS provider's Location always returns false for .hasSpeed() and 0 for .getSpeed().
When I register my location listener, the GPS provider returns true for .supportsSpeed() but it never returns the speed in a Location even when the accuracy is down to 30m and it is physically moving (in a car, on the dashboard for max reception, screen on).
Is there some difference from 2.3.x to ICS 4.x?
Do I have to implement my own speed calculation even when the provider reports support?
Google Nexus S has history of problems with GPS. I don't think that it's specifically related to ICS. Have you tried Factory data reset the phone and then retry it?