Hello all,
In Today’s article we will be discussing about the SyncAdapters in Android.
SyncAdapter is just a simple plugin like structure for syncing your server and Device.
Check out this post about Account authenticator before proceeding.
Why do we use SyncAdapter instead of Using Alarm Manger to Sync?
Automated execution
Sync can be requested based on variety of criteria, including data changes, elapsed time, or time of day.
Automated network checking
The system only runs your data transfer when the device has network connectivity.
Improved battery performance
Allows you to centralize all of your app’s data transfer tasks in one place, so that they all run at the same time. Your data transfer is also scheduled in conjunction with data transfers from other apps. These factors reduce the number of times the system has to switch on the network, which reduces battery usage.
Account management and authentication
If your app requires user credentials or server login, you can optionally integrate account management and authentication into your data transfer.
Automatic Retry
Failed syncs are retried with exponential backoffs.
What makes the Sync Adapter?
There are three components that makes up the SyncAdapter..
1.A Content-provider that extends ContentProvider.
2. An Adapter that extends AbstractThreadedSyncAdapter.
3. A Service that extends Service – this links the content provider with the sync adapter
The Content- provider and the Service need to be declared in AndroidManifest.xml.
For example the declaration will look like this…
<provider android:name="MyContentProvider" android:authorities="@string/content_authority" android:exported="false" android:label="MyContentProvider" android:syncable="true" /> <service android:name="AuthenticatorService" android:exported="true" android:process=":auth" > <intent-filter> <action android:name="android.accounts.AccountAuthenticator" /> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> </service> <service android:name="SyncService" android:exported="true" android:process=":sync" > <intent-filter> <action android:name="android.content.SyncAdapter" /> </intent-filter> <meta-data android:name="android.content.SyncAdapter" android:resource="@xml/sync_adapter" /> </service>
Now create a folder inside the “res” folder named “xml” and create two xmls, one for the autheticator and other for the Adapter.
authenticator.xml
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="@string/auth_type" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:smallIcon="@drawable/ic_launcher" />
sync_adapter.xml
<?xml version="1.0" encoding="utf-8"?> <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" android:contentAuthority="@string/content_authority" android:accountType="@string/auth_type" android:userVisible="true" android:allowParallelSyncs="true" android:isAlwaysSyncable="true" android:supportsUploading="false"/>
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Android Account Authenticator</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="auth_type">com.coderzheaven.auth_example</string> <string name="content_authority">com.coderzheaven.mycont_provider</string> </resources>
NOTE : The “android:authorities” in the Provider Declaration and “android:contentAuthority” in the Sync Adapter should match.
That is why I put it in the strings.xml and gave a common name.
Authority is the string which establishes the relationship among the service, content provider and sync adapter.
In the above example “com.coderzheaven.mycont_provider”.
To Start Sync.
ContentResolver.requestSync(account, authority, bundle);
The account should be valid.
For periodic Syncing.
ContentResolver.addPeriodicSync (account, authority, extras,frequency)
When you request Sync, the System may not start the Syncing immediately, because it will wait for the best battery performance.
Sync Immediately.
If we want to Sync immediately…
Bundle bundle = new Bundle(); //Set below two flags bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); ContentResolver.requestSync(account, authority, bundle);
NOTE : Periodic syncs are not allowed to have any of SYNC_EXTRAS_DO_NOT_RETRY, SYNC_EXTRAS_IGNORE_BACKOFF,
SYNC_EXTRAS_IGNORE_SETTINGS, SYNC_EXTRAS_INITIALIZE, SYNC_EXTRAS_FORCE,SYNC_EXTRAS_EXPEDITED, SYNC_EXTRAS_MANUAL set to true.
If any are supplied then an IllegalArgumentException will be thrown.
if we request an immediate sync when another sync is already in progress, then sync would be retried after 10 seconds.
NOTE : In Some devices Periodic Sync will not work unless “Auto-Sync” is turned on.
Full Source code that implements Android Authenticator and Sync Adapter is available here.
Please leave your valuable comments below.