Firebase + Android - Notifications ChildAdded - How to get only New Childs?

只愿长相守 提交于 2019-12-03 08:40:02

问题


I'm trying to setup an Android Service in my app that listens for new Childs in a Firebase Ref, and throws a Notification when that happens.

I'm having issues because addChildEventListener onChildAdded apparently is called one time for every existent record and only then actually listens for new childs..

In this answer @kato states that if addChildEventListener is called like ref.endAt().limit(1).addChildEventListener(...) it would get only the newly added records.

It actually only gets one record at a time (I suppose with limit(1)) but it still gets an existant record before listening for added records.

Here's some code:

Initializing the Listener in onCreate():

@Override
public void onCreate() {
    super.onCreate();
    this.handler = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            AllowedGroup ag = dataSnapshot.getValue(AllowedGroup.class);

            postNotif("Group Added!", ag.getName());
        }
        ...rest of needed overrides, not used...

I'm using the AllowedGroup.class to store the records, and postNotif to build and post the notification. This part is working as intended.

Then, onStartCommand():

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    this.f = new Firebase(FIREBASE_URL).child("users").child(this.currentUserUid).child("allowedGroups");
    f.endAt().limit(1).addChildEventListener(handler);
    return START_STICKY;
}

It still returns one existant record before actually listening for newly added childs.

I've also tried querying by timestamp, like so:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    this.f = new Firebase(FIREBASE_URL).child("users").child(this.currentUserUid).child("allowedGroups");
    f.startAt(System.currentTimeMillis()).addChildEventListener(handler);
    return START_STICKY;
}

Hoping that it would only get records set after the service was started. It doesn't get existant records, but doesn't even get newly added childs.

EDIT:

I've also thought of something like getting into memory first all of the existant records, and conditionally post a notification if the record brought by onChildAdded does not exist on the previously gathered list, but that seems a bit like overkill, and thought that could be an easier (more API-friendly) way of doing this, am I right ?

Can anyone provide me with some insight on this ? I can't really find anything on the official docs or in any StackOverflow question or tutorial.

Thanks.


回答1:


If you have a field modifiedOn, you can index that and setup a query like:

Query byModified = firebaseEndpoint.orderByChild("modifiedOn").startAt(lastInAppTime);



回答2:


For me the logic was is to have value -"status" for example- which needs to be validated before deciding whether it is really new or was an old record then I set the "status" to a different value so I don't get it next time:

@Override
        public void onChildAdded(DataSnapshot dataSnapshot, String previousChildKey) {

                if(dataSnapshot.hasChildren()) {

                    String Id = (String) dataSnapshot.child("user_id").getValue();
                    String status = (String) dataSnapshot.child("status").getValue();

                    if (Id != null && Id.equals(storedId) && status != null && status.equals("created")) {
                        Log.d("INCOMING_REQUEST", "This is for you!");
                        sessionsRef.child(dataSnapshot.getKey()).child("status").setValue("received");
                    }

                }


        }



回答3:


I overcome this problem by keeping items of firebase database reference node in a List; and whenever onChildAdded(...) method is triggered, check if the incoming datasnapshot is in your list or not; if not, then it's new data

In order to achieve this you must meet below conditions:

  1. Have a unique value that must not repeated from item to item. (this can be easily achieved when you add items into Firebase using .push() method.
  2. Override .equals() method of your model class in order to fulfill the comparison based on this unique value.

Here code snippets based on your inputs

Model class

public class AllowedGroup {

    private String id;
    public static List<AllowedGroup> sGroups;

    // reset of fields ...


    public AllowedGroup() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }


    @Override
    public boolean equals(@Nullable Object o) {

        // If the object is compared with itself then return true
        if (o == this) {
            return true;
        }

        // Check if o is an instance of AllowedGroup or not
        if (!(o instanceof AllowedGroup)) {
            return false;
        }

        // typecast o to AllowedGroup so that we can compare data members
        AllowedGroup group = (AllowedGroup) o;

        // Compare data based on the unique id
        return (group.id).equals(id);
    }

}

Listening to firebase added nodes

@Override
public void onCreate() {
    super.onCreate();
    this.handler = new ChildEventListener() {
        @Override
        public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            AllowedGroup group = dataSnapshot.getValue(AllowedGroup.class);

            if (!AllowedGroup.sGroups.contains(group)) {
                // Here you'll receive only the new added values
            }

        }

        // ...rest of needed overrides, not used... 
    }

}


来源:https://stackoverflow.com/questions/24713765/firebase-android-notifications-childadded-how-to-get-only-new-childs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!