How often should an Android app and server sync - java

I'm developing an Android app that talks to a Play-framework app, the two apps are passing user data between one another using Volley requests, my question is this:
Is it desirable to have the Android app sync with the Play server constantly to check for changes to the user profile? (like syncing during a fragment change)
Or is it better practice to have the user on the Android app logout and back in before that changes occur.
Or is there some alternative solution that only syncs with the server if a change occurs?
I think the last option would be the most efficient and desirable, but I fail to see how could do the check without sending a request first to the server and if I'm sending a request to check for changes anyway, wouldn't it make sense to have the changes in the response.

You should not sync whenever a fragment changes. It is a waste of the user's battery and data. You also most likely don't want to force a logout/login all that often as it becomes inconvenient for the user.
If you are expecting very infrequent changes to the user profile, it might be better to send a push request from the server using GCM to inform the app that it should invalidate its local cache. Then query the server for new profile information.
If using push is unfeasible for some reason, you might want to look into using a SyncAdapter and syncing infrequently. In most cases, it should be okay if profile information is potentially behind unless the user is specifically checking the profile settings, in which case you might want to check the validity of your cache when they check their settings.

Related

Best way to send firebase message or notification that trigger pull request from server

Currently the Android application I have taken in charge performs a "pull" on the server every minute to recover data and update a fragment with this data. Obviously this does not work when the device switches to doze mode. So I decided to use FCM as Google recommends.
Constraints :
The user needs to know that new data is available even in doze mode.
To not change the application too much, I do not want to send the data in the firebase message but rather send an https request to the server when I receive the fcm message.
The fcm message must:
Advise the user that new data is available with a notification.
If the user presses the notification OR returns to the application after turning the screen on, the https request must be triggered and fragment has to be updated.
I will add that it must be triggered at the latest when the user returns to the application.
My solution for now
I used a data message with a high priority instead of a notification message because a notification message need the user to tape the notification to trigger action.
In onMessageReceived :
I send the notification that redirects to my application.
I send my request to the server and update my application.
Disadvantage of my solution :
If my app is killed by the system while the screen was off what's going on?
My request has a time limit to complete when the phone come out of doze mode.
Questions :
Is this solution the best possible ?
Is there another way to proceed?
Perhaps could i schedule a task that runs immediately when user resume my app in onMessage received ? But i dont know how to do that.
Use WorkManager to schedule the background work to run immediately. It will also retry until your code indicates that it's successful.
I answer myself to close the subject and hope it can help someone !
After a night ... I definitely do not like the workmanager solution. Even if in practice it can work I do not like to use APIs for unplanned uses. If google tells me that it is not garanty to launch task immediately, they are (much :)) better than me and I believe them!
In this case, I think that my task may be postponed, for example because the OS wants to group calls with other apps. There may be internal conditions i dont know about.
Especially since I found a much simpler solution.
In onMessageReceived, I use a simple boolean indicator.
In the onResume of the activity I want to update I read this indicator and I launch my request if true for example.
I no longer need a scheduler, and after all if it is not done 100% reliable, it does not matter :
If fcm could send me a message there is a lot of chance there is a network when the user turn on the screen.
Even if there is none it is not very serious since I can warn the user who can proceed otherwise (by phoning for example !!!!)

Android O background networking

I was reading about background service limitation in Android 8 and from what I read it seems that you can't run your service in the background for a long time. This seems reasonable but because I use background service to keep connection to server - currently pooling new stuff, sending location and responses I am a bit confused. The responses are OK, I can respond only when interacting with the app, but the pooling new stuff is problematic because it needs to get an stuff from server and if something new come present the user with a notification to respond to it.
If I understand it correctly I can use JobScheduler to schedule some job every several seconds. I can basically schedule the pooling. For the background locations, well there are those restrictions so only foreground service is an option to get updates in requested time.
I will be migrating to websockets and then the pooling is off, the connection to server will be persistent and the app will get updates from server, I was planing to do this in the background service so something would receive stuff from server everytime. However it seems I can't since Android 8. How would you solve this? Should I use foreground service for location and server connection? Or is there a better way to do background networking in an android app on android 8?
Thanks
Here are a few options for performing background work on Android O:
Use JobScheduler. You already seem to have a good grasp on this one- the downside is that it is periodic, not persistent.
Use GCM/FCM or a similar push service to push data to your app when it is relevant instead of constantly holding a connection to your server.
Use a foreground service. This will allow you to continue performing your background work without your app being in the foreground, but will put a notification in the status bar to inform your user that you are doing that work.
Before you select one of these methods, you should take a moment to step back and look at the data that you need from your server and determine why you need a persistent connection and whether the first or second options might be sufficient.
If you absolutely need a persistent connection to your server, the last option is your best option. The idea behind the changes in O is to still allow background work such as what you are describing, but to make it painfully obvious to the user that your app is doing so. That way if they don't think your data is as important as you do, they can take action.

Sync mechanism like Google Drive in Java/Android

