Android account sync interval change in preferences - android

Hi
I am implementing an account sync adapter and i am trying to make a preference screen in settings under Account and Sync for the user to be able to change the sync interval. what i want to know is how can i make the adapter sync at the specified time on the preference screen? does android provide a method for that? what i was thinking of doing was saving the time of the last successful sync and comparing the passed time since then with the period stored in preferences. is this the right way to do it or is there a cleaner solution to my problem?

What you can do is call the method addPeriodicSync(Account account, String authority, Bundle extras, long pollFrequency)
Specifies that a sync should be requested with the specified the account, authority, and extras at the given frequency.
I think it will solve your problem.

For an example, see this commit where I added an option to change the sync interval in one of my apps. This commit then expanded on that by dynamically choosing how this is done, based on the api level of the os its currently running on, so it uses the built in method for 8+, and the alarm for <8.
The gist of it is that setting the interval on api <8 creates an alarm using the AlarmManager api with the specified interval that triggers a BroadcastReceiver to call requestSync.

Related

Android : Decrement a variable daily

Heyyy, I know how to save variables and other data in SharedPreferences, but I like to know how it would be possible to decrement a variable daily.
Already this var (int) will be in the Shared Preferences, and every day we decrements of -1.
How could I decrement, knowing that the user does not necessarily open the app every day for example?
Have a good day :)
Save the original date, when the application is opened check for current date and you know what your variable should be :)
If you want to decrement the variable on Daily Basis then
Implement a BroadcastReceiver and declare it in AndroidManifest.xml with action android.intent.action.DATE_CHANGED. This would run the BroadcastReceiver once in a day when the date is changed.
In onReceive() method you can place code (validations) and persist results into SharedPrefs.
Note:
1. Service would incur huge running cost.
2. Activity would run the same code everytime it opens but BroadCast would run it once a day in a clean and independent fashion.
You might need a Broadcast action BOOT_COMPLETED as if the device is turned on (reboot).
You have several choices:
Every time your app starts, load the value from Shared Preferences and decrement it by the number of days which have passed.
Write a service which decrements the values every day.
Write a BroadcastReceiver which starts when the date changes.
I think using JobScheduler would be a nice way to implement this. It's available from API 21 and allows the app to execute actions under certain circumstances, even if it's not open. Here's the official doc, and a nice tutorial here.

If I call addperiodicsync and autosync on the same account which one will be effective?

If for a particular calendar sync account in android I call following two in given order,
ContentResolver.addPeriodicSync(account,CalendarContract.AUTHORITY, result, 120);
ContentResolver.setSyncAutomatically(account,CalendarContract.AUTHORITY, true);
What would be given priority ? As per documentation
These periodic syncs honor the "syncAutomatically" and "masterSyncAutomatically" settings. Although these sync are scheduled at the specified frequency, it may take longer for it to actually be started if other syncs are ahead of it in the sync operation queue. This means that the actual start time may drift.

Retrieving the current date and time from a time server

In my Android app, I would like to retrieve the current date/time (UTC) from some server. Android does have the built-in ability to synchronize the device's date and time with some server but I have found this to be unreliable. Does Google or some other well known service provider provide a simple API that would allow me to retrieve the current date/time? I am not interested in trying to set the date/time on the device (that's not even possible). But I do need to know the correct date in order to perform scheduled tasks that depend on exact dates.
I have seen a device reset its date to something like 1980 when the battery has been removed for an extended period of time and therefore I cannot rely upon the date of the device.
EDIT:
I came across this post:
https://stackoverflow.com/a/13066268/753632
But it requires installing Apache Commons Net. Kind of overkill just to get the time. I don't need to bloat my code more than it already is.
you can refer this link How can I get the "network" time, (from the "Automatic" setting called "Use network-provided values"), NOT the time on the phone?
You could use the calender class, like is explained here, although this uses the time of the device itself. You could also read this it explains how to get the time for the service provider.
I think using the calender and then calculating the UTC time with based on the timezone the phone is in (like this). Because the phone already gets it's time from a server when it is connected to the internet.
I hope this helps.
EDIT: I see you edited your post. So you don't want to use the device time... I think you could look into getting it from the service provider then.

Syncadapter onPerformSync being called twice the first time

