3

我已经设置了一个由 BroadcastReceiver 接收的警报,它启动了一个 WakefulIntentService (类LocationMonitor)。在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. 警告来自这里。我在代码中找不到触发侦听器的删除也看不到它们在哪里被分配了 uid 1000显然是系统服务器)。
  2. 当我启用 gps 时,我得到了预期的位置,然后是“RemoteException”

    LocationManagerService(...): RemoteException 在接收器上调用 onLocationChanged{4083ee68 Intent PendingIntent{4084e6b8: PendingIntentRecord{4083ef78 gr.uoa.di.monitoring.android broadcastIntent}}}mUpdateRecords: {gps=UpdateRecord{40838180 mProvider: gps mUid: 10064} }

    这不是一个真正的 RemoteException,只是一个 PendingIntent.CancelledException - 该消息非常具有误导性。或者我认为:它来自这里调用这个我的问题是:为什么要重用 Intent - FLAG_ONE_SHOT 不应该处理它吗?

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

请记住,我正在使用这种模式,因为我想让手机即使在睡着的时候也能更新它的位置,这实现了它(我确实得到了位置更新)。我尝试requestSingleUpdate使用FLAG_ONE_SHOT.

接收者 :

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

1 回答 1

4

对于这个问题:

当我像这样注册 PendingIntent 时,我希望收到什么意图?我应该使用什么标志?

当您注册位置更新并通过 a时PendingIntent,这PendingIntent将在LocationManager决定通知您位置更新时触发。你可以提供几乎任何你想要的东西,这取决于你想要在PendingIntent触发时发生什么。将为发送的LocationManager内容添加额外Intent内容。这个额外的有捆绑键LocationManager.KEY_LOCATION_CHANGED,与该键关联的对象是一个Location对象。

LocationManagerPendingIntent一次又一次地使用它来通知您的应用程序位置更新,所以我认为使用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从现有代码中删除。我认为这是一个更好/更清洁/更清晰的解决方案。

于 2013-06-05T15:43:02.110 回答