I am trying to develop a mechanism for Sync data with app & server, like Google Drive/Dropbox for one of my android based application where data are stored locally on device and I would like to sync data with server.
Ways thought -
1) Observer which looks for change and call web service
2) Background service which runs in background and check for changes
3) Set Alarm which checks at particular time and sync all the data with server
I have not started to which option to go with, I would like to get experts view on this and like to get some guidance so that I can achieve the sync mechanism in best possible way for my app.
All suggestion are welcome.
Thinking on same line as you have been,the aim should be to achieve a balance between the number of times the server is queried for same set of information AND the data consistency.
for this, I would fire a GCM message from my server to the device for which the data on the server has changed, I would maintain a count for these Update Messages(No Notification genereated). If this count Exceeds the minimum-threshold-count-value, I would immediately call for an UPDATE. Or otherwise, if this count still is less than the threshold-count-value, for a certain period, that I would call the threshold-waiting-period, then too I call for an UPDATE.
The UPDATE would be using Sync Adapters and Services. This link explains its basics.
Hope this prooves to be helpful!
...so that I can achieve the sync mechanism in best possible way for my app
Well, the BEST mechanism depends completely on what kind of application, you are developing. Also, your option 1 and 2 seems very similar to me except few implementation changes. However, how frequently your device data is changing, that also matters a lot. If you have authentication mechanism, you can configure sync up, at the time, whenever you login to your app. Like in case of confidential data, sync up should happen immediately.
If data is managed well based on authentication and authorization based on user roles or so, you also need to take care of synchronization among them. For example, one user has updated an entity which is not yet sync and another user tries to update the same, then first user will see his changes are not synced or has been lost.
The best way (means having least drawbacks) to do this would be sync up trigger at a particular interval of time OR at every login time. (still as I said, depends on your app).
Hope this would clear some or all of your doubts.

How to manage multiple data syncing threads

I have two threads, each of which handle syncing data one way either from the server or to the server. The thread for getting data off the server needs to run once a day. The other sending data to the server needs to run every 15 mins. I am currently using an Alarm Manager to create repeating alarms for each of these threads. This is then received by a BroadcastReceiver, from which i call an activity, which then according to the data passed into the activity either runs the to server syncing thread or the from server syncing thread. I am using the activity to display a dialog box, to prevent the user from using the application until the syncing has been completed as they both access the database required by the application. Is this the correct way to accomplish this task, or are there better alternatives?
Thank you in advance
This question is not really fit for SO... This is more a debate without any details on how your app works.
Anyway I would use an Android Service to do so. You do not need to bother the user just to upload data. Also why block the use of the app for uploading? Since for uploading you only need to read, just make a snapshot of the current data and upload it. Any changes the user is making right now will be uploaded in next upload, so that's not a problem.
For downloading, you most likely do need to block the app use, but maybe not. This depends on how the app works. You could start DB transactions to avoid doing that.

How to be made aware of incoming emails on GMail without frequent polling?

If I am developing an Android application, what is the most feasible way to get near real-time notifications about an incoming email? Is there a push-like mechanism, or can I hold my IMAP connection for a long time, or do I use IDLE command?
Consider that user is authorized to use GMail services via OAuth and I don't want to poll IMAP server madly.
Update:
I'm not using the phone's configured-in Google account. There is another account set up using OAuth.
I'm using Apache Commons Net to connect to IMAP/SMTP in my app. It's a bare-bone library for IMAP, but I can perhaps modify it to add IMAP commands/extensions.
You can register a ContentObserver with GMail, anytime something changes in GMail, the observer will be called.
contentResolver.registerContentObserver(Uri.parse("content://gmail-ls"), true, myContentObserver );
Override onChange in your ContentObserver to do stuff when something in GMail changes.
Since IMAP does natively provide any sort of push notifications and the Google extensions don't either, you have to implement it yourself.
One way is to use IDLE requests, which is still a cheap way to do polling. Of course, you can't expect your app to be running all the time, so you need to use a background service. An 'always-on' service is however an anti-pattern on Android and will drain the battery quickly and likely get you many 1-stars. Additionally the system may decide to kill it at any time. The other alternative is to use AlarmManager to start the service periodically, but starting it every couple of seconds or so is just as bad. So you are basically back to square one: polling.
The other way is to get push notifications using GCM or a similar service. This does require you to have a server, and the server needs to have the authentication info for the user (which might be a problem), but there are no real constraints concerning keeping open connections and sending IDLEs each second, etc. On the Android side, if you want to implement push yourself, you need to keep an open socket to get notifications. This is not very easy to do if you are not a system app (see above), so that leaves GCM. The connection it uses is manged by the system (Google Services framework), it can do things a regular app cannot, and you basically get it for free, since it's already there. It receives small pieces of data when there is something to do, called 'tickles'. Those in turn trigger broadcasts, Google Play updates, etc.
So, take your pick. Or just give up, register the account and use GMail and its labels Android API.
I'd check out Google Cloud Messaging (GCM):
http://developer.android.com/training/cloudsync/gcm.html
My understanding is that this works without requiring the user's Google account, and lets you handle authentication.
See a tutorial here:
http://www.techrepublic.com/blog/app-builder/implementing-googles-cloud-to-device-messaging/428
You would need additional server-side code running to do this though.

Categories