当任何位置提供程序启用/禁用并确定发生了什么操作时是否可以获得通知?

我希望在用户启用或禁用networking或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> 

如果广播内有额外的内容,说明哪个提供者发生了变化,是否启用或禁用,那么这将是完美的。 不幸的是,这种情况并非如此。 有谁知道任何机制,我可以确定什么状态已经改变,而不需要维护我自己的状态variables。

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

Solutions Collecting From Web of "当任何位置提供程序启用/禁用并确定发生了什么操作时是否可以获得通知?"

我希望这不会违背你的要求

我知道,我可以保持每个提供者的状态,然后当我收到通知他们已经改变,然后我可以计算出什么改变了,我正在寻找一个更“标准”的方法来做到这一点。

…但我会认为最好的,“标准的”,最灵活的方法是让你的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权限添加到您的清单。 此外,其他提供者(超出“networking”和“全球定位系统”)可能适用取决于上下文,如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的意图,您可以尝试接收(和处理)。 但是,由于这个意图隐藏在官方文档中,所以在这个答案中提到使用它可能是不安全的。

甚至另一种方法:
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; } 

(来自官方消息 )。
您也可以为其他位置提供商调整此方法。

这适用于我:

将收件人添加到清单文件:

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

虽然这个接收器由于显而易见的原因被多次调用,但这会告诉你状态。

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

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

这样你就可以获得所有的启用提供者。

感谢@usman的回答,我们可以应用解决scheme,而不用以下方式extends类:

AndroidManifest.xml中;

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

class(我从来没有testing过);

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