LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)不可靠,为什么?

9

我的应用程序的一个用户报告说,即使他已经打开了网络定位,应用程序仍然显示网络定位关闭。他给我发了一些截图,这让我开始思考;

LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)

他的手机(运行Android 4.1.2)出现了问题。一开始我认为这个是导致问题的原因,但事实并非如此。他还向我发送了该设置的截图。

后来我在谷歌上搜索,并找到了这个。这个问题似乎有助于我,但不幸的是答案对于这种情况没有帮助,提问者也没有继续追究。

我的应用程序与位置有关,并且一直使用LocationManager.isProviderEnabled来了解GPS和网络位置是否打开或关闭。直到最近,我从未被告知我的应用程序无法正确识别这些设置。他是第一个报告此问题的用户。我了解到还有另一种方法可以了解GPS和网络位置设置,即通过查看Secure.LOCATION_PROVIDERS_ALLOWED。为了看看这种方法在他的手机上如何工作,我编写了简单的应用程序,并要求他运行。该应用程序执行简单任务并在屏幕上显示文本。

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";
}

他又发送了截屏。看起来如下:
GPS=on
Network=off
GPS=on
Network=on

这个结果让我很不开心。可能有一些原因导致这样的结果。

  • 就像其他人之前问过的,这个问题在一些手机上一直存在。
  • 谷歌在4.1.2版本中出现了问题。isProviderEnabled在此版本中无法工作。
  • 虽然没有文档说明,但是从4.1.2版本开始,isProviderEnabled的工作方式已经发生变化。
  • 不,谷歌没有改变任何东西。这是这个特定手机上的一个错误。

现在我的问题是:

  1. LocationManager.isProviderEnabled对Android 4.1.2及更高版本仍然有效吗?
  2. 当我放弃使用LocationManager.isProviderEnabled时,查看Secure.LOCATION_PROVIDERS_ALLOWED是否有一些缺点/陷阱?

提前感谢。

编辑1:

您可以在Google Play上下载测试应用程序(链接)以尝试或请别人尝试。

编辑6:

我删除了测试应用程序,因为问题已得到解答。

编辑2:

我发布了一个应用程序,通过查看Secure.LOCATION_PROVIDERS_ALLOWED检查网络提供商是否可用,并在有限的手机上遇到了异常。以下是ACRA的报告。

一些运行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)

一些装有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)

我之前从未见过这些异常情况,直到我更改方法来检查网络提供商是否可用。所以我认为LocationManager.isProviderEnabled是安全的,而Secure.LOCATION_PROVIDERS_ALLOWED则是有风险的。但这会让我回到最初的问题。为什么LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)返回false(实际上没有),而Secure.LOCATION_PROVIDERS_ALLOWED告诉我们有。Android操作系统设计得不好吗?还是我只看到与特定手机(但至少有两个)相关的问题?
编辑3: 我更新了测试应用程序,通过使用requestLocationUpdates()访问GPS/网络位置提供程序的可用性,并披露了2台手机的名称。
1)SBM200SH,OS4.1.2,Softbank移动,夏普公司 2)HTX21(INFOBAR A02),OS4.1.1,KDDI,HTC
编辑4: 我找到了第三台手机。
3)SBM203SH,OS4.1.2,Softbank移动,夏普公司
编辑5: 夏普公司正在为移动开发人员运行讨论空间。我在那里发布了这个SO的问题,并希望夏普公司的某个人会采取行动。我会保持更新。

我刚在4.1.2(Galaxy S2)和4.2.2(Nexus 7)上测试过,两个设备都可以正常工作。只有这个用户出了问题吗?他用的是什么手机? - dumazy
1
只是一条注释,但考虑使用融合。 - shemsu
@dumazy,我看到至少有2部手机出现了这个问题。我暂时不想透露手机的品牌。 - Tomcat
@Tomcat,三星手机因网络提供商位置问题而闻名。请告知手机型号以便获得帮助。 - Siddharth
@Siddharth,请阅读我对您答案的评论。 - Tomcat
4个回答

6

夏普公司提供的开发者支持非常出色,他们在不到48小时内回答了我的问题。

这是我从他们那里得到的答复:

有两个条件必须满足,LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)才会返回true。

  1. 一些内部状态已准备好进行网络定位。
  2. 在设置屏幕上启用了网络位置。

第二个条件很明显。但第一个条件不是。他们告诉如何模拟第一个条件为负。您可以按照下面的步骤确认问题,并运行我的测试应用程序(请参阅我的问题以获取下载链接)。

  • 打开手机的设置。
  • 点击应用程序。
  • 点击全部选项卡。
  • 找到“网络位置”,点击它。
  • 点击“禁用”。
  • 重新启动您的手机。
  • 运行测试应用程序。

由于某种我无法理解的原因,用户的手机未能执行与上述第一个条件相关的操作,并出现了问题。

结论:

LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)是可靠的。请注意,Secure.LOCATION_PROVIDERS_ALLOWED不太可靠。


1
你的客户会执行这些步骤吗?你有在其他手机上测试过你的应用吗?比如三星2.3.6和4.0?我认为你需要一种编程方式来触发更新。好好考虑一下吧。 - Siddharth
一个用户使用了我的测试应用程序,并证明了这个问题的原因。我的回答可能听起来不正确,因为你无法阅读Sharp公司运营的用户支持论坛上的对话。他们清楚地指出了问题,并已解决。 - Tomcat

4

查看用户位置设置的现代方法是通过Settings.Secure中的LOCATION_MODE来实现。

例如,如果您只想知道用户是否已禁用它们,可以执行以下操作:

   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);
   }

如果位置已启用,此方法将返回true。如果您需要更细的粒度,请参阅文档了解详情

使用Google服务位置API时,此方法比旧的NETWORK_PROVIDER和GPS_PROVIDER方式更适合。注意:需要KitKat / API19。


1
这也已经被弃用了。要检查位置状态,请使用LocationManager#isLocationEnabled()。要获取位置提供程序的状态,请使用LocationManager#isProviderEnabled(String)。 - CoolMind

2

5
这个回答与我的问题不相关。 - Tomcat

0

在某些手机上,位置管理器不是很可靠。您可能会注意到,如果您突然启动谷歌地图,您的应用程序就可以正常工作了。这是因为谷歌地图启动了位置管理器。这也意味着有一种编程方式可以唤醒该服务。因此,我使用了

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) {
        }
    });

在上面的代码之后,我从LocationManager调用了所需的内容,它有点起作用。如果不行,请尝试使用新的API LocationClient。这应该更好,电池寿命、准确性和可靠性都会得到提高。

调用requestLocationUpdates会抛出异常。请再次查看问题。我猜我面临的问题与你所知道的不同。 - Tomcat
@Tomcat,你可能是对的,但我也要指出,在某些情况下,上面的解决方案非常有效。 - holgac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接