10

我希望在用户启用或禁用网络或 GPS 位置时收到通知,重要的是我希望知道他们更改了哪个以及如何更改。我有一个用于android.location.PROVIDERS_CHANGED广播意图的广播接收器,它正在接收正确的广播。

我现在需要尝试确定发生了哪些操作,即启用或禁用以及更改了哪个提供程序。我知道我可以保留每个提供者的状态,然后当我收到他们已更改的通知时,我可以弄清楚发生了什么变化,我正在寻找一种更“标准”的方法来执行此操作。广播意图似乎没有任何额外内容来指示哪个提供者已更改。

这是我目前拥有的代码。

    public class LocationProviderChangedReceiver extends BroadcastReceiver {
    private final static String TAG = "LocationProviderChangedReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
      if (intent.getAction().matches("android.location.PROVIDERS_CHANGED"))
      {
        Log.i(TAG,"Location Providers changed");
        Bundle bundle = intent.getExtras();
        if (bundle == null) {
          Log.d(TAG, "No extras data");
         } else {
           Log.d(TAG, "Bundle received of size " + bundle.size);
         } 
      }
    }
  }

这是我的清单中的一小部分摘录

  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

  <receiver 
    android:name=".LocationProviderChangedReceiver"
    android:exported="false">
    <intent-filter>
      <action android:name="android.location.PROVIDERS_CHANGED" />
      <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
  </receiver>

如果广播中有一个额外的说明哪个提供者已更改以及它是启用还是禁用,这将是完美的。不幸的是,这种情况并非如此。有谁知道我可以在不维护自己的状态变量的情况下确定哪些状态发生了变化的任何机制。

在一个理想的世界里,我会不断地监控变化,但只是偶尔监听位置变化。我想避免不断监控位置变化。

4

4 回答 4

5

这对我有用:

将接收者添加到清单文件中:

<receiver
        android:name="com.eegeo.location.LocationProviderChangedReceiver">
        <intent-filter>
            <action android:name="android.location.PROVIDERS_CHANGED" />
        </intent-filter>
    </receiver>

检查接收器中的两个位置提供程序:

public class LocationProviderChangedReceiver  extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {

        boolean anyLocationProv = false;
        LocationManager locationManager = (LocationManager) MyMainActivity.context.getSystemService(Context.LOCATION_SERVICE);

        anyLocationProv |= locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        anyLocationProv |=  locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        Log.i("", "Location service status" + anyLocationProv);


    }

}

尽管由于显而易见的原因多次调用此接收器,但这会告诉您状态。

于 2015-03-11T07:07:59.350 回答
4

我希望这不会与您的要求相矛盾

我知道我可以保留每个提供者的状态,然后当我收到他们已更改的通知时,我可以弄清楚发生了什么变化,我正在寻找一种更“标准”的方法来执行此操作。

...但我认为最好的“标准”和最灵活的方法是让您LocationProviderChangedReceiver实现LocationListener接口,然后实现onProviderEnabled()onProviderDisabled()就像这样:

public void onProviderEnabled(String provider) {
  if(provider.equals(LocationManager.GPS_PROVIDER)){
    ...
  } else if (provider.equals(LocationManager.NETWORK_PROVIDER)){
    ...
  }
}

请注意,ACCESS_FINE_LOCATION如果您还没有将权限添加到您的清单中,您应该这样做。此外,其他提供商(“网络”和“GPS”之外)可能会根据上下文应用,例如PASSIVE_PROVIDER甚至FUSED_PROVIDER.

更新的答案:
如果您无法选择不断侦听位置变化,则LocationManager还知道当前启用了哪个提供程序

LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

...这样您就可以将这些检查与您一起使用,BroadcastReceiver以避免手动持有任何启用/禁用的标志。android.location.GPS_ENABLED_CHANGE除此之外,您还可以尝试接收(和处理)一个意图。但是由于此意图隐藏在官方文档中,因此使用它可能不安全,如this answer中所述。

甚至另一种方法:
Android 的默认设置切换小部件(你知道我的意思)通过订阅android.location.PROVIDERS_CHANGED意图(就像你做的那样)来显示 GPS 启用/禁用状态,以通过用户设置触发 GPS 状态请求:

@Override
public int getActualState(Context context) {
  ContentResolver resolver = context.getContentResolver();
  boolean on = Settings.Secure.isLocationProviderEnabled(
                 resolver, LocationManager.GPS_PROVIDER);
  return on ? STATE_ENABLED : STATE_DISABLED;
}

(来自官方来源)。
您也可以将此方法应用于其他位置提供程序。

于 2013-04-09T11:32:17.117 回答
1

感谢@usman 的回答,我们可以extends通过以下方式应用没有类的解决方案;

AndroidManifest.xml;

<receiver android:name="com.eegeo.location.LocationProviderChangedReceiver">
    <intent-filter>
        <action android:name="android.location.PROVIDERS_CHANGED" />
    </intent-filter>
</receiver>

类(我从未测试过);

public class LocationProviderChangedReceiver {

    private mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String ability = (isGPSProviderEnabled() && isNetworkProviderEnabled()) ? "CAN" : "CANNOT";
            Log.d("", "The location " + ability + " be caught in high accuracy!");
        }
    };


    public startProviderChangeObserving () {
        registerReceiver(mReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));

    }


    public stopProviderChangeObserving () {
        unregisterReceiver(mReceiver);
    }   


    /**
    * Method to verify that the location providers wheter on or not on the device
    **/
    public boolean isGPSProviderEnabled() {
        return (Boolean) mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    public boolean isNetworkProviderEnabled() {
        return (Boolean) mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

}
于 2016-09-08T07:40:42.980 回答
0

在接收器上,您可以简单地检查启用了哪些提供程序:

LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE)
List<String> providers = lm.getProviders(true);

通过这种方式,您可以获得所有启用提供程序。

于 2014-09-30T11:13:03.503 回答