Android LocationManager.isProviderEnabled(LocationManager.NETWORK\u提供程序)不可靠,为什么?

Android LocationManager.isProviderEnabled(LocationManager.NETWORK\u提供程序)不可靠,为什么?,android,locationmanager,Android,Locationmanager,我的应用程序的一位用户报告说,即使他确实打开了该应用程序,该应用程序也会告诉网络位置已关闭。他给我发了几张屏幕截图,让我思考 LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) 它不能正常工作。他的手机运行的是安卓4.1.2,首先我认为是这个问题的原因。但事实并非如此。他也给我发了一张那个场景的屏幕截图 然后我在谷歌上搜索发现。这个问题似乎对我有所帮助,但不幸的是,这个答案对这个案例并没有帮助,提问者并没有进一

我的应用程序的一位用户报告说,即使他确实打开了该应用程序,该应用程序也会告诉网络位置已关闭。他给我发了几张屏幕截图,让我思考

LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
它不能正常工作。他的手机运行的是安卓4.1.2,首先我认为是这个问题的原因。但事实并非如此。他也给我发了一张那个场景的屏幕截图

然后我在谷歌上搜索发现。这个问题似乎对我有所帮助,但不幸的是,这个答案对这个案例并没有帮助,提问者并没有进一步追问

我的应用程序与位置相关,并且一直在使用LocationManager.isProvidered以了解位置的GPS和网络处于打开或关闭状态。直到最近,我才被告知我的应用程序无法正确了解这些设置。他是第一个报告此问题的用户。我了解到还有另一种方法可以通过查看Secure.location\u PROVIDERS\u来了解GPS和网络的位置设置。为了了解这个方法在他的手机上是如何工作的,我编写了一个简单的应用程序,让他运行。此应用程序执行简单任务,并在屏幕上显示文本

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将无法像以前那样工作
  • 不,谷歌改变了一切。这是这部手机的一个bug
现在我的问题是,

  • LocationManager.isProviderEnabled对Android 4.1.2及更高版本仍然有效吗
  • 允许查看Secure.LOCATION\u PROVIDERS\u是否存在一些缺点/漏洞(当我放弃使用LocationManager.isProviderEnabled时)
  • 提前谢谢

    EDIT1:

    您可以从Google Play下载测试应用程序来尝试或请他人尝试

    EDIT6:

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

    EDIT2:

    我发布了我的应用程序,通过查看Secure.LOCATION\u PROVIDERS\u允许并在有限的手机上获得异常,检查网络提供商是否可用。 这些是ACRA的报告

    一些运行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)
    
    一些运行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)
    
    我从未见过这些异常,直到我更改了一种方法来检查网络提供商的位置是否可用。因此我认为LocationManager.isProviderEnabled是安全的,而查看Secure.location\u PROVIDERS\u ALLOWED是有风险的。但这将使我回到原来的问题。为什么LocationManager.isProviderEnabled(LocationManager.network\u provider)当Secure.LOCATION\u PROVIDERS\u ALLOWED告诉存在时,返回false(实际上没有)。Android操作系统设计是否糟糕?或者我刚刚看到的问题仅与特定(但至少有两个)手机有关

    EDIT3:

    通过使用requestLocationUpdates()访问,我更新了测试应用程序,以显示GPS/网络位置提供程序是否真的可用

    我透露了两部手机的名字

    1) SBM200SH,OS4.1.2,软银移动,夏普公司
    2) HTX21(信息栏A02),OS4.1.1,KDDI,HTC

    EDIT4:

    我找到了第三部电话

    3) SBM203SH,OS4.1.2,软银移动,夏普公司

    EDIT5:


    夏普公司正在为移动开发者提供讨论空间。我通过提出这个SO的问题发布了这个主题。我希望夏普公司有人对此采取行动。我将不断更新此信息。

    不是直接回答您的问题,而是查看谷歌上周推出的新位置API。它很容易实现,并且可以在不浪费电池的情况下检查最佳位置。 下面是谷歌I/O的一个会议,讨论这个新API以及如何使用它。


    这样,您就不必担心检查GPS是否开启以及类似的东西在某些手机上是不可靠的。你可能会注意到,如果你突然启动谷歌地图,你的应用程序就会正常工作。这是因为谷歌地图踢了LocationManager。这也意味着有一种程序化的方法可以活活踢死那个家伙。所以我用

    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
    。这被认为是更好的,电池,准确性和可靠性。

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

    这是我从他们那里得到的

    LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)返回true必须满足两个条件

  • 某些内部状态已准备好进行网络定位
  • 网络位置在设置屏幕上启用
  • 第二个是显而易见的。但第一个不是。他们告诉如何模拟第一个是否定的。您可以通过以下步骤确认问题,并运行我的测试应用程序(请参阅我的问题以获取下载链接)

    • 打开手机的设置
    • 点击应用程序
    • 点击所有选项卡
    • 找到“网络位置”,点击它
    • 点击“禁用”
    • 重新启动你的手机
    • 运行测试应用程序
    由于我无法理解的原因,用户的手机无法执行与上述第一种情况相关的操作,并显示出问题

    结论:


    LocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)是可靠的。请注意,允许的Secure.LOCATION\u提供者不太可靠。

    检查用户位置设置的现代方法是通过
    设置中的
    位置模式

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

       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。如果您需要更精细的粒度