我已设置一个由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);
}
}
}
}
我在上面的代码中遇到了几个问题。
W/GpsLocationProvider(...): Unneeded remove listener for uid 1000
。警告来自here。我在代码中找不到这里删除的侦听器被触发,我也无法看到他们在哪里被分配了uid 1000 (apparently系统服务器)。当我启用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处理掉吗?
但最重要的问题是:当我注册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);
}
}
答案 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}}即可。我认为这是一个更好/更清洁/更清晰的解决方案。