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

Ste*_*eet 10 android android-location

我希望在用户启用或禁用网络或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);
         } 
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

这是我Manifest的一个小摘录

  <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>
Run Code Online (Sandbox Code Playgroud)

如果广播中有额外的内容声明哪个提供商已更改以及是否已启用或禁用,那么这将是完美的.不幸的是,这种情况并非如此.是否有人知道我可以通过哪种机制来确定哪些状态已经改变而不维护我自己的状态变量.

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

M. *_*han 5

这对我有用:

将接收器添加到清单文件:

<receiver
        android:name="com.eegeo.location.LocationProviderChangedReceiver">
        <intent-filter>
            <action android:name="android.location.PROVIDERS_CHANGED" />
        </intent-filter>
    </receiver>
Run Code Online (Sandbox Code Playgroud)

检查接收器中的两个位置提供者

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


    }

}
Run Code Online (Sandbox Code Playgroud)

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


sas*_*oar 4

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

我知道我可以保留每个提供者的状态,然后当我收到它们已更改的通知时,我可以找出更改的内容,我正在寻找一种更“标准”的方法来执行此操作。

...但我认为最好的、“标准的”、最灵活的方法是让你LocationProviderChangedReceiver实现LocationListener接口,然后实现onProviderEnabled(),onProviderDisabled()如下所示:

public void onProviderEnabled(String provider) {
  if(provider.equals(LocationManager.GPS_PROVIDER)){
    ...
  } else if (provider.equals(LocationManager.NETWORK_PROVIDER)){
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,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);
Run Code Online (Sandbox Code Playgroud)

...这样您就可以将这些检查与您的一起使用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;
}
Run Code Online (Sandbox Code Playgroud)

(来自官方消息来源)。
您也可以针对其他位置提供商采用此方法。