Firebase onComplete从未在后台进程中调用

时间:2016-10-06 14:08:22

标签: android firebase broadcastreceiver firebase-realtime-database

我的目标

构建一个允许用户在&关闭。启用跟踪后,我想将用户的位置数据推送到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连接太慢了?

1 个答案:

答案 0 :(得分:1)

问题可能与BroadcastReceiver的生命周期有关。

文档解释说:

  

BroadcastReceiver对象仅在通话期间有效   to onReceive(Context,Intent)。一旦你的代码从此返回   功能,系统认为要完成的对象不再   活性

     

这对你能做些什么有重要的影响   onReceive(Context,Intent)实现:需要的任何东西   异步操作不可用,因为您需要   从函数返回来处理异步操作,但是在   那一点,BroadcastReceiver不再有效,因此   系统可以在异步操作之前自由地终止其进程   完成

由于FirebaseDatabase操作是在后台线程上异步执行的,因此在某些情况下,系统会在执行数据库操作之前销毁LocationProcessingReceiver实例。

您可能认为使用WakefulBroadcastReceiver会阻止接收器对象过早被破坏,但事实并非如此。 WakefulBroadcastReceiver旨在用于安全地启动您未在此处执行的服务。这没有任何好处。请改用BroadcastReceiver

为确保允许完成数据库操作,请在pushLocationToServer()中获取Wakelock(可能需要超时以确保安全),然后在onComplete()回调中释放它。