We have an android app which collects users' location every 30 seconds and writes it to Firebase Realtime database. I want to execute a cloud function on firebase if the user's location has not changed for 15 minutes.
Initial approach:
Have the android app make a HTTP call to invoke the cloud function every 15 minutes.
Problem with the approach:
There are 1000 active users and expected to grow to 10,000 this approach would result in firing 960,000 (1000 users * 4 requests per hour * 24 hours) times every day.
The purpose of location is that if it has not changed after 15 min., the cloud function sends a notification to a web client.
The mobile phones operate in low connectivity and are low-end devices so it is not viable to have the mobile trigger a notification.
The goal is to minimise the number of cloud functions to be fired.
What could be the right approach so that number of cloud function invocations is minimised?
The solution your are asking is depending on the context of the position data usage.
If it's just a statistic, you could cache the position data locally and push it into a cloud from time to time.
If the position data is used to provide a service based on, it's up to you to decide based on algorithms implemented.
Related
I can't find documentation on best practices for the maximum number of messages one should send to the Firebase database (or one like it) over a period of time, like one second, and also what rate an app could handle receiving without slowing down significantly. For example:
//send updated location of user character in MMORG
MyDatabaseReference.child(LOCATIONS).child(charid).setValue . . .
//recieive locations of other characters in a MMORG
MyDatabaseReference.child(LOCATIONS).addValueEventListener(new
ValueEventListener() { . . .
In testing, 3 devices each sending 20 messages per second to the database, and each receiving 60 messages per second, appears to work OK (S8 used, a fast device). I was wondering what would happen with, say, 100 devices, in which case each user app would be getting 2000 messages per second theoretically. I imagine there is some automatic throttling of this.
As mentioned in Firebase officil documentation regarding Firebase database limits, there is a maximum of 1000 write operations/second for the free plan.
If you want to stay on the free plan, remember that when you'll reach the maximum number of writes per second, it doesn't mean that you'll not be able to use Firebase database anymore. When 1001th simultaneous connection occurs, a queue of operations is created and Firebase will wait until one connection is closed, and than it uses your new connection.
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.
I have 2 Android Apps involved in a Food Car-Delivery Service:
1- Driver.App : an App running on a Device in the Car (driver)
delivering the food.
The Driver.App is notifying the GPS position to a WebAPI Server where the position (lat,lng) is stored on a SQL-DB.
The Driver.App notifies this position every 2-5 seconds... depends on the settings but mainly every 3 seconds.
2- Customer.App : an App where the Customer track the position on a
Map of the food delivery.
The Customer.App requests to the WebAPI every 5 seconds where it tracks the latest position of the car delivering the food.
I am considering changing this WebAPI solution (explain above) to use Firebase Realtime Database instead. I really need the expertise of this community in order to understand the pros and cons that I must face.
The new idea (with Firebase) is to have the Customer.App subscribed to a Driver.App.Locations (Firebase.DB) and so the Customer will not need to keep requesting and doing http-calls to the WebAPI.
The Driver.App will notify the changes to Firebase and so Firebase will notify the updates to the Customers.App.
I have 3 questions in regards the Customer.App Battery:
Doing the WebAPI request... how bad is it to do this? How much battery will consume the WebAPI request every 5 seconds considering that the result/response JSON is around 500 bytes. Will that be an issue with the App and the Battery?
Using Firebase, how much REALLY efficiency will be listening and receiving the updates from the Firebase every time the Driver updates the locations instead of doing the http-request every 5 seconds?
Is there any other better suggestion to be implemented?
I would like to know the pros/cons of doing the WebAPI-Http-Request instead of being listening while subscribed to the Firebase, of course knowing the the Delivery.Car is moving and so is generating new locations every time.
My app has the feature to send a particular app data to a server once a day in every 24 hr.
Total number of my Android app installs on play store - 5,00,000 (approx)
Total no of seconds in 24 hr - 86400 sec.
I need to distribute the load on server over the entire day, in order to assure that all the installed apps are not sending data at the same time or in a short time window.
In short I need some logic on client side to distribute these calls to server evenly across 86400 sec.
A random number should give you enough spread with so many installs. So, first time app runs, call Rand(0, 86399), and save it in preferences. Then send sms at that second in day.
We had similar situation, and we switched this type of call from Apache server to node.js server, and never looked back. Node.js can handle many many more connections AND can return and close connection before all the work is done (so for example if data is not critical, you can close connection and return, before saving to database).
Requirement - I need to get the user's location coordinates every 15 minutes roughly and post it to the server. It is necessary to post data roughly at these intervals.
Implementation - I've made a sync adapter instead of using AlarmManager as it saves battery. I've set ContentResolver.addPeriodicSync() to sync my app every 15 minutes roughly which gets the current location and posts to server.
Problem - In case there's no internet connection, I want to continue taking the user's location every 15 minutes and save them in the local sqlite database. When the internet comes back again next time then I'll post all the saved locations in one go so that server data remains consistent and after that sync will resume as normal.
The main problem is that when there's no internet then the sync stops and I stop getting periodic sync callbacks in my app and I'm not able to save data in the local database. So what I want is that even when there's no internet I keep getting callbacks at regular intervals till the internet comes back and auto sync starts again. Can the sync adapter do that?
One solution I can think of is that I get a broadcast when the Internet stops and at that moment I start using the AlarmManager to start a service every 15 minutes and get the location and save to local database. And when the internet comes back on then I stop using the AlarmManager and go back to auto syncing.
Solution 2 - Provided by David Medenjak below. It is also efficient due to AlarmManager's setInexactRepeating() behavior which tries to imitate Sync adapter's behavior by scheduling Alarms for different apps together to reduce the number of times the CPU wakes up. Also it leads to a little simpler implementation. Would this the better way than the previous solution comparing the pros and cons?
Still any better way to achieve this?
You are mixing two things:
Getting the user location every 15 minutes
Syncing the data with the server
If you start mixing those you have a service and sync adapter that are both strongly dependent on each other, you have to check for states which of those has run and which should run. You might end up with the exact thing that you want (syncing every 15 minutes, just cache it if user is offline) but it will be hard to test and maintain.
Always use a service that is run every 15 minutes to store the current user location.
Periodically sync all updates to the server. This may also happen to be every 15 minutes, but you should not depend on this.
By having one part just storing the location and the other part just synchronizing the data you will have a much easier time handling things. And you also don't have to worry about internet connection or the interval of the synchronizations (since sync adapters are not guaranteed to run at exact times).
Concerning battery life (comments)
There should be no big difference whether a SyncAdapter uses gps and posts it immediately or a service persists it for the time being until the adapter syncs it. As soon as a task has to run every x minutes the device will have to wake up.
There might be slight improvements if the synchronization is run at a slower rate compared to the service, since the gps alone might not need any internet connection.
IntentService - runs every 15 min (using AlarmManager) and saves the user location in the db and mark it as unsent.
SyncAdapter - runs every 15 min and ties to send all unsent locations to the server. On success mark the location as sent. Android will make sure it's only run when there is a internet connection.
Edit:
The key point is separating the two sub-tasks (also suggested by #David Medenjak):
1) Get a location update and store it in a db
2) Send the location updates to the server when there is a network connection.
The FusedLocationProvider has a method
requestLocationUpdates (GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)
for when your app is in the background. Link
This method is suited for the background use cases, more specifically
for receiving location updates, even when the app has been killed by
the system.
You can use a LocationRequest to set the priority, interval, power consumption. Link
When you receive the pending intent, you can insert the location in the database and request a sync using the sync adapter.