I am developing an app using Android & Firebase Realtime Database where users join a room, then when the host presses start game, all clients start the main game Activity (through a ValueEventListener on a "Started" child node in the room). The main game has a 60sec countdown where users make a sentence then at the end of the 60secs all sentences are collected and displayed.
I am having a hard time collecting all of the sentences at the end due to the 60sec timers being so off on different clients. I need a way to ensure all games end at the same time so the collection process is smooth and nothing gets missed.
I know that Firebase has both: /.info/serverTimeOffset and ServerValue.TIMESTAMP but i'm struggling on how to use them to sync timers.
I have tried to use System.currentTimeMillis() + serverTimeOffset to estimate the server time and get all clients to count down to endTime - (System.currenTimeMillis() + serverTimeOffset) where endTime is a time written to the database by the host that all clients read but timers are still way off.
What is the best way to handle this situation?
I would suggest:
Instead of running a timer that updates every second on the server, simply store the start/stop times of the event and allow the clients to manage their own timers.
Not be done by -1 every second (as setInterval and other client-side tools are not very exact) but by comparing the current timestamp to the end, and determining the difference.
Related
I Will describe my use case with figures attached and everything i can do to be clear so we may get up with a better idea ...
General idea:
Whatsapp chat application with firebase
Use case:
As we know one of the features of whatsapp is the last seen, when the user did (exited the app, log out, lost wifi connection, etc ..)
I tried to use:
onDisconnect, but onDisconnect gives bad result when losing wifi connection (because of the socket latency to be timed out)
the one I am using now, is every user updates its timestamp every 3 seconds (update document every 3 seconds), when the user loses connection,
he won't be able to update his timestamp, right? So, if another user wants to chat with this offline user, I can show him the user's last seen. Hope this
this is clear...
Developed using Flutter framework
Redux to manage app state
Firebase, cloud firestore
The code below is dispatching an action every three seconds, this dispatched action will update the last seen in firebase...
timer = Timer.periodic(Duration(seconds: 3), (Timer t) {
// store.dispatch(updateUserOnline());
});
As you can see in the figure below my data structure of how I am updating last seen for this user every 3 seconds ...
This implementation is very expensive to get satisfactory results for a last seen for a user, if we have million users and these million users are updating their
last seen every 3 seconds it will cost a lot $ per month, as we are doing a write operation, no?
So, my other solution is to implement a socket connection to my own server and let all the users listen to the onDisconnect socket event on my server instead of Firebase server, is this doable to avoid the huge cost of writing operations?
image attached: here
Firebase writes would indeed be a bit costlier since you would be sending in a lot of writes, which, apparently are just for the job of "last seen".
Instead, as you mentioned, having a socket connection with your own server will help reduce the number of queries you make. i.e. As soon as the socket disconnects from the server, you can send a write operation to Firebase. "Every 3 seconds vs Only when the user disconnects".
Plus (not something that you asked for), if you would be setting up a socket server of your own, then it shall help in the following scenarios as well:
Typing events (The indication we get when the other person is typing a message)
Quicker way to know if the person at the other end is online/offline (because of sockets)
My question might be bit confusing, but what I basically want to do is,
I want to display the time exceeded for each item in the list when the start button on each item is clicked.
For example, suppose I have a listView of items that has a time and a button
TIME START
TIME START
TIME START
When I click the start button, the TIME textView should start a timer that increments every 1 minute and stops when it reaches a specific minute).
Since I am using the Firebase realtime database as my DB, I was thinking of incrementing 1 to the Time data every 1 minute.
What is a good approach of doing this?
You can update a value in Firebase Realtime Database either on client side or either on server side by using Cloud Functions for Firebase.
You can write a function that updates that particular value every 10 minutes. The benefit of using Cloud Functions rather then the first option is that will still work even if the application is offline. This is the best practice.
I'm developing a simple tracking application. This application sends current location and time to a remote server every 30 seconds. I've used android-priority-jobqueue and Retrofit, so if no notwork is available the app enqueues these data and send them when a network's available.
If the app works offline for you say 1 hour after getting online, it calls my webapi 120 times. is there any out of box solution to combine these jobs in one or replace my api call jobs in android-priority-jobqueue with one job containing all past one hour data so the data is sent in one webapi call?
I mean some event that raises before run jobs in the queue and a way to access all jobs in the queue to replace them with a new one
One way to solve this problem is to have repository or cache to store locations, and schedule Single Instance Jobs every 30 seconds, which just clear out repo/cache and send all locations at once.
The whole project consists in making an android application based on crowd sensing that collects data from volunteers (phase 1) and then based on the collected data, every user has a file in the server and the file would be separated into multiple online episodes and I will apply Artificial intelligence algorithms to make the data mining better.
For example, if in phase 1 I can determine that the volunteer is usually at home before 8am and he has no valuable information for me to analyse then the application wouldn't even send data to the server.
I'm still in phase 1, I'm trying to make an android application that starts running as soon as the user in connected to internet, it would send the data (battery, gps, activity...) to the server and based on the activity (walking, running...) it would determine when the next flow of data is sent. For exemple if he is walking then, the next time the data is sent to the server would be in 5 minutes.
While searching, I found many solutions on how to make an android application run in the background while keeping sensors collecting full time (high energy consumption) and the better solution would be to have a schedule for example every 5 minutes.
What I want to know is, is there an android studio solution to make the schedule dynamic? because it depends on the activity as I said before, so each time it collects information it schedules the next time the information is collected again (the next time we use sensors to collect the data then send it to the server).
I hope I made my point clear: what is always running in the background is an application that has a countdown to a specific moment; when that moment arrives the sensors are ON to collect data and send it to the server and that data is also used to make the next countdown (based on the activity data collected) and then the sensor are off until the countdown ends.
I would appreciate your suggestions.
Probably the best option for your project is AlarmManager. It can execute your code periodically or at a particular time, samples could be found here.
Also the app could be launched by system state event(like wi-fi on/off). To catch these events you need to use BroadcastReceiver, samples are here.
So you don't really need to implement countdown timers or background threads. Moreover manually created countdown background thread could be killed by the system at any time.
I have an app where I have up to a few thousand entries in a firebase table.
Now someone is connecting to this table and I need to count and sum these items up.
-itemlist
|
--1
|-x:2
--2
|-x:4
and so on. A user can connect at any time (meaning he never saw this table before) and another user can change some value at any given time or add values.
Now if I try and add a ValueEventListener to "itemlist" it works if there is no new data but as soon as I connect to a new database with 1000 entries or so the listener calls for every one of these 1000 entries.
I tried with onChildlistener but this calls the on ChildItem added for every item extra on the first time.
This takes over 2 minutes sometimes.
Is there a way to get the whole database once, calculate it and then only listen for changes?
The Firebase Database has no server-side aggregation operators, since they would inherently be at odds with the scalability and realtime nature of the database.
That leaves you with two options to calculate aggregates:
perform them client side as you already suggested
keep a running aggregate that you update with every change
Performing the aggregation client-side is a good option if the client already needs to display the data anyway. For example: if you're showing the list of users in a specific chat room, you can easily count the number of users client-side from the same data.
But if you don't need the data client-side, then just downloading it to aggregate it is wasteful and will hurt scalability of your app. In such cases, an option is to keep an extra node that keeps the aggregate and update it with every relevant write operation. For example: if you want to show how many users have registered with your app, you could keep a global /user_count that you update whenever a user registers/unregisters. For this update, you'd typically use a transaction.