我的目标
构建一个允许用户在&关闭。启用跟踪后,我想将用户的位置数据推送到Firebase。
我尝试过的解决方案
我使用PendingIntent和Google Play服务FusedLocationAPI来跟踪后台的位置。在每个位置更新(标点为30秒)时,PendingIntent会将一个意图(具有位置更新,如果可用)触发到WakefulBroadcastReceiver。然后,WakefulBroadcastReceiver应将位置数据保存到Firebase。
以下是WakefulBroadcastReceiver的样子:
public class LocationProcessingReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "LocationProcessingRcv";
@Override
public void onReceive(Context context, Intent intent) {
if (LocationResult.hasResult(intent)) {
Log.i(this.TAG, "Received location result");
// Extract location from result and push to server
Location location = LocationResult.extractResult(intent).getLastLocation();
this.pushLocationToServer(location, intent.getStringExtra("userId"));
}
else {
Log.i(TAG, "No location result");
}
}
/**
* Pushes location to Firebase server
* @param location
*/
private void pushLocationToServer(Location location, String userId) {
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
// Data to update the latest status of the user
Map<String, Object> statusMap = new HashMap<String, Object>();
// ... various statusMap.put(...) calls go here
// Get reference to Firebase as well as key at which to update reference
DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference();
dbRef.child(DB_LOC_HISTORY_REFERENCE).push().updateChildren(historyMap, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
Log.i(TAG, "Successfully pushed to server");
}
else {
Log.i(TAG, "Server push failed: " + databaseError.toString());
}
}
});
}
}
问题
在某些手机上,永远不会调用onComplete回调(在某些设备上!)。我不知道为什么这不起作用......在某些设备上,回调按预期工作。在其他情况下,回调从未收到,我从未在Firebase中看到数据更新。
日志显示位置更新正常工作,并且按预期定期调用WakefulBroadcastReceiver的onReceive()方法。
我原本希望调用onComplete,但是如果存在连接问题则显示错误。但这种情况从未发生过,我很难理解为什么。
警告:许多这些设备都在3G上运行。是否有可能当我的应用程序处于后台时,在Firebase完成此操作之前,BroadcastReceiver会被杀死,可能是因为3G连接太慢了?
答案 0 :(得分:1)
问题可能与BroadcastReceiver的生命周期有关。
文档解释说:
BroadcastReceiver对象仅在通话期间有效 to onReceive(Context,Intent)。一旦你的代码从此返回 功能,系统认为要完成的对象不再 活性
这对你能做些什么有重要的影响 onReceive(Context,Intent)实现:需要的任何东西 异步操作不可用,因为您需要 从函数返回来处理异步操作,但是在 那一点,BroadcastReceiver不再有效,因此 系统可以在异步操作之前自由地终止其进程 完成强>
由于FirebaseDatabase操作是在后台线程上异步执行的,因此在某些情况下,系统会在执行数据库操作之前销毁LocationProcessingReceiver
实例。
您可能认为使用WakefulBroadcastReceiver会阻止接收器对象过早被破坏,但事实并非如此。 WakefulBroadcastReceiver
旨在用于安全地启动您未在此处执行的服务。这没有任何好处。请改用BroadcastReceiver
。
为确保允许完成数据库操作,请在pushLocationToServer()
中获取Wakelock(可能需要超时以确保安全),然后在onComplete()
回调中释放它。