[Unity] Problems with ChildAdded Listener

783 views
Skip to first unread message

Joe Roy

unread,
Feb 15, 2017, 5:13:28 PM2/15/17
to Firebase Google Group
[Using Unity 5.5.0f3 and Firebase 1.1.2. testing on Nexus 5 Android 5.0 emulator(Genymotion) and a real LG G3 Android 6.0]

In my Unity program, I have a function that, when a user logs in using the firebase Auth, he then starts listening to changes on a particular database reference. When data is added to the reference, the user is supposed to be shown that new data in the Unity program. The database reference is "dbref.Child("whateverYouWant").OrderByKey().LimitToLast(25)". The database in question has no restrictions meaning that anyone can read or write to it.

If the user is already signed in when the app starts(due to a saved auth token), the data of the reference is displayed without any problem and if the user adds data, he immediately see the changes.

The problem is that if the user is not signed in when the app starts but then signs in, the listeners do not work. No data of the reference is loaded and if the user adds data, he cannot see the new data he entered. The handler functions are simply not called at all. The data can be seen from the firebase console though meaning that the transaction did take place but the listeners did not react. No error are displayed in the logs. I added what is displayed right after adding the "add data handlers".

Can anyone replicate that problem? 


I/Unity   ( 6829): System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
I/Unity   ( 6829): System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
I/Unity   ( 6829): System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
I/Unity   ( 6829): System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
I/Unity   ( 6829): System.Threading.Tasks.<ContinueWith>c__AnonStorey0`1:<>m__1(Task)
I/Unity   ( 6829): System.Threading.Tasks.Task`1:RunContinuations()
I/Unity   ( 6829): System.Threading.Tasks.Task`1:TrySetResult(DataSnapshot)
I/Unity   ( 6829): System.Threading.Tasks.TaskCompletionSource`1:TrySetResult(DataSnapshot)
I/Unity   ( 6829): System.Threading.Tasks.TaskCompletionSource`1:SetResult(DataSnapshot)
I/Unity   ( 6829): Firebase.Database.<GetValueAs

Benjamin Wulfe

unread,
Feb 15, 2017, 5:57:17 PM2/15/17
to Firebase Google Group
So you are saying -- in the case where the user starts out not signed-in -- that it initially works unauthenticated (because you have public access), but then it stops working as soon as the user signs in.  But in the logs, you see indications that the continuation is being called, but it never comes back...

And you are using GetValueAsync() to make the call immediately after changing the data?  Remember that data changes on the server side will be asynchronous, so its probably better to use ValueChanged.
Maybe somehow the callbacks are being orphaned after the change in auth -- but since you are calling GetValueAsync() each time with a new callback, that seems unlikely.

And you are sure that control never reaches your handler?  Can you post a minimum repro case with some code?

Joe Roy

unread,
Feb 16, 2017, 11:14:54 AM2/16/17
to Firebase Google Group
Hey Benjamin,

So when the app starts, I add an auth listener (auth.StateChanged += AuthStateChanged) to see if the user is authenticated. If it is authenticated then a function is called that do the following: 

DatabaseReference dbref = databaseReference; //(set when the app starts from FirebaseDatabase.DefaultInstance.RootReference;)


dbref
.Child("someReference").OrderByKey().LimitToLast(loadLimit).GetValueAsync().ContinueWith(task =>
               
{


                   
if (task.IsCompleted)
                   
{
                       
DataSnapshot snapshot = task.Result;
                        dbref
.Child("someReference").OrderByKey().LimitToLast(loadLimit).ChildAdded += HandleChildAdded;
                   
}
               
});
       
}



HandleChildAdded looks something like this:

void HandleChildAdded(object sender, ChildChangedEventArgs args)
   
{
       
if (args.DatabaseError != null)
       
{
           
Debug.LogError(args.DatabaseError.Message);
           
return;
       
}
       
// Do something with the data in args.Snapshot
       
print("child added " + args.Snapshot.GetRawJsonValue());
       

   
}


When a user adds data, a function like this is called:

public void savePost(string json)
   
{
       
DatabaseReference dbref = databaseReference; //(set when the app starts from FirebaseDatabase.DefaultInstance.RootReference;)
        dbref
= dbref.Child("someReference").Push();
        dbref
.SetRawJsonValueAsync(json);
   
}


With all of this said, if the user is already authenticated when opening the app(because of an auth token), what happens is that "HandleChildAdded" is added to the specific database reference. And then, HandleChildAdded is called and it prints "args.Snapshot.GetRawJsonValue()" for each data point currently present in the reference. Furthermore, when the user calls "savePost", HandleChildAdded will print whatever new datapoint the user entered.

If the user opens the app but is not already authenticated in; he can go through a typical login process. This process ends with "auth.SignInWithEmailAndPasswordAsync(email, password)". When Firebase says that the user is authenticated. "AuthStateChanged()"  calls a function that will add "HandleChildAdded" to the specific database reference. Unfortunately, once this is done, HandleChildAdded will not print anything and calling savePost will not make it print anything new either.

I have not tried to add the handler when the user is not authenticated as this is not something I need in my app.

I've waited ~5-15 mins for the answer back when signing in but nothing ever happens while if the user is already authenticated an answer is provided almost instantly.

Does this clarify the situation? Let me know if you need more details. Thankfully I can work around it by reloading the scene after authenticating(so that it's as if the app was started while already being authenticated) but this is not super practical.


Benjamin Wulfe

unread,
Feb 18, 2017, 11:52:46 AM2/18/17
to Firebase Google Group
Hi Joe thanks for the extra information.
I do not know of a Firebase issue that would be affecting you here.

Could you please turn on logging by setting FirebaseDatabase.DefaultInstance.LogLevel = LogLevel.Verbose;

Also, just in case it's not logged, could you log out "dbref.Child("somereference").ToString()" *every* place that HandleChildAdded is hooked.
One possibility here is that the path is somehow different or incorrect in the auth case.

Also, try simplifying this code:

                        dbref.Child("someReference").OrderByKey().LimitToLast(loadLimit).ChildAdded += HandleChildAdded;

and remove the OrderBy/LimitToLast so its simply dbref.Child("somereference").ChildAdded += HandleChildAdded.  For some reason there could be an issue with orderby/limit affecting ChildAdded.

Finally, if none of these work, please contact our support line here:  https://firebase.google.com/support/contact/troubleshooting/
And they will provide more direct 1-1 help and open a support issue for us to investigate further.

Regards
-Ben
Reply all
Reply to author
Forward
0 new messages