My syncadapter works well, except for one thing. After the user installs the application, my app syncs twice. Later, if I manually sync it in "settings" it syncs just once as expected. It's just the very first run of the app that this happens.
Here's the code in my "onCreate" that creates account if not already created and sets up the syncadapter. Any ideas on what I'm doing wrong?
if (accountManager.addAccountExplicitly(appAccount, null, null)) {
ContentResolver.setIsSyncable(appAccount, PROVIDER, 1);
ContentResolver.setSyncAutomatically(appAccount, PROVIDER, true);
Bundle extras = new Bundle();
extras.putBoolean("dummy stuff", true);
ContentResolver.addPeriodicSync(appAccount, PROVIDER, extras, 43200);
}
My desired behavior is for the app to sync once immediately after installation and then periodically as per the "addPeriodicSync" statement.
I observed this behavior as well.
It is correct, that addAccountExplicit() will trigger a system-wide account resync of stale accounts.
Clarificiation
However, Zapek's observation about addPeriodic sync or request sync being "immediate" syncs, is not quite correct. Both are just queued. Additionally the following holds for addPeriodicSync():
These periodic syncs honor the "syncAutomatically" and
"masterSyncAutomatically" settings. Although these sync are scheduled
at the specified frequency, it may take longer for it to actually be
started if other syncs are ahead of it in the sync operation queue.
This means that the actual start time may drift.
(Documentation)
Pertaining to your problem
What you experience is described in the training on running sync adapters:
The method addPeriodicSync() doesn't disable setSyncAutomatically(),
so you may get multiple sync runs in a relatively short period of
time. Also, only a few sync adapter control flags are allowed in a
call to addPeriodicSync(); the flags that are not allowed are
described in the referenced documentation for addPeriodicSync().
Android Training Sync Adapter
Google's own solution looks like yours, with a lower frequency even (60*60=3600):
if (accountManager.addAccountExplicitly(account, null, null)) {
// Inform the system that this account supports sync
ContentResolver.setIsSyncable(account, CONTENT_AUTHORITY, 1);
// Inform the system that this account is eligible for auto sync when the network is up
ContentResolver.setSyncAutomatically(account, CONTENT_AUTHORITY, true);
// Recommend a schedule for automatic synchronization. The system may modify this based
// on other scheduled syncs and network utilization.
ContentResolver.addPeriodicSync(
account, CONTENT_AUTHORITY, new Bundle(),SYNC_FREQUENCY);
newAccount = true;
}
Proposition
I propose using the SyncStats in onPerformSync() to actually return some information about your initial sync to the system, so it can schedule more efficiently.
syncResult.stats.numEntries++; // For every dataset
this may not help if the other task is already scheduled - investigating
Additionally one may set up a flag 'isInitialOnPerformSync' (w. sharedPreferences), to cause other tasks to back up.
syncResult.delayUntil = <time>;
I personally am not really fan of creating a fixed no sync timeframe after the initial sync.
Further Considerations - Initial Sync Immediately
As stated in the clarification, the sync will not run immediately with your settings. There is a solution, that will let you sync immediately. This will not influence the sync settings, and will not cause them to backoff, which is why this does not solve your problem, but it has the effect that your user will not have to wait for sync to kick in. Important if you use this to display the main content in your app this way.
Code:
Set up a flag for isInitialSync inside your normal app process (which you save e.g. in defaultSharedPreferences). You can even use the Upon the initial completion of the installation or login (if authentication is required) you can invoke an immediate sync as follow.
/**
* Start an asynchronous sync operation immediately. </br>
*
* #param account
*/
public static void requestSyncImmediately(Account account) {
// Disable sync backoff and ignore sync preferences. In other words...perform sync NOW!
Bundle settingsBundle = new Bundle();
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
// Request sync with settings
ContentResolver.requestSync(account, SyncConstants.CONTENT_AUTHORITY, settingsBundle);
}
Are you requesting a sync apart from the addPeriodicSync()?
It should sync by itself when you first add the account. So any extra sync requests would account for the double sync.
If that doesn't help, you can always save in preferences the time of the last sync and check against that every sync, so that you can limit the sync frequency to whatever you want.
Hope that helps!
addAccountExplicitely() will cause a sync for all accounts that have an unknown syncable state (which includes your newly added SyncAdapter).
The problem is that it can take from a few seconds to a few minutes to perform, depending on how many other apps with a SyncAdapter and configured accounts are installed.
addPeriodicSync() (or requestSync()) will perform a sync immediately, which is desirable in the case that the user needs to see data as soon as possible when launching the app.
There's not much you can do, other than making sure your syncs are optimized to be quick in the case that no data between the client and server changed.

Application Signature for 2 days in android

I wanted add application signature for some application, which will be valid only for 1 or 2 days. I did enough googling but did not find enough info. So Please let me know how can i make a application get expired in 2 days..
simply add an alarm of calculating time equals to 2 days at the very first start of the app.When the alarm gets expired you will get the callback and set a global flag as false.Code in your app that if that flag is false, display a lock screen
You could save the first start time in SharedPreferences and then on each start compare the current time with the saved one. If the 2 days have passed, you can do what ever action you want.
It will probably not be possible to automatically remove the app from the device though.
If your app sends data to a server, you should store the "first run time" there. Storing it locally on the phone (for example SharedPreferences) is not very safe as it's easily overcome by changing the phone's time settings.

Categories

Resources