combining android-priority-jobqueue queued jobs in one - android

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.

Related

Android: Sync CountDownTimer across multiple clients using Firebase Realtime Database

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.

Cloud function for firebase being fired too many times

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.

What is the correct way of fetching data from web api periodically in background even if the app is closed?

I want to create an android app which should fetch data from a WEB-API after equal intervals of time (lets say after every five minutes) even if my app is closed. Also it should generate the notifications if new data is fetched.
What is the correct way to do it ??
Do I need to you background service and call a thread from on Start Command and fetch data in that thread with some sleep time ???
Fetching Data in Background..?? what is better to hit API or socket
When you want your data to be fetched in background as well that generally we hit api once and then w use socket for it

Posting data to server every 15 minutes using Sync Adapter and Alarms

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.

Running One off GCM Network Manager task on Push

In an Android app, I perform a data poll from server on push. When the device receives a push it pings the server to get the latest data.
As the user base grows, Server could potentially get 1000's of request at the time of push taking the backend down. I am looking for a good alternative so that I can spread out the server call in a given time window say next 2 hours. What is the a good way to do it?
I was looking into GCM Network Manager One-off task. One thing I am not certain is that even if I set a time-window start now with offset of 2 hours, since the device would be connected to the network when the push is received, it would trigger the server call right away defeating the purpose.
Any suggestions on what might be a good way to resolve this?
I don't think the task will execute immediately, as the GCM network manager doesn't execute only when the network is up, but tries to batch jobs together to reduce the number of wakeups and power consumption.
However, to be safe, when you create the OneoffTask, you can set an execution window. There you can set a minimum amount of time before the task will run. I suggest using a random number of seconds, e.g. between 0 and 60 to reduce the potential load on your server.

Categories

Resources