The Network Location Provider is a key part of an Android location-based solution because it is far more power efficient than GPS and works in places where GPS doesn’t (of course GPS works in places the Network Location Provider doesn’t so it’s often good to use both).
The Network Location Provider capitalizes on the Wi-Fi and cellular radios within your phone to estimate location. This, of course, means that the Network Location Provide only works when those radios are working … and this is where we can easily run into trouble.
Prior to using a location provider, it’s always a good idea to confirm that the user hasn’t disabled it. According the Android docs, the code in the following function checks that the Network Location Provider is enabled.
// Check that Network Location Provider reports enabled boolen isNetLocEnabled(Context context) { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); return lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER); }
What that code actually checks is whether the user has the Location Service enabled … basically … is the following box checked in the device settings?
But what that code does not check is whether the phone’s Wi-Fi radio is turned on or if the phone is in Airplane mode …. that’s these device settings …
If the user disables Wi-Fi, the Network Location Provider can no longer use the Wi-Fi system and will be limited to cellular towers for locates. Using cellular towers generally provides very limited accuracy (in the area of 1 to 3 kilometers … not accurate enough for most systems).
If the user puts the phone in Airplane mode, neither Wi-Fi nor the cellular radio are available .. in this case, the Network Location Provider will simply never report any location values.
And here’s the problem – in both of these cases, LocationManager.isProviderEnabled will still report that the Network Location Provider is enabled. This is a false positive.
To safely use the Network Location Provider, we need to explicitly check the Wi-Fi and Airplane Mode, settings. The following code shows how we can check those.
// Check Wi-Fi is on boolean confirmWiFiAvailable(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return wifiInfo.isAvailable(); } // Check Airplane Mode - we want airplane mode off boolean confirmAirplaneModeOff(Context context) { int airplaneSetting = Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) ; return airplaneSetting == 0; }
Using the above 2 functions along with the isNetLocEnabled function from earlier in this post, we can now use the following function to determine if the Network Location Provider is really usable.
bool isNetLocUsable(Context context) { return isNetLocEnabled(context) && confirmAirplaneModeOff(context) && confirmWiFiAvailable(context); }
With that, we can now be sure that the Network Location Provider is enabled and the underlying services it relies upon are also available.
For complete certainty, in addition to checking the Wi-Fi and Airplane Mode settings prior to using the Network Location Provider, we should also continuously monitor the Wi-Fi and Airplane Mode settings (notification mechanisms exist for each) the entire time we’re using the Network Location Provider. Doing so allows our application to respond accordingly should the user change either setting while we’re using the Network Location Provider.
This post is adapted from Jim’s Plurasight Course…
For more information about Jim and his courses visit his Pluralsight Author Page
Great post, some findings below:
Need to add :
import android.content.Context;
import android.location.LocationManager;
Typo in the code to check location provider :
change boolen to boolean.
good post!
What if the phone is searching for network constantly because no signal?, Ie, no mobile signal network available. the wifi is off and airplane mode disabled, and the method “isProviderEnabled(LocationManager.NETWORK_PROVIDER)” still tell that this network mobile provider is enabled. ¿what do you do? sorry by my bad english
Hi Yeferson … no worries on your english … it looks good to me.
In the scenario you describe, isProviderEnabled should still return true .. That method (isProviderEnabled) simply indicates whether the provider is on, not whether it’s reliable.
What would probably happen is that you would get either very low-accuracy results or old results.
In most cases where one is not able to get a phone signal it means that you are out in the middle of nowhere which is when a GPS provider is preferable.
So if you find that the network provider is returning old results or results with poor accuracy you’ll want to start the GPS provider and start using it instead.
Something you might want to consider is using the Google Play Services location system (something that Google released after I wrote the above post). It takes care of these kinds of scenarios in terms of switching between the network and gps providers, etc.
The following link will take you to a page that walks through its usage…
http://developer.android.com/training/location/retrieve-current.html
I hope that helps,
Jim
Thanks for the prompt reply. I read on the possibility of obtaining the location with google play services, but in my country, the most android devices use 2.2 version so that the minimum target, and the device I use for testing, does not allow me to use the services of google because it asked me upgrade the apk of google play, but still does not allow me to use google services play because is incompatble.
however, your post help me to improve the app development
best regards
Yeferson .. I’m really glad I could help.
[…] APIs for checking network availability (I talked about some of the Android network APIs in this discussion of network-based locates) but those APIs don’t tell the whole […]
Sir if device gps and network both are not enable to get location than how i can get location ?
If both GPS and network locates are disabled, you can’t get the location.
Google’s desire is to provide the user with the ability to control whether apps can get the device location. When both of those options are disabled, the user is telling us that they don’t want our apps to get their location.
Really good post! Thanks a lot!
Thanks Luis!
i need to know how to restrict user can disable the location service.if the user disabled means how to send information to server.the particular user are turned off his gps.
There’s no way to actually prevent a user from disabling location services. Google’s attitude is that it’s the user’s phone and the user therefore has authority over the settings. 🙂
In terms of being notified when the service is disabled …
I have not had to do this myself but you should be able to achieve the desired result with the FusedLocationProviderAPI. Using that API you can register a PendingIntent (directed to a service, for example) that will fire when there’s a change in Location Availability. The corresponding Intent will contain an instance of the LocationAvailability class which you can then use to check whether location is currently available.
If the location is not available, you can then check the current device settings to make a determination as to whether the lack of location availability is due to the current device settings. If it is due to the settings, you can then send a message to the server indicating the change.
hi hedgehogjim,
can we find a user location without using gps or internet but with network provider only???
Sure thing … just indicate that you want to use the network provider when setting up the location provider.