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

时间:2013-05-25 23:39:00

标签: android gps android-pendingintent location-provider

我已设置一个由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。警告来自here。我在代码中找不到这里删除的侦听器被触发我也无法看到他们在哪里被分配了uid 1000 apparently系统服务器)。
  2. 当我启用gps时,我获得了预期的位置,然后是“RemoteException”

      

    LocationManagerService(...):RemoteException在Receiver上调用onLocationChanged {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处理掉吗?

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

    请记住我正在使用此模式,因为我希望手机更新其位置即使在睡着时并且实现了它(我确实获得了位置更新)。我尝试使用requestSingleUpdate来模拟FLAG_ONE_SHOT(在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);
        }
    }
    

1 个答案:

答案 0 :(得分:4)

对这个问题:

  

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

当您注册位置更新并传递PendingIntent时,PendingIntent会在LocationManager决定通知您位置更新时触发此PendingIntent。您可以提供您想要的任何内容,具体取决于触发LocationManager时您想要发生的事情。 Intent会为发送的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注册了位置更新,我认为再次注册不会导致{{1}}多次使用。如果您想尝试,只需从现有代码中删除{{1}}即可。我认为这是一个更好/更清洁/更清晰的解决方案。