Firebase: Listening to multiple user nodes - android

I'm working on an app using Firebase and Geofire. On running the Geo query at the current location, let's say I receive 10 keys in the OnKeyEntered override method. Each of these keys is essentially a user node in Firebase. I need to listen to each of the user in the query area for any data change so that I can show updates on the map in realtime.
Currently, I'm adding a ValueEventListener for every key entered but I'm not sure if starting so many listeners at the same time is good idea. The users in the query area can potentially be more than 50. That means I could have 50 open listeners!
Is there a better way to go about it? I was trying to figure out a firebase query to filter on only the geo query keys but was unsuccessful.
Any help would be great!

Listeners are not computationally expensive, unless you have one that's going to be triggered very frequently because the data it's listening to is changing often.
Don't fall into the trap of optimizing your code before you actually observe a need to optimize it. When you see that performance is poor, that's the time to make optimizations. If you need a bunch of listeners to get your work done, go ahead and do that. Just know what your practical upper bound it, and be sure to test that upper bound for problems.

Related

Firebase database fetching a number of nodes at a time

I know that pagination is a well discussed topic here but... Is there a way to fetch some amount of nodes(something like 5 at a time) and know when the end has been reached? Firebase Database does not have a way of knowing the total number of nodes. So how will I achieve this?
The only way to know if you have all the data at a location is to perform a single 'value' type query on it. Even then, the data may change after that listener is invoked, so all you really have is a snapshot at a particular moment in tim.
For child events, there is no way to know there is no more data after the current event. In fact, child events may keep firing as more data is added, as long as the listener is still added at that location.
This is why pagination is so hard. There is no generalized way to know if you have a full page of data at any given point, or if there's another page.

Better way to update PolyLine track from GPS readings

In my app I have a Service which receives location updates and stores them to a database. I also have a Fragment which displays a MapView and a PolyLine of all recorded waypoints from the database.
During recording, the Service notifies the Fragment about new waypoints so the Fragment can update the PolyLine. The problem is that when the user navigates away from the app the app the Service keeps recording waypoints to the database, but now the Fragment doesn't get updated since the Fragment is paused. So in onResume I create a new PolyLine, read all the waypoints in the database and add them to the database.
This is all working fine, but it doesn't really feel like it's optimal from a performance perspective to create a new PolyLine and re-add all the waypoints (there could be thousands!). I guess I could just re-add any new waypoints that are not already in the PolyLine, but I wanted to see if anyone here has an alternate solution? Is there any way to keep the Fragment "alive" and updating its PolyLine even when the app is in the background (as long as the service is running)? Or is there a better way to do this?
Recreating the polyline is probably inevitable, but here are some things you should think about doing if performance becomes an issue:
Put a time limit. When recreating the polyline, only fetch the data in the last hour or day (test and you'll be able to determine the best value here), and offer an option to extend that period. This will make it more understood by the user that the data needs some time to load, and that the app will use more resources.
Aggregate the data while saving them. This should reduce the disk space used to save the points in the database (very important for low end devices) and improve on the performance when rebuilding the activity.. These are some tips for what you can do to reduce the number:
Check 2 points behind and see if they are a straight line. If so, delete the middle one. That should remove a lot of data recorded when the user is in a car or walking a long distance
Check if the last set of points (5 or more) are in the same area, that way you can get rid of a lot of data. So if a user is just waling in his home or workplace, you can just save one point for that without loosing too much data, which shouldn't really be a problem in most (99%) of the applications.

Sum firebase data efficiently up

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.

Android: Fetch changed data on server in real-time. Which technique is better?

I am building an app that shows user's friends' real-time locations on a map.
Each user updates his currnet location on the server (Parse.com) every defined interval (time and distance).
When a user opens the FindFriends activity, he'll get a map with markers on friends locations.
The friends locations data can be retrieved in two methods:
When activity is running, I am calling an AsyncTask that will download locations data from the server in a while loop (inside doInBackground), and after each time I call publishProgress() to handle the changes on the map.
I wrote a cloud code that is called every time a user updates his location on the server, which sends push notification to the relevant users (the user cant see the notification). When the FindFriends activity is running, a broadcast reciever is getting those pushes and update locations data on the map.
My question is: Which method is better for my needs or maybe I should do it differently? Of course I would like to keep battery consumption to minimum but not at expense of getting almost real time data.
I don't really think that this is an appropriate question, since you really should just make a prototype using each implementation, and see which is more performant in your particular use case. However, I can say that I definitely prefer the cloud solution. I've used GCM to implement a messaging client, and from my testing the updates are definitely really quick (very little noticeable lag time, when testing two clients side by side). So, I don't think that implementing it with GCM would negatively impact your user experience, and it does have the plus side of eliminating pointless server polling when, potentially, no updates could be present - which saves on battery.
If you want real time data then push notification GCM is not a good idea because, there is no guarantee that all users will get push notification in time. Sometime you will encounter delays in push notification.
Under given circumstances AsyncTask or Service can be a good way to perform required task, if they are handled properly. You should have control on AsyncTask/Service so that you can stop it any time you want.

Do something when phone reaches a set of location?

I have a list of coordinates in the database identified as POI. For a city could be >100 records.
I would like to get notified when the phone gets in 150 meters range of one of the location. The location coordinates too has an error/radius, usually 10 to 100meters. Since I don't find it good to add each location(could be hundreds) for a trigger, how can I optimize the wake-up code?
Also do I have options to remove a previously setup notification from the queue?
You could store your POIs in some sort of intelligent Hash-Table using the coordinates to compute a unique hash. Each time a location update arrives you make a lookup in your hash-table to see if there are POIs near the current location. This lookup should only take O(1), since it is a hash-lookup.
The desired range should be taken into account when computing the hashes and storing the POIs.
Just an idea!
Kind regards,
mefiX
There's an app named Locale, that can toggle various events based on your GPS location OR available Wifi network OR cell-station id, etc
It also has a plugins interface. It could be useful for you to examine that app and, maybe, write a plugin for it.
This problem reminds me of graphics in video games. There's no need to load the points that are well outside your range of movement. I'd break down the map into a grid, set triggers for the 8 adjecent grid blocks and then for each of the POI within the current grid block. When a new grid block is reached the triggers are updated. It'd probably be smart to overlap the grid blocks considering the range of error.

Categories

Resources