android - requestLocationUpdates with PendingIntent 和 Broadcast - 我得到什么广播

标签 android gps android-pendingintent location-provider

我设置了一个警报,该警报由启动 WakefulIntentService(类 LocationMonitor)的 BroadcastReceiver 接收。在 LocationMonitor 我有:

private static final int MIN_TIME_BETWEEN_SCANS = 1 * 30 * 1000;
private static final int MIN_DISTANCE = 0;

@Override
protected void doWakefulWork(Intent intent) {
    final CharSequence action = intent.getAction();
    if (action == null) { // monitor command from the alarm manager
        // the call below enables the LocationReceiver
        BaseReceiver.enable(this, ENABLE, LocationReceiver.class);
        if (lm == null) lm = (LocationManager) this
                    .getSystemService(Context.LOCATION_SERVICE);
        Intent i = new Intent(this, LocationReceiver.class);
        PendingIntent pi = PendingIntent.getBroadcast(this, NOT_USED, i,
            PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                MIN_TIME_BETWEEN_SCANS, MIN_DISTANCE, pi);
    } else if (ac_location_data.equals(action)) {
        final Bundle extras = intent.getExtras();
        if (extras != null) {
            final Location loc = (Location) extras
                    .get(LocationManager.KEY_LOCATION_CHANGED);
            if (loc == null) {
                w("NULL LOCATION  - EXTRAS : " + extras); //Log.w
                // while gps is disabled I keep getting this :
                // NULL LOCATION - EXTRAS : Bundle[{providerEnabled=false}]
            } else {
                final double lon = loc.getLongitude();
                final double lat = loc.getLatitude();
                w("latitude :" + lat + " -- longitude : " + lon);
            }
        }
    }
}

上面的代码我有几个问题。

  1. 如果 GPS 最初被禁用,然后我启用它,我会得到一堆 W/GpsLocationProvider(...): Unneeded remove listener for uid 1000。警告来自 here .我在代码中找不到 删除监听器的位置我也看不到为它们分配 uid 1000 的位置(apparently 系统服务器)。
  2. 当我启用 gps 时,我得到了预期的位置,然后是“RemoteException”

    LocationManagerService(...): RemoteException calling onLocationChanged on Receiver{4083ee68 Intent PendingIntent{4084e6b8: PendingIntentRecord{4083ef78 gr.uoa.di.monitoring.android broadcastIntent}}}mUpdateRecords: {gps=UpdateRecord{40838180 mProvider: gps mUid: 10064}}

    这实际上不是 RemoteException,只是 PendingIntent.CancelledException - 该消息具有误导性。或者我认为:它来自 here这叫this . 我的问题是:为什么要重用 Intent - FLAG_ONE_SHOT 不应该处理它吗?

但最重要的问题是:当我像这样注册一个 PendingIntent 时,我希望收到什么 Intent 我应该使用什么标志

请记住,我正在使用此模式,因为我想让手机更新其位置即使在睡着的时候,这实现了它(我确实获得了位置更新)。我尝试使用 FLAG_ONE_SHOT 模拟 requestSingleUpdate(在 2.3 中不可用)。

接收者:

public final class LocationReceiver extends BaseReceiver {

    private static final Class<? extends Monitor> MONITOR_CLASS =
        LocationMonitor.class;

    @Override
    public void onReceive(Context context, Intent intent) {
        d(intent.toString());
        final String action = intent.getAction();
        d(action + "");
        final Intent i = new Intent(context, MONITOR_CLASS);
        i.fillIn(intent, 0); // TODO do I need flags ?
        i.setAction(ac_location_data.toString());
        WakefulIntentService.sendWakefulWork(context, i);
    }
}

最佳答案

对于这个问题:

when I register a PendingIntent like this what intents do I expect to receive ? And what flags should I use ?

当您注册位置更新并传递一个PendingIntent时,这个PendingIntent将在LocationManager决定通知您一个位置时被触发更新。您几乎可以提供任何您想要的内容,具体取决于您希望在 PendingIntent 被触发时发生什么。 LocationManager 将向发送的 Intent 添加额外内容。这个 extra 具有 bundle 键 LocationManager.KEY_LOCATION_CHANGED 并且与该键关联的对象是一个 Location 对象。

LocationManager 将一次又一次地使用此 PendingIntent 来通知您的应用程序位置更新,所以我认为使用 PendingIntent.FLAG_ONE_SHOT 可能不是真是个好主意。如果您只想要一次更新,为什么不在获得一次更新后取消注册?

编辑:添加代码以在注册更新之前取消任何先前请求的更新

在调用 registerLocationUpdates() 之前,执行此操作以取消任何先前注册的更新:

    Intent i = new Intent(this, LocationReceiver.class);
    // Get any existing matching PendingIntent
    PendingIntent pi = PendingIntent.getBroadcast(this, NOT_USED, i,
        PendingIntent.FLAG_NO_CREATE);
    if (pi != null) {
        // Cancel any updates for this PendingIntent, because we are about to
        //  invalidate it
        lm.removeUpdates(pi);
    }
    // Create a new PendingIntent and cancel any previous one
    pi = PendingIntent.getBroadcast(this, NOT_USED, i,
                  PendingIntent.FLAG_CANCEL_CURRENT);
    // Now register for location updates...
    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
            MIN_TIME_BETWEEN_SCANS, MIN_DISTANCE, pi);

注意:实际上,我不知道为什么在这种情况下您需要取消任何以前的 PendingIntent 并创建一个新的。你可以得到一个PendingIntent,如果你已经注册了那个PendingIntent的位置更新,我不认为再次注册会导致PendingIntent 多次使​​用。如果您想尝试这样做,您需要做的就是删除 PendingIntent.FLAG_ONE_SHOT |来自现有代码的 PendingIntent.FLAG_CANCEL_CURRENT。我认为这是更好/更清洁/更清晰的解决方案。

关于android - requestLocationUpdates with PendingIntent 和 Broadcast - 我得到什么广播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16754896/

相关文章:

java - android中不显示特殊字符

android - 仍然需要 Facebook Activity 吗?

ios - CoreLocation 闲置后停止获取更新

linux - 使用 BeagleBone Black 读取两个串口时出现 Segmentation Fault 错误

android - 在android中按下通知时如何打开 fragment 页面

android - 广播接收器不会在 android Lollipop 设备上触发

android - 页面更改后标签布局滑动并在动态标签布局中滑动

android - 在外部存储器上保存数据

python - 如何在python中从gps历元获取当前日期的闰秒

android - LocationClient requestLocationUpdates 与 PendingIntent