Home » Android » android – LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) is not reliable, why?

android – LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) is not reliable, why?

Posted by: admin June 15, 2020 Leave a comment

Questions:

One user of my app reported that app tells network for location is off even he did turn it on. He sent me few screen shots and they made me think;

LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)

is not working properly. His phone is running Android 4.1.2 and first I thought this is the cause of this issue. But it was not the case. He sent me a screen shot of that setting too.

Then I googled and found this. The question seems to help me but unfortunately answer was not helpful for this case and questioner did not pursue farther.

My app is related to location and have been using LocationManager.isProviderEnabled to know GPS and Network for location is on or off. I have never been told my app is not properly knowing those settings until recently. He is the first user who reported the issue. I learned there are another method to know GPS and Network for location settings, by seeing Secure.LOCATION_PROVIDERS_ALLOWED. To see how this method work on his phone, I wrote simple app and asked him to run. This app does simple task and shows text on screen.

LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
    string = "GPS=on\n";
}
else
{
    string = "GPS=off\n";
}
if(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
{
    string += "Network=on\n";
}
else
{
    string += "Network=off\n";
}
String status = android.provider.Settings.Secure.getString(getContentResolver(), Secure.LOCATION_PROVIDERS_ALLOWED);
if(status.contains("gps"))
{
    string += "GPS=on\n";
}
else
{
    string += "GPS=off\n";
}
if(status.contains("network"))
{
    string += "Network=on\n";
}
else
{
    string += "Network=off\n";
}

He sent back screen shot again. It looks;

GPS=on
Network=off
GPS=on
Network=on

This result did not make me happy. There could be some possibilities for this.

  • As other person questioned before, this issue has been there on some phones.
  • Google broke this with 4.1.2. isProviderEnabled does not work on this version.
  • Although not documented, starting 4.1.2, isProviderEnabled won’t work as it did before.
  • No, Google changed anything. This is a bug for this particular phone.

Now my questions are;

  1. Is LocationManager.isProviderEnabled still valid for Android 4.1.2 and later?
  2. Does seeing Secure.LOCATION_PROVIDERS_ALLOWED have some drawbacks/pit holes (when I gave up using LocationManager.isProviderEnabled?

Thanks in advance.

EDIT1:

Here you can download test app from Google Play to try or ask someone to try.

EDIT6:

I removed test app since this question is answered.

EDIT2:

I released my app which checks network provider is usable by seeing Secure.LOCATION_PROVIDERS_ALLOWED and got exception on limited phones.
These are ACRA’s report.

Some phone running OS 4.1.1.

java.lang.IllegalArgumentException: requested provider network doesn't exisit
    at android.os.Parcel.readException(Parcel.java:1434)
    at android.os.Parcel.readException(Parcel.java:1384)
    at android.location.ILocationManager$Stub$Proxy.requestLocationUpdates(ILocationManager.java:675)
    at android.location.LocationManager._requestLocationUpdates(LocationManager.java:686)
    at android.location.LocationManager.requestLocationUpdates(LocationManager.java:508)

Some phone running OS 4.1.2.

java.lang.IllegalArgumentException: provider=network
    at android.os.Parcel.readException(Parcel.java:1439)
    at android.os.Parcel.readException(Parcel.java:1389)
    at android.location.ILocationManager$Stub$Proxy.requestLocationUpdates(ILocationManager.java:659)
    at android.location.LocationManager._requestLocationUpdates(LocationManager.java:690)
    at android.location.LocationManager.requestLocationUpdates(LocationManager.java:512)

I have never seen those exceptions until I changed a method to check network provider for location is usable or not. So I think LocationManager.isProviderEnabled is safe and seeing Secure.LOCATION_PROVIDERS_ALLOWED is risky. But this will put me back to original issue. Why LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) returns false (and there is not really) when Secure.LOCATION_PROVIDERS_ALLOWED tells there IS. Is Android OS poorly designed? Or I have just seeing issues tied only to specific (but there are at least 2 of them) phones?

EDIT3:

I updated test app to show GPS/Network location provider seems really usable or not by accessing with requestLocationUpdates().

And I disclose 2 phones name.

1) SBM200SH, OS4.1.2, Softbank mobile, Sharp Corporation
2) HTX21 (INFOBAR A02), OS4.1.1, KDDI, HTC

EDIT4:

I found 3rd phone.

3) SBM203SH, OS4.1.2, Softbank mobile, Sharp Corporation

EDIT5:

Sharp Corporation is running discussion space for mobile developers. I posted topic by presenting this SO’s question. I hope someone at Sharp Corporation takes action for this. I will keep this updated.

How to&Answers:

Developer support provided by Sharp corporation is excellent and they answered to my question in less than 48 hours.

This is what I got from them.

There are 2 conditions must be met that LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) returns true.

  1. Some internal state is ready for network location.
  2. Network location is enabled on setting screen.

Second one is obvious. But first one is not. They told how to simulate first one is negative. You can confirm the issue with steps shown below and running my test app (please see my question for link to download).

  • Open settings of you phone.
  • Tap Applications.
  • Tap All tab.
  • Find “Network Location”, tap it.
  • Tap “Disable”.
  • Reboot your phone.
  • Run test app.

For reason I can’t understand the user’s phone failed to do something related to first condition shown above and exhibits the issue.

Conclusion:

LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) is reliable. And be aware, Secure.LOCATION_PROVIDERS_ALLOWED is less reliable.

Answer:

The modern way to check the users Location settings is through LOCATION_MODE in Settings.Secure

For example if you simply want to know if the user has disabled them or not, you can do:

   public static boolean isLocationEnabled(Context context) {
       return getLocationMode(context) != Settings.Secure.LOCATION_MODE_OFF;
   }

   private static int getLocationMode(Context context) {
       return Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
   }

This will return true if Location is enabled. If you need finer granularity see the docs for details.

This method is better suited when using the Google Services Location APIs than the old NETWORK_PROVIDER and GPS_PROVIDER ways. Note: Requires KitKat / API19

Answer:

Not directly an answer to your question(s), but check out the new Location API that Google launched last week. It’s really easy to implement and it will check for the best possible location without wasting battery.
http://developer.android.com/google/play-services/location.html
and here’s a session at Google I/O about this new API and how to use it.
http://www.youtube.com/watch?v=Bte_GHuxUGc

This way you don’t need to worry about checking if the GPS is on or not and stuff like that

Answer:

Location Manager is not reliable on some phones. You may notice that if you launch google maps all of a sudden your app works. That is because Google Maps kicked the LocationManager. Which also means that there is programmatic way to kick that dude alive. So I used

HomeScreen.getLocationManager().requestLocationUpdates(
    LocationManager.NETWORK_PROVIDER, 0, 0, new LocationListener() {
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
        @Override
        public void onProviderEnabled(String provider) {
        }
        @Override
        public void onProviderDisabled(String provider) {
        }
        @Override
        public void onLocationChanged(final Location location) {
        }
    });

After the above code, I called what ever I needed from LocationManager and it kinda worked. If not try out the new API’s LocationClient. This is suppose to be much better, battery, accuracy and reliability.