Breaking down Google's SampleSyncAdapter

Kyle Miller explains how various pieces in Google's SampleSyncAdapter project fit together, so you can write your own custom sync provider.

In Android 2.0 Google introduced APIs that allowed third-party developers to create their own custom synchronization providers for content providers such as contacts, calendar, etc. As part of the SDK, Google created a SampleSyncAdapter project that you can use for reference, but I found the documentation to be lacking. So with the goal of helping out my fellow Android developers, I decided that I would walk through Google's sample project and explain how various pieces fit together and how it all works.

Getting started

I encourage you to download the source code, compile it, and test it out on a device. When I did this (I used the SDK 14 sample version), the first thing I noticed was that this app has no launcher icon in the app drawer. The reason why is because the Sync provider can be set up through the Accounts & Sync system settings, which is where you'll have to choose the Add Account button in order to add the new account type enabled by the app you installed. In this case, the account type is called Sample SyncAdapter. After you select this account type, you'll be prompted with a login dialog to enter a username and password. It should already be prefilled, so just click Sign In. After that, you should see a new item for the Account you added in the list of existing Accounts, and you can click on it to view and alter its Preferences.

Getting your app to show up in the list of Sync Providers

The first question I had after I demoed the sample was "how did they get their app in the list of options to choose from when I try to add a new Account type?" It turns out this is accomplished by an intent-filter in the Manifest that is defined for the AuthenticationService class:



android:name="android.accounts.AccountAuthenticator" />



When your app is selected from the list of options when adding an Account, the AuthenticationService is instantiated and its onBind method is called. This AuthenticationService is incredibly simple. The onCreate method instantiates an instance of the Authenticator class:

mAuthenticator = new Authenticator(this);

and the onBind method returns:



The Authenticator class extends the AbstractAccountAuthenticator class. One of the methods it overrides is the addAccount method. In the addAccount method, an Intent is created that will launch the Activity responsible for letting the user enter their credentials. This activity is then placed inside a Bundle object, which gets returned by this method:

final Intent intent = new Intent(mContext, AuthenticatorActivity.class);

intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);

final Bundle bundle = new Bundle();

bundle.putParcelable(AccountManager.KEY_INTENT, intent);

return bundle;

The only other interesting method in this class for the sake of Google's demo is the getAuthToken method. Sync Providers use auth tokens for verification purposes, rather than sending username and password credentials over the wire every time a sync operation is being performed.

The first time the user logs in, an auth token must be generated, which the operating system will then use for every subsequent sync operation (this will be explained in the next section).

This particular method requests the username and password from the account manager and then tries to authenticate it with a remote server. However, the password it requests is not the original password entered by the user, but rather the auth token that was generated and stored upon the first login request (more on this in the next section).

final AccountManager am = AccountManager.get(mContext);

final String password = am.getPassword(account);

if (password != null) {

final String authToken = NetworkUtilities.authenticate(, password);

if (!TextUtils.isEmpty(authToken)) {

final Bundle result = new Bundle();


result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);

result.putString(AccountManager.KEY_AUTHTOKEN, authToken);

return result;




The Authenticator Activity can be used for logging in to the remote server for the first time and validating existing credentials. This activity is what creates the UI you see with the username and password field when you go to add the account for the first time.

When this activity authenticates the user for the first time, it sends the username and password entered by the user to a remote server for authorization. If the user is authorized, the server returns an auth token. This activity then creates a new Account object, storing the username, and the auth token is stored as the password, such that the system is never storing the original password entered by the user. On subsequent authorization attempts to the remote server, this auth key is sent up in lieu of the original password such that as I mentioned before, the original password only had to be sent over the wire one time.


There are also three xml files that are used for configuring the SyncProvider.

  • authenticator.xml is used for setting the account type associated with the sync provider, the icon that is displayed to the end user, and the label for the sync provider in the Accounts list.
  • syncadapter.xml is responsible for setting which content authority the sync provider is interacting with. In this case, it's the contacts (
  • contacts.xml, from what I can tell, is responsible for mapping data from the sync provider to the contacts content provider.


Google's example has more advanced topics (especially in SDK version 14) that I didn't cover in this post, but hopefully now that you have a little bit of knowledge and some sample code, you can easily begin writing your own custom sync provider.