am 8b3c7d0c: am c355a1c1: DOC: Sync Adapters Android Training

* commit '8b3c7d0c8fec82a6ad32abcb7e78416d8513512d':
  DOC: Sync Adapters Android Training
diff --git a/docs/downloads/training/BasicSyncAdapter.zip b/docs/downloads/training/BasicSyncAdapter.zip
new file mode 100644
index 0000000..25aa8bb
--- /dev/null
+++ b/docs/downloads/training/BasicSyncAdapter.zip
Binary files differ
diff --git a/docs/html/training/sync-adapters/creating-authenticator.jd b/docs/html/training/sync-adapters/creating-authenticator.jd
new file mode 100644
index 0000000..1b272e7
--- /dev/null
+++ b/docs/html/training/sync-adapters/creating-authenticator.jd
@@ -0,0 +1,290 @@
+page.title=Creating a Stub Authenticator
+
+trainingnavtop=true
+@jd:body
+
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+    <li>
+        <a href="#CreateAuthenticator">Add a Stub Authenticator Component</a>
+    </li>
+    <li>
+        <a href="#CreateAuthenticatorService">Bind the Authenticator to the Framework</a>
+    </li>
+    <li>
+        <a href="#CreateAuthenticatorFile">Add the Authenticator Metadata File</a>
+    </li>
+    <li>
+        <a href="#DeclareAuthenticator">Declare the Authenticator in the Manifest</a>
+    </li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+    <li>
+        <a href="{@docRoot}guide/components/bound-services.html">Bound Services</a>
+    </li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/BasicSyncAdapter.zip" class="button">Download the sample</a>
+ <p class="filename">BasicSyncAdapter.zip</p>
+</div>
+
+</div>
+</div>
+<p>
+    The sync adapter framework assumes that your sync adapter transfers data between device storage
+    associated with an account and server storage that requires login access. For this reason, the
+    framework expects you to provide a component called an authenticator as part of your sync
+    adapter. This component plugs into the Android accounts and authentication framework and
+    provides a standard interface for handling user credentials such as login information.
+</p>
+<p>
+    Even if your app doesn't use accounts, you still need to provide an authenticator component.
+    If you don't use accounts or server login, the information handled by the authenticator is
+    ignored, so you can provide an authenticator component that contains stub method
+    implementations. You also need to provide a bound {@link android.app.Service} that
+    allows the sync adapter framework to call the authenticator's methods.
+</p>
+<p>
+    This lesson shows you how to define all the parts of a stub authenticator that you need to
+    satisfy the requirements of the sync adapter framework. If you need to provide a real
+    authenticator that handles user accounts, read the reference documentation for
+    {@link android.accounts.AbstractAccountAuthenticator}.
+</p>
+
+<h2 id="CreateAuthenticator">Add a Stub Authenticator Component</h2>
+<p>
+    To add a stub authenticator component to your app, create a class that extends
+    {@link android.accounts.AbstractAccountAuthenticator}, and then stub out the required methods,
+    either by returning {@code null} or by throwing an exception.
+</p>
+<p>
+    The following snippet shows an example of a stub authenticator class:
+</p>
+<pre>
+/*
+ * Implement AbstractAccountAuthenticator and stub out all
+ * of its methods
+ */
+public class Authenticator extends AbstractAccountAuthenticator {
+    // Simple constructor
+    public Authenticator(Context context) {
+        super(context);
+    }
+    // Editing properties is not supported
+    &#64;Override
+    public Bundle editProperties(
+            AccountAuthenticatorResponse r, String s) {
+        throw new UnsupportedOperationException();
+    }
+    // Don't add additional accounts
+    &#64;Override
+    public Bundle addAccount(
+            AccountAuthenticatorResponse r,
+            String s,
+            String s2,
+            String[] strings,
+            Bundle bundle) throws NetworkErrorException {
+        return null;
+    }
+    // Ignore attempts to confirm credentials
+    &#64;Override
+    public Bundle confirmCredentials(
+            AccountAuthenticatorResponse r,
+            Account account,
+            Bundle bundle) throws NetworkErrorException {
+        return null;
+    }
+    // Getting an authentication token is not supported
+    &#64;Override
+    public Bundle getAuthToken(
+            AccountAuthenticatorResponse r,
+            Account account,
+            String s,
+            Bundle bundle) throws NetworkErrorException {
+        throw new UnsupportedOperationException();
+    }
+    // Getting a label for the auth token is not supported
+    &#64;Override
+    public String getAuthTokenLabel(String s) {
+        throw new UnsupportedOperationException();
+    }
+    // Updating user credentials is not supported
+    &#64;Override
+    public Bundle updateCredentials(
+            AccountAuthenticatorResponse r,
+            Account account,
+            String s, Bundle bundle) throws NetworkErrorException {
+        throw new UnsupportedOperationException();
+    }
+    // Checking features for the account is not supported
+    &#64;Override
+    public Bundle hasFeatures(
+        AccountAuthenticatorResponse r,
+        Account account, String[] strings) throws NetworkErrorException {
+        throw new UnsupportedOperationException();
+    }
+}
+</pre>
+<h2 id="CreateAuthenticatorService">Bind the Authenticator to the Framework</h2>
+<p>
+    In order for the sync adapter framework to access your authenticator, you must create a bound
+    Service for it. This service provides an Android binder object that allows the framework
+    to call your authenticator and pass data between the authenticator and the framework.
+</p>
+<p>
+    Since the framework starts this {@link android.app.Service} the first time it needs to
+    access the authenticator, you can also use the service to instantiate the authenticator,
+    by calling the authenticator constructor in the
+    {@link android.app.Service#onCreate Service.onCreate()} method of the service.
+</p>
+<p>
+    The following snippet shows you how to define the bound {@link android.app.Service}:
+</p>
+<pre>
+/**
+ * A bound Service that instantiates the authenticator
+ * when started.
+ */
+public class AuthenticatorService extends Service {
+    ...
+    // Instance field that stores the authenticator object
+    private Authenticator mAuthenticator;
+    &#64;Override
+    public void onCreate() {
+        // Create a new authenticator object
+        mAuthenticator = new Authenticator(this);
+    }
+    /*
+     * When the system binds to this Service to make the RPC call
+     * return the authenticator's IBinder.
+     */
+    &#64;Override
+    public IBinder onBind(Intent intent) {
+        return mAuthenticator.getIBinder();
+    }
+}
+</pre>
+
+<h2 id="CreateAuthenticatorFile">Add the Authenticator Metadata File</h2>
+<p>
+    To plug your authenticator component into the sync adapter and account frameworks, you need to
+    provide these framework with metadata that describes the component. This metadata declares the
+    account type you've created for your sync adapter and declares user interface elements
+    that the system displays if you want to make your account type visible to the user. Declare this
+    metadata in a XML file stored in the {@code /res/xml/} directory in your app project.
+    You can give any name to the file, although it's usually called {@code authenticator.xml}.
+</p>
+<p>
+    This XML file contains a single element <code>&lt;account-authenticator&gt;</code> that
+    has the following attributes:
+</p>
+<dl>
+    <dt>
+        <code>android:accountType</code>
+    </dt>
+    <dd>
+        The sync adapter framework requires each sync adapter to have an account type, in the form
+        of a domain name. The framework uses the account type as part of the sync adapter's
+        internal identification. For servers that require login, the account type along with a
+        user account is sent to the server as part of the login credentials.
+    <p>
+        If your server doesn't require login, you still have to provide an account type. For the
+        value, use a domain name that you control. While the framework uses it to manage your
+        sync adapter, the value is not sent to your server.
+    </p>
+    </dd>
+    <dt>
+        <code>android:icon</code>
+    </dt>
+    <dd>
+        Pointer to a <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a>
+        resource containing an icon. If you make the sync adapter visible by specifying the
+        attribute <code>android:userVisible="true"</code> in <code>res/xml/syncadapter.xml</code>,
+        then you must provide this icon resource. It appears in the <b>Accounts</b> section of
+        the system's Settings app.
+    </dd>
+    <dt>
+        <code>android:smallIcon</code>
+    </dt>
+    <dd>
+        Pointer to a <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a>
+        resource containing a small version of the icon. This resource may be used instead of
+        <code>android:icon</code> in the <b>Accounts</b> section of the system's Settings app,
+        depending on the screen size.
+    </dd>
+    <dt>
+        <code>android:label</code>
+    </dt>
+    <dd>
+        Localizable string that identifies the account type to users. If you make the sync adapter
+        visible by specifying the attribute <code>android:userVisible="true"</code> in
+        <code>res/xml/syncadapter.xml</code>, then you should provide this string. It appears in the
+        <b>Accounts</b> section of the system's Settings app, next to the icon you define for the
+        authenticator.
+    </dd>
+</dl>
+<p>
+    The following snippet shows the XML file for the authenticator you created previously:
+</p>
+<pre>the
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;account-authenticator
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:accountType="example.com"
+        android:icon="&#64;drawable/ic_launcher"
+        android:smallIcon="&#64;drawable/ic_launcher"
+        android:label="&#64;string/app_name"/&gt;
+</pre>
+
+<h2 id="DeclareAuthenticator">Declare the Authenticator in the Manifest</h2>
+<p>
+    In a previous step, you created a bound {@link android.app.Service} that links the authenticator
+    to the sync adapter framework. To identify this service to the system, declare it in your app
+    manifest by adding the following
+    <code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
+    element as a child element of
+<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>:
+</p>
+<pre>
+    &lt;service
+            android:name="com.example.android.syncadapter.AuthenticatorService"&gt;
+        &lt;intent-filter&gt;
+            &lt;action android:name="android.accounts.AccountAuthenticator"/&gt;
+        &lt;/intent-filter&gt;
+        &lt;meta-data
+            android:name="android.accounts.AccountAuthenticator"
+            android:resource="@xml/authenticator" /&gt;
+    &lt;/service&gt;
+</pre>
+<p>
+    The
+<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
+    element sets up a filter that's triggered by the intent action
+    {@code android.accounts.AccountAuthenticator}, which sent by the system to run the
+    authenticator. When the filter is triggered, the system starts {@code AuthenticatorService},
+    the bound {@link android.app.Service} you have provided to wrap the authenticator.
+</p>
+<p>
+    The
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
+    element declares the metadata for the authenticator. The
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
+    attribute links the meta-data to the authentication framework. The
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#rsrc">android:resource</a></code>
+    element specifies the name of the authenticator metadata file you created previously.
+</p>
+<p>
+    Besides an authenticator, a sync adapter also requires a content provider. If your app doesn't
+    use a content provider already, go to the next lesson to learn how to create a stub content
+    provider; otherwise, go to the lesson <a href="creating-sync-adapter.html"
+    >Creating a Sync Adapter</a>.
+</p>
diff --git a/docs/html/training/sync-adapters/creating-stub-provider.jd b/docs/html/training/sync-adapters/creating-stub-provider.jd
new file mode 100644
index 0000000..8f6eba0
--- /dev/null
+++ b/docs/html/training/sync-adapters/creating-stub-provider.jd
@@ -0,0 +1,203 @@
+page.title=Creating a Stub Content Provider
+
+trainingnavtop=true
+@jd:body
+
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+    <li>
+        <a href="#CreateProvider">Add a Stub Content Provider</a>
+    </li>
+    <li>
+        <a href="#DeclareProvider">Declare the Provider in the Manifest</a>
+    </li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-provider-basics.html"
+        >Content Provider Basics</a>
+    </li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/BasicSyncAdapter.zip" class="button">Download the sample</a>
+ <p class="filename">BasicSyncAdapter.zip</p>
+</div>
+
+</div>
+</div>
+<p>
+    The sync adapter framework is designed to work with device data managed by the flexible and
+    highly secure content provider framework. For this reason, the sync adapter framework expects
+    that an app that uses the framework has already defined a content provider for its local data.
+    If the sync adapter framework tries to run your sync adapter, and your app doesn't have a
+    content provider, your sync adapter crashes.
+</p>
+<p>
+    If you're developing a new app that transfers data from a server to the device, you should
+    strongly consider storing the local data in a content provider. Besides their importance for
+    sync adapters, content providers offer a variety of security benefits and are specifically
+    designed to handle data storage on Android systems. To learn more about creating a content
+    provider, see <a href="{@docRoot}guide/topics/providers/content-provider-creating.html"
+    >Creating a Content Provider</a>.
+</p>
+<p>
+    However, if you're already storing local data in another form, you can still use a sync
+    adapter to handle data transfer. To satisfy the sync adapter framework requirement for a
+    content provider, add a stub content provider to your app. A stub provider implements the
+    content provider class, but all of its required methods return {@code null} or {@code 0}. If you
+    add a stub provider, you can then use a sync adapter to transfer data from any storage
+    mechanism you choose.
+</p>
+<p>
+    If you already have a content provider in your app, you don't need a stub content provider.
+    In that case, you can skip this lesson and proceed to the lesson
+    <a href="creating-sync-adapter.html">Creating a Sync Adapter</a>. If you don't yet have a
+    content provider, this lesson shows you how to add a stub content provider that allows you to
+    plug your sync adapter into the framework.
+</p>
+<h2 id="CreateProvider">Add a Stub Content Provider</h2>
+<p>
+    To create a stub content provider for your app, extend the class
+    {@link android.content.ContentProvider} and stub out its required methods. The following
+    snippet shows you how to create the stub provider:
+</p>
+<pre>
+/*
+ * Define an implementation of ContentProvider that stubs out
+ * all methods
+ */
+public class StubProvider extends ContentProvider {
+    /*
+     * Always return true, indicating that the
+     * provider loaded correctly.
+     */
+    &#64;Override
+    public boolean onCreate() {
+        return true;
+    }
+    /*
+     * Return an empty String for MIME type
+     */
+    &#64;Override
+    public String getType() {
+        return new String();
+    }
+    /*
+     * query() always returns no results
+     *
+     */
+    &#64;Override
+    public Cursor query(
+            Uri uri,
+            String[] projection,
+            String selection,
+            String[] selectionArgs,
+            String sortOrder) {
+        return null;
+    }
+    /*
+     * insert() always returns null (no URI)
+     */
+    &#64;Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+    /*
+     * delete() always returns "no rows affected" (0)
+     */
+    &#64;Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+    /*
+     * update() always returns "no rows affected" (0)
+     */
+    public int update(
+            Uri uri,
+            ContentValues values,
+            String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+}
+</pre>
+<h2 id="DeclareProvider">Declare the Provider in the Manifest</h2>
+<p>
+    The sync adapter framework verifies that your app has a content provider by checking that your
+    app has declared a provider in its app manifest. To declare the stub provider in the
+    manifest, add a <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
+    >&lt;provider&gt;</a></code> element with  the following attributes:
+</p>
+<dl>
+    <dt>
+        <code>android:name="com.example.android.datasync.provider.StubProvider"</code>
+    </dt>
+    <dd>
+        Specifies the fully-qualified name of the class that implements the stub content provider.
+    </dd>
+    <dt>
+        <code>android:authorities="com.example.android.datasync.provider"</code>
+    </dt>
+    <dd>
+        A URI authority that identifies the stub content provider. Make this value your app's
+        package name with the string ".provider" appended to it. Even though you're declaring your
+        stub provider to the system, nothing tries to access the provider itself.
+   </dd>
+    <dt>
+        <code>android:exported="false"</code>
+    </dt>
+    <dd>
+        Determines whether other apps can access the content provider. For your stub content
+        provider, set the value to {@code false}, since there's no need to allow other apps to see
+        the provider. This value doesn't affect the interaction between the sync adapter framework
+        and the content provider.
+    </dd>
+    <dt>
+        <code>android:syncable="true"</code>
+    </dt>
+    <dd>
+        Sets a flag that indicates that the provider is syncable. If you set this flag to
+        {@code true}, you don't have to call {@link android.content.ContentResolver#setIsSyncable
+        setIsSyncable()} in your code. The flag allows the sync adapter framework to make data
+        transfers with the content provider, but transfers only occur if you do them explicitly.
+    </dd>
+</dl>
+<p>
+    The following snippet shows you how to add the
+    <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
+    >&lt;provider&gt;</a></code> element to the app manifest:
+</p>
+<pre>
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.network.sync.BasicSyncAdapter"
+    android:versionCode="1"
+    android:versionName="1.0" &gt;
+    &lt;application
+        android:allowBackup="true"
+        android:icon="&#64;drawable/ic_launcher"
+        android:label="&#64;string/app_name"
+        android:theme="&#64;style/AppTheme" &gt;
+    ...
+    &lt;provider
+        android:name="com.example.android.datasync.provider.StubProvider"
+        android:authorities="com.example.android.datasync.provider"
+        android:export="false"
+        android:syncable="true"/&gt;
+    ...
+    &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+<p>
+    Now that you have created the dependencies required by the sync adapter framework, you can
+    create the component that encapsulates your data transfer code. This component is called a
+    sync adapter. The next lesson shows you how to add this component to your app.
+</p>
diff --git a/docs/html/training/sync-adapters/creating-sync-adapter.jd b/docs/html/training/sync-adapters/creating-sync-adapter.jd
new file mode 100644
index 0000000..7c59c8c
--- /dev/null
+++ b/docs/html/training/sync-adapters/creating-sync-adapter.jd
@@ -0,0 +1,658 @@
+page.title=Creating a Sync Adapter
+
+trainingnavtop=true
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+    <li>
+        <a href="#CreateSyncAdapter"
+        >Create the Sync Adapter Class</a>
+    </li>
+    <li>
+        <a href="#CreateSyncAdapterService">Bind the Sync Adapter to the Framework</a>
+    </li>
+    <li>
+        <a href="#CreateAccountTypeAccount"
+        >Add the Account Required by the Framework</a>
+    </li>
+    <li>
+        <a href="#CreateSyncAdapterMetadata">Add the Sync Adapter Metadata File</a>
+    </li>
+    <li>
+        <a href="#DeclareSyncAdapterManifest">Declare the Sync Adapter in the Manifest</a>
+    </li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+    <li>
+        <a href="{@docRoot}guide/components/bound-services.html">Bound Services</a>
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+    </li>
+    <li>
+        <a href="{@docRoot}training/id-auth/custom_auth.html">Creating a Custom Account Type</a>
+    </li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/BasicSyncAdapter.zip" class="button">Download the sample</a>
+ <p class="filename">BasicSyncAdapter.zip</p>
+</div>
+
+</div>
+</div>
+<p>
+    The sync adapter component in your app encapsulates the code for the tasks that transfer
+    data between the device and a server. Based on the scheduling and triggers you provide in
+    your app, the sync adapter framework runs the code in the sync adapter component. To add a
+    sync adapter component to your app, you need to add the following pieces:
+<dl>
+    <dt>
+        Sync adapter class.
+    </dt>
+    <dd>
+        A class that wraps your data transfer code in an interface compatible with the sync adapter
+        framework.
+    </dd>
+    <dt>
+        Bound {@link android.app.Service}.
+    </dt>
+    <dd>
+        A component that allows the sync adapter framework to run the code in your sync adapter
+        class.
+    </dd>
+    <dt>
+        Sync adapter XML metadata file.
+    </dt>
+    <dd>
+        A file containing information about your sync adapter. The framework reads this file to
+        find out how to load and schedule your data transfer.
+    </dd>
+    <dt>
+        Declarations in the app manifest.
+    </dt>
+    <dd>
+        XML that declares the bound service and points to sync adapter-specific metadata.
+    </dd>
+</dl>
+<p>
+    This lesson shows you how to define these elements.
+</p>
+<h2 id="CreateSyncAdapter">Create a Sync Adapter Class</h2>
+<p>
+    In this part of the lesson you learn how to create the sync adapter class that encapsulates the
+    data transfer code. Creating the class includes extending the sync adapter base class, defining
+    constructors for the class, and implementing the method where you define the data transfer
+    tasks.
+</p>
+<h3>Extend the base sync adapter class AbstractThreadedSyncAdapter</h3>
+<p>
+    To create the sync adapter component, start by extending
+    {@link android.content.AbstractThreadedSyncAdapter} and writing its constructors. Use the
+    constructors to run setup tasks each time your sync adapter component is created from
+    scratch, just as you use {@link android.app.Activity#onCreate Activity.onCreate()} to set up an
+    activity. For example, if your app uses a content provider to store data, use the constructors
+    to get a {@link android.content.ContentResolver} instance. Since a second form of the
+    constructor was added in Android platform version 3.0 to support the {@code parallelSyncs}
+    argument, you need to create two forms of the constructor to maintain compatibility.
+</p>
+<p class="note">
+    <strong>Note:</strong> The sync adapter framework is designed to work with sync adapter
+    components that are singleton instances. Instantiating the sync adapter component is covered
+    in more detail in the section
+    <a href="#CreateSyncAdapterService">Bind the Sync Adapter to the Framework</a>.
+</p>
+<p>
+    The following example shows you how to implement
+    {@link android.content.AbstractThreadedSyncAdapter}and its constructors:
+</p>
+<pre style="clear: right">
+/**
+ * Handle the transfer of data between a server and an
+ * app, using the Android sync adapter framework.
+ */
+public class SyncAdapter extends AbstractThreadedSyncAdapter {
+    ...
+    // Global variables
+    // Define a variable to contain a content resolver instance
+    ContentResolver mContentResolver;
+    /**
+     * Set up the sync adapter
+     */
+    public SyncAdapter(Context context, boolean autoInitialize) {
+        super(context, autoInitialize);
+        /*
+         * If your app uses a content resolver, get an instance of it
+         * from the incoming Context
+         */
+        mContentResolver = context.getContentResolver();
+    }
+    ...
+    /**
+     * Set up the sync adapter. This form of the
+     * constructor maintains compatibility with Android 3.0
+     * and later platform versions
+     */
+    public SyncAdapter(
+            Context context,
+            boolean autoInitialize,
+            boolean allowParallelSyncs) {
+        super(context, autoInitialize, allowParallelSyncs);
+        /*
+         * If your app uses a content resolver, get an instance of it
+         * from the incoming Context
+         */
+        mContentResolver = context.getContentResolver();
+        ...
+    }
+</pre>
+<h3>Add the data transfer code to onPerformSync()</h3>
+<p>
+    The sync adapter component does not automatically do data transfer. Instead, it
+    encapsulates your data transfer code, so that the sync adapter framework can run the
+    data transfer in the background, without involvement from your app. When the framework is ready
+    to sync your application's data, it invokes your implementation of the method
+    {@link android.content.AbstractThreadedSyncAdapter#onPerformSync onPerformSync()}.
+</p>
+<p>
+    To facilitate the transfer of data from your main app code to the sync adapter component,
+    the sync adapter framework calls
+    {@link android.content.AbstractThreadedSyncAdapter#onPerformSync onPerformSync()} with the
+    following arguments:
+</p>
+<dl>
+    <dt>
+        Account
+    </dt>
+    <dd>
+        An {@link android.accounts.Account} object associated with the event that triggered
+        the sync adapter. If your server doesn't use accounts, you don't need to use the
+        information in this object.
+    </dd>
+    <dt>
+        Extras
+    </dt>
+    <dd>
+        A {@link android.os.Bundle} containing flags sent by the event that triggered the sync
+        adapter.
+    </dd>
+    <dt>
+        Authority
+    </dt>
+    <dd>
+        The authority of a content provider in the system. Your app has to have access to
+        this provider. Usually, the authority corresponds to a content provider in your own app.
+    </dd>
+    <dt>
+        Content provider client
+    </dt>
+    <dd>
+        A {@link android.content.ContentProviderClient} for the content provider pointed to by the
+        authority argument. A {@link android.content.ContentProviderClient} is a lightweight public
+        interface to a content provider. It has the same basic functionality as a
+        {@link android.content.ContentResolver}. If you're using a content provider to store data
+        for your app, you can connect to the provider with this object. Otherwise, you can ignore
+        it.
+    </dd>
+    <dt>
+        Sync result
+    </dt>
+    <dd>
+        A {@link android.content.SyncResult} object that you use to send information to the sync
+        adapter framework.
+    </dd>
+</dl>
+<p>
+    The following snippet shows the overall structure of
+    {@link android.content.AbstractThreadedSyncAdapter#onPerformSync onPerformSync()}:
+</p>
+<pre>
+    /*
+     * Specify the code you want to run in the sync adapter. The entire
+     * sync adapter runs in a background thread, so you don't have to set
+     * up your own background processing.
+     */
+    &#64;Override
+    public void onPerformSync(
+            Account account,
+            Bundle extras,
+            String authority,
+            ContentProviderClient provider,
+            SyncResult syncResult) {
+    /*
+     * Put the data transfer code here.
+     */
+    ...
+    }
+</pre>
+<p>
+    While the actual implementation of
+    {@link android.content.AbstractThreadedSyncAdapter#onPerformSync onPerformSync()} is specific to
+    your app's data synchronization requirements and server connection protocols, there are a few
+    general tasks your implementation should perform:
+</p>
+<dl>
+    <dt>
+        Connecting to a server
+    </dt>
+    <dd>
+        Although you can assume that the network is available when your data transfer starts, the
+        sync adapter framework doesn't automatically connect to a server.
+    </dd>
+    <dt>
+        Downloading and uploading data
+    </dt>
+    <dd>
+        A sync adapter doesn't automate any data transfer tasks. If you want to download
+        data from a server and store it in a content provider, you have to provide the code that
+        requests the data, downloads it, and inserts it in the provider. Similarly, if you want to
+        send data to a server, you have to read it from a file, database, or provider, and send
+        the necessary upload request. You also have to handle network errors that occur while your
+        data transfer is running.
+    </dd>
+    <dt>
+        Handling data conflicts or determining how current the data is
+    </dt>
+    <dd>
+        A sync adapter doesn't automatically handle conflicts between data on the server and data
+        on the device. Also, it doesn't automatically detect if the data on the server is newer than
+        the data on the device, or vice versa. Instead, you have to provide your own algorithms for
+        handling this situation.
+    </dd>
+    <dt>
+        Clean up.
+    </dt>
+    <dd>
+        Always close connections to a server and clean up temp files and caches at the end of
+        your data transfer.
+    </dd>
+</dl>
+<p class="note">
+    <strong>Note:</strong> The sync adapter framework runs
+    {@link android.content.AbstractThreadedSyncAdapter#onPerformSync onPerformSync()} on a
+    background thread, so you don't have to set up your own background processing.
+</p>
+<p>
+    In addition to your sync-related tasks, you should try to combine your regular
+    network-related tasks and add them to
+    {@link android.content.AbstractThreadedSyncAdapter#onPerformSync onPerformSync()}.
+    By concentrating all of your network tasks in this method, you conserve the battery power that's
+    needed to start and stop the network interfaces. To learn more about making network access more
+    efficient, see the training class <a href="{@docRoot}training/efficient-downloads/index.html"
+    >Transferring Data Without Draining the Battery</a>, which describes several network access
+    tasks you can include in your data transfer code.
+</p>
+<h2 id="CreateSyncAdapterService">Bind the Sync Adapter to the Framework</h2>
+<p>
+    You now have your data transfer code encapsulated in a sync adapter component, but you have
+    to provide the framework with access to your code. To do this, you need to create a bound
+    {@link android.app.Service} that passes a special Android binder object from the sync adapter
+    component to the framework. With this binder object, the framework can invoke the
+    {@link android.content.AbstractThreadedSyncAdapter#onPerformSync onPerformSync()} method and
+    pass data to it.
+</p>
+<p>
+    Instantiate your sync adapter component as a singleton in the
+    {@link android.app.Service#onCreate onCreate()} method of the service. By instantiating
+    the component in {@link android.app.Service#onCreate onCreate()}, you defer
+    creating it until the service starts, which happens when the framework first tries to run your
+    data transfer. You need to instantiate the component in a thread-safe manner, in case the sync
+    adapter framework queues up multiple executions of your sync adapter in response to triggers or
+    scheduling.
+</p>
+<p>
+    For example, the following snippet shows you how to create a class that implements the
+    bound {@link android.app.Service}, instantiates your sync adapter component, and gets the
+    Android binder object:
+</p>
+<pre>
+package com.example.android.syncadapter;
+/**
+ * Define a Service that returns an {@link android.os.IBinder} for the
+ * sync adapter class, allowing the sync adapter framework to call
+ * onPerformSync().
+ */
+public class SyncService extends Service {
+    // Storage for an instance of the sync adapter
+    private static SyncAdapter sSyncAdapter = null;
+    // Object to use as a thread-safe lock
+    private static final Object sSyncAdapterLock = new Object();
+    /*
+     * Instantiate the sync adapter object.
+     */
+    &#64;Override
+    public void onCreate() {
+        /*
+         * Create the sync adapter as a singleton.
+         * Set the sync adapter as syncable
+         * Disallow parallel syncs
+         */
+        synchronized (sSyncAdapterLock) {
+            if (sSyncAdapter == null) {
+                sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
+            }
+        }
+    }
+    /**
+     * Return an object that allows the system to invoke
+     * the sync adapter.
+     *
+     */
+    &#64;Override
+    public IBinder onBind(Intent intent) {
+        /*
+         * Get the object that allows external processes
+         * to call onPerformSync(). The object is created
+         * in the base class code when the SyncAdapter
+         * constructors call super()
+         */
+        return sSyncAdapter.getSyncAdapterBinder();
+    }
+}
+</pre>
+<p class="note">
+    <strong>Note:</strong> To see a more detailed example of a bound service for a sync adapter,
+    see the sample app.
+</p>
+<h2 id="CreateAccountTypeAccount">Add the Account Required by the Framework</h2>
+<p>
+    The sync adapter framework requires each sync adapter to have an account type. You declared
+    the account type value in the section
+    <a href="creating-authenticator.html#CreateAuthenticatorFile"
+    >Add the Authenticator Metadata File</a>. Now you have to set up this account type in the
+    Android system. To set up the account type, add a dummy account that uses the account type
+    by calling {@link android.accounts.AccountManager#addAccountExplicitly addAccountExplicitly()}.
+</p>
+<p>
+    The best place to call the method is in the
+    {@link android.support.v4.app.FragmentActivity#onCreate onCreate()} method of your app's
+    opening activity. The following code snippet shows you how to do this:
+</p>
+<pre>
+public class MainActivity extends FragmentActivity {
+    ...
+    ...
+    // Constants
+    // The authority for the sync adapter's content provider
+    public static final String AUTHORITY = "com.example.android.datasync.provider"
+    // An account type, in the form of a domain name
+    public static final String ACCOUNT_TYPE = "example.com";
+    // The account name
+    public static final String ACCOUNT = "dummyaccount";
+    // Instance fields
+    Account mAccount;
+    ...
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ...
+        // Create the dummy account
+        mAccount = CreateSyncAccount(this);
+        ...
+    }
+    ...
+    /**
+     * Create a new dummy account for the sync adapter
+     *
+     * @param context The application context
+     */
+    public static Account CreateSyncAccount(Context context) {
+        // Create the account type and default account
+        Account newAccount = new Account(
+                ACCOUNT, ACCOUNT_TYPE);
+        // Get an instance of the Android account manager
+        AccountManager accountManager =
+                (AccountManager) context.getSystemService(
+                        ACCOUNT_SERVICE);
+        /*
+         * Add the account and account type, no password or user data
+         * If successful, return the Account object, otherwise report an error.
+         */
+        if (accountManager.addAccountExplicitly(newAccount, null, null))) {
+            /*
+             * If you don't set android:syncable="true" in
+             * in your &lt;provider&gt; element in the manifest,
+             * then call context.setIsSyncable(account, AUTHORITY, 1)
+             * here.
+             */
+        } else {
+            /*
+             * The account exists or some other error occurred. Log this, report it,
+             * or handle it internally.
+             */
+        }
+    }
+    ...
+}
+</pre>
+<h2 id="CreateSyncAdapterMetadata">Add the Sync Adapter Metadata File</h2>
+<p>
+    To plug your sync adapter component into the framework, you need to provide the framework
+    with metadata that describes the component and provides additional flags. The metadata specifies
+    the account type you've created for your sync adapter, declares a content provider authority
+    associated with your app, controls a part of the system user interface related to sync adapters,
+    and declares other sync-related flags. Declare this metadata in a special XML file stored in
+    the {@code /res/xml/} directory in your app project. You can give any name to the file,
+    although it's usually called {@code syncadapter.xml}.
+</p>
+<p>
+    This XML file contains a single XML element <code>&lt;sync-adapter&gt;</code> that has the
+    following attributes:
+</p>
+<dl>
+    <dt><code>android:contentAuthority</code></dt>
+    <dd>
+        The URI authority for your content provider. If you created a stub content provider for
+        your app in the previous lesson <a href="creating-stub-provider.html"
+        >Creating a Stub Content Provider</a>, use the value you specified for the
+        attribute
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#auth">android:authorities</a></code>
+        in the <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
+        >&lt;provider&gt;</a></code> element you added to your app manifest. This attribute is
+        described in more detail in the section
+        <a href="creating-stub-provider.html#DeclareProvider"
+        >Declare the Provider in the Manifest</a>.
+        <br/>
+        If you're transferring data from a content provider to a server with your sync adapter, this
+        value should be the same as the content URI authority you're using for that data. This value
+        is also one of the authorities you specify in the
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#auth">android:authorities</a></code>
+        attribute of the <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
+        >&lt;provider&gt;</a></code> element that declares your provider in your app manifest.
+    </dd>
+    <dt><code>android:accountType</code></dt>
+    <dd>
+        The account type required by the sync adapter framework. The value must be the same
+        as the account type value you provided when you created the authenticator metadata file, as
+        described in the section <a href="creating-authenticator.html#CreateAuthenticatorFile"
+        >Add the Authenticator Metadata File</a>. It's also the value you specified for the
+        constant {@code ACCOUNT_TYPE} in the code snippet in the section
+        <a href="#CreateAccountTypeAccount">Add the Account Required by the Framework</a>.
+    </dd>
+    <dt>Settings attributes</dt>
+    <dd>
+        <dl>
+            <dt>
+                {@code android:userVisible}
+            </dt>
+            <dd>
+                Sets the visibility of the sync adapter's account type. By default, the
+                account icon and label associated with the account type are visible in the
+                <b>Accounts</b> section of the system's Settings app, so you should make your sync
+                adapter invisible unless you have an account type or domain that's easily associated
+                with your app. If you make your account type invisible, you can still allow users to
+                control your sync adapter with a user interface in one of your app's activities.
+            </dd>
+            <dt>
+                {@code android:supportsUploading}
+            </dt>
+            <dd>
+                Allows you to upload data to the cloud. Set this to {@code false} if your app only
+                downloads data.
+            </dd>
+            <dt>
+                {@code android:allowParallelSyncs}
+            </dt>
+            <dd>
+                Allows multiple instances of your sync adapter component to run at the same time.
+                Use this if your app supports multiple user accounts and you want to allow multiple
+                users to transfer data in parallel. This flag has no effect if you never run
+                multiple data transfers.
+            </dd>
+            <dt>
+                {@code android:isAlwaysSyncable}
+            </dt>
+            <dd>
+                Indicates to the sync adapter framework that it can run your sync adapter at any
+                time you've specified. If you want to programmatically control when your sync
+                adapter can run, set this flag to {@code false}, and then call
+                {@link android.content.ContentResolver#requestSync requestSync()} to run the
+                sync adapter. To learn more about running a sync adapter, see the lesson
+                <a href="running-sync-adapter.html">Running a Sync Adapter</a>
+            </dd>
+        </dl>
+    </dd>
+</dl>
+<p>
+    The following example shows the XML for a sync adapter that uses a single dummy account and
+    only does downloads.
+</p>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;sync-adapter
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:contentAuthority="com.example.android.datasync.provider"
+        android:accountType="com.android.example.datasync"
+        android:userVisible="false"
+        android:supportsUploading="false"
+        android:allowParallelSyncs="false"
+        android:isAlwaysSyncable="true"/&gt;
+</pre>
+
+<h2 id="DeclareSyncAdapterManifest">Declare the Sync Adapter in the Manifest</h2>
+<p>
+    Once you've added the sync adapter component to your app, you have to request permissions
+    related to using the component, and you have to declare the bound {@link android.app.Service}
+    you've added.
+</p>
+<p>
+    Since the sync adapter component runs code that transfers data between the network and the
+    device, you need to request permission to access the Internet. In addition, your app needs
+    to request permission to read and write sync adapter settings, so you can control the sync
+    adapter programmatically from other components in your app. You also need to request a
+    special permission that allows your app to use the authenticator component you created
+    in the lesson <a href="creating-authenticator.html">Creating a Stub Authenticator</a>.
+</p>
+<p>
+    To request these permissions, add the following to your app manifest as child elements of
+<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>:
+</p>
+<dl>
+    <dt>
+        {@link android.Manifest.permission#INTERNET android.permission.INTERNET}
+    </dt>
+    <dd>
+        Allows the sync adapter code to access the Internet so that it can download or upload data
+        from the device to a server. You don't need to add this permission again if you were
+        requesting it previously.
+    </dd>
+    <dt>
+{@link android.Manifest.permission#READ_SYNC_SETTINGS android.permission.READ_SYNC_SETTINGS}
+    </dt>
+    <dd>
+        Allows your app to read the current sync adapter settings. For example, you need this
+        permission in order to call {@link android.content.ContentResolver#getIsSyncable
+        getIsSyncable()}.
+    </dd>
+    <dt>
+{@link android.Manifest.permission#WRITE_SYNC_SETTINGS android.permission.WRITE_SYNC_SETTINGS}
+    </dt>
+    <dd>
+        Allows your app to control sync adapter settings. You need this permission in order to
+        set periodic sync adapter runs using {@link android.content.ContentResolver#addPeriodicSync
+        addPeriodicSync()}. This permission is <b>not</b> required to call
+        {@link android.content.ContentResolver#requestSync requestSync()}. To learn more about
+        running the sync adapter, see <a href="running-sync-adapter.html"
+        >Running A Sync Adapter</a>.
+    </dd>
+    <dt>
+{@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS android.permission.AUTHENTICATE_ACCOUNTS}
+    </dt>
+    <dd>
+        Allows you to use the authenticator component you created in the lesson
+        <a href="creating-authenticator.html">Creating a Stub Authenticator</a>.
+    </dd>
+</dl>
+<p>
+    The following snippet shows how to add the permissions:
+</p>
+<pre>
+&lt;manifest&gt;
+...
+    &lt;uses-permission
+            android:name="android.permission.INTERNET"/&gt;
+    &lt;uses-permission
+            android:name="android.permission.READ_SYNC_SETTINGS"/&gt;
+    &lt;uses-permission
+            android:name="android.permission.WRITE_SYNC_SETTINGS"/&gt;
+    &lt;uses-permission
+            android:name="android.permission.AUTHENTICATE_ACCOUNTS"/&gt;
+...
+&lt;/manifest&gt;
+</pre>
+<p>
+    Finally, to declare the bound {@link android.app.Service} that the framework uses to
+    interact with your sync adapter, add the following XML to your app manifest as a child element
+    of <code><a href="{@docRoot}guide/topics/manifest/application-element.html"
+    >&lt;application&gt;</a></code>:
+</p>
+<pre>
+        &lt;service
+                android:name="com.example.android.datasync.SyncService"
+                android:exported="true"
+                android:process=":sync"&gt;
+            &lt;intent-filter&gt;com.example.android.datasync.provider
+                &lt;action android:name="android.content.SyncAdapter"/&gt;
+            &lt;/intent-filter&gt;
+            &lt;meta-data android:name="android.content.SyncAdapter"
+                    android:resource="&#64;xml/syncadapter" /&gt;
+        &lt;/service&gt;
+</pre>
+<p>
+    The
+<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
+    element sets up a filter that's triggered by the intent action
+    {@code android.content.SyncAdapter}, sent by the system to run the sync adapter. When the filter
+    is triggered, the system starts the bound service you've created, which in this example is
+    {@code SyncService}. The attribute
+<code><a href="{@docRoot}guide/topics/manifest/service-element.html#exported">android:exported="true"</a></code>
+    allows processes other than your app (including the system) to access the
+    {@link android.app.Service}. The attribute
+<code><a href="{@docRoot}guide/topics/manifest/service-element.html#proc">android:process=":sync"</a></code>
+    tells the system to run the {@link android.app.Service} in a global shared process named
+    {@code sync}. If you have multiple sync adapters in your app they can share this process,
+    which reduces overhead.
+</p>
+<p>
+    The
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
+    element provides provides the name of the sync adapter metadata XML file you created previously.
+    The
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
+    attribute indicates that this metadata is for the sync adapter framework. The
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#rsrc">android:resource</a></code>
+    element specifies the name of the metadata file.
+</p>
+<p>
+    You now have all of the components for your sync adapter. The next lesson shows you how to
+    tell the sync adapter framework to run your sync adapter, either in response to an event or on
+    a regular schedule.
+</p>
diff --git a/docs/html/training/sync-adapters/index.jd b/docs/html/training/sync-adapters/index.jd
new file mode 100644
index 0000000..1f7977b
--- /dev/null
+++ b/docs/html/training/sync-adapters/index.jd
@@ -0,0 +1,135 @@
+page.title=Transferring Data Using Sync Adapters
+
+trainingnavtop=true
+startpage=true
+
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+<ul>
+    <li>Android 3.0 (API Level 11) or higher</li>
+</ul>
+
+<h2>You should also read</h2>
+<ul>
+    <li>
+        <a href="{@docRoot}guide/components/bound-services.html">Bound Services</a>
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+    </li>
+    <li>
+        <a href="{@docRoot}training/id-auth/custom_auth.html">Creating a Custom Account Type</a>
+    </li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/BasicSyncAdapter.zip" class="button">Download the sample</a>
+ <p class="filename">BasicSyncAdapter.zip</p>
+</div>
+
+</div>
+</div>
+<p>
+    Synchronizing data between an Android device and web servers can make your application
+    significantly more useful and compelling for your users. For example, transferring data to a web
+    server makes a useful backup, and transferring data from a server makes it available to the user
+    even when the device is offline. In some cases, users may find it easier to enter and edit their
+    data in a web interface and then have that data available on their device, or they may want to
+    collect data over time and then upload it to a central storage area.
+</p>
+<p>
+    Although you can design your own system for doing data transfers in your app, you should
+    consider using Android's sync adapter framework. This framework helps manage and automate data
+    transfers, and coordinates synchronization operations across different apps. When you use
+    this framework, you can take advantage of several features that aren't available to data
+    transfer schemes you design yourself:
+</p>
+<dl>
+    <dt>
+        Plug-in architecture
+    </dt>
+    <dd>
+        Allows you to add data transfer code to the system in the form of callable components.
+    </dd>
+    <dt>
+        Automated execution
+    </dt>
+    <dd>
+        Allows you to automate data transfer based on a variety of criteria, including data changes,
+        elapsed time, or time of day. In addition, the system adds transfers that are unable to
+        run to a queue, and runs them when possible.
+    </dd>
+    <dt>
+        Automated network checking
+    </dt>
+    <dd>
+        The system only runs your data transfer when the device has network connectivity.
+    </dd>
+    <dt>
+        Improved battery performance
+    </dt>
+    <dd>
+        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.
+    </dd>
+    <dt>
+        Account management and authentication
+    </dt>
+    <dd>
+        If your app requires user credentials or server login, you can optionally
+        integrate account management and authentication into your data transfer.
+    </dd>
+</dl>
+<p>
+    This class shows you how to create a sync adapter and the bound {@link android.app.Service} that
+    wraps it, how to provide the other components that help you plug the sync adapter into the
+    framework, and how to run the sync adapter to run in various ways.
+</p>
+<p class="note">
+    <strong>Note:</strong> Sync adapters run asynchronously, so you should use them with the
+    expectation that they transfer data regularly and efficiently, but not instantaneously. If
+    you need to do real-time data transfer, you should do it in an {@link android.os.AsyncTask} or
+    an {@link android.app.IntentService}.
+</p>
+<h2>Lessons</h2>
+<dl>
+    <dt>
+        <b><a href="creating-authenticator.html">Creating a Stub Authenticator</a></b>
+    </dt>
+    <dd>
+        Learn how to add an account-handling component that the sync adapter framework expects to be
+        part of your app. This lesson shows you how to create a stub authentication component for
+        simplicity.
+    </dd>
+    <dt>
+        <b><a href="creating-stub-provider.html">Creating a Stub Content Provider</a></b>
+    </dt>
+    <dd>
+        Learn how to add a content provider component that the sync adapter framework expects to be
+        part of your app. This lesson assumes that your app doesn't use a content provider, so it
+        shows you how to add a stub component. If you have a content provider already in your app,
+        you can skip this lesson.
+    </dd>
+    <dt>
+        <b><a href="creating-sync-adapter.html">Creating a Sync Adapter</a></b>
+    </dt>
+    <dd>
+        Learn how to encapsulate your data transfer code in a component that the sync
+        adapter framework can run automatically.
+    </dd>
+    <dt>
+        <b><a href="running-sync-adapter.html">Running a Sync Adapter</a></b>
+    </dt>
+    <dd>
+        Learn how to trigger and schedule data transfers using the sync adapter framework.
+    </dd>
+</dl>
diff --git a/docs/html/training/sync-adapters/running-sync-adapter.jd b/docs/html/training/sync-adapters/running-sync-adapter.jd
new file mode 100644
index 0000000..8fb7e80c
--- /dev/null
+++ b/docs/html/training/sync-adapters/running-sync-adapter.jd
@@ -0,0 +1,524 @@
+page.title=Running a Sync Adapter
+
+trainingnavtop=true
+@jd:body
+
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you how to:</h2>
+<ol>
+    <li><a href="#RunByMessage">Run the Sync Adapter When Server Data Changes</a>
+    <li><a href="#RunDataChange">Run the Sync Adapter When Content Provider Data Changes</a></li>
+    <li><a href="#RunByNetwork">Run the Sync Adapter After a Network Message</a></li>
+    <li><a href="#RunPeriodic">Run the Sync Adapter Periodically</a></li>
+    <li><a href="#RunOnDemand">Run the Sync Adapter On Demand</a></li>
+</ol>
+
+
+<h2>You should also read</h2>
+<ul>
+    <li>
+        <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+    </li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/BasicSyncAdapter.zip" class="button">Download the sample</a>
+ <p class="filename">BasicSyncAdapter.zip</p>
+</div>
+
+</div>
+</div>
+<p>
+    In the previous lessons in this class, you learned how to create a sync adapter component that
+    encapsulates data transfer code, and how to add the additional components that allow you to
+    plug the sync adapter into the system. You now have everything you need to install an app that
+    includes a sync adapter, but none of the code you've seen actually runs the sync adapter.
+</p>
+<p>
+    You should try to run your sync adapter based on a schedule or as the indirect result of some
+    event. For example, you may want your sync adapter to run on a regular schedule, either after a
+    certain period of time or at a particular time of the day. You may also want to run your sync
+    adapter when there are changes to data stored on the device. You should avoid running your
+    sync adapter as the direct result of a user action, because by doing this you don't get the full
+    benefit of the sync adapter framework's scheduling ability. For example, you should avoid
+    providing a refresh button in your user interface.
+</p>
+<p>
+    You have the following options for running your sync adapter:
+</p>
+<dl>
+    <dt>
+        When server data changes
+    </dt>
+    <dd>
+        Run the sync adapter in response to a message from a server, indicating that server-based
+        data has changed. This option allows you to refresh data from the server to the device
+        without degrading performance or wasting battery life by polling the server.
+    </dd>
+    <dt>When device data changes</dt>
+    <dd>
+        Run a sync adapter when data changes on the device. This option allows you to send
+        modified data from the device to a server, and is especially useful if you need to ensure
+        that the server always has the latest device data. This option is straightforward to
+        implement if you actually store data in your content provider. If you're using a stub
+        content provider, detecting data changes may be more difficult.
+    </dd>
+    <dt>
+        When the system sends out a network message
+    </dt>
+    <dd>
+        Run a sync adapter when the Android system sends out a network message that keeps the
+        TCP/IP connection open; this message is a basic part of the networking framework. Using
+        this option is one way to run the sync adapter automatically. Consider using it in
+        conjunction with interval-based sync adapter runs.
+    </dd>
+    <dt>
+        At regular intervals
+    </dt>
+    <dd>
+        Run a sync adapter after the expiration of an interval you choose, or run it at a certain
+        time every day.
+    </dd>
+    <dt>On demand</dt>
+    <dd>
+        Run the sync adapter in response to a user action. However, to provide the best user
+        experience you should rely primarily on one of the more automated options. By using
+        automated options, you conserve battery and network resources.
+    </dd>
+</dl>
+<p>
+    The rest of this lesson describes each of the options in more detail.
+</p>
+<h2 id="RunByMessage">Run the Sync Adapter When Server Data Changes</h2>
+<p>
+    If your app transfers data from a server and the server data changes frequently, you can use
+    a sync adapter to do downloads in response to data changes. To run the sync adapter, have
+    the server send a special message to a {@link android.content.BroadcastReceiver} in your app.
+    In response to this message, call {@link android.content.ContentResolver#requestSync
+    ContentResolver.requestSync()} to signal the sync adapter framework to run your
+    sync adapter.
+</p>
+<p>
+    <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> (GCM) provides both the
+    server and device components you need to make this messaging system work. Using GCM to trigger
+    transfers is more reliable and more efficient than polling servers for status. While polling
+    requires a {@link android.app.Service} that is always active, GCM uses a
+    {@link android.content.BroadcastReceiver} that's activated when a message arrives. While polling
+    at regular intervals uses battery power even if no updates are available, GCM only sends
+    messages when needed.
+</p>
+<p class="note">
+    <strong>Note:</strong> If you use GCM to trigger your sync adapter via a broadcast to all
+    devices where your app is installed, remember that they receive your message at
+    roughly the same time. This situation can cause multiple instance of your sync adapter to run
+    at the same time, causing server and network overload. To avoid this situation for a broadcast
+    to all devices, you should consider deferring the start of the sync adapter for a period
+    that's unique for each device.
+<p>
+    The following code snippet shows you how to run
+    {@link android.content.ContentResolver#requestSync requestSync()} in response to an
+    incoming GCM message:
+</p>
+<pre>
+public class GcmBroadcastReceiver extends BroadcastReceiver {
+    ...
+    // Constants
+    // Content provider authority
+    public static final String AUTHORITY = "com.example.android.datasync.provider"
+    // Account type
+    public static final String ACCOUNT_TYPE = "com.example.android.datasync";
+    // Account
+    public static final String ACCOUNT = "default_account";
+    // Incoming Intent key for extended data
+    public static final String KEY_SYNC_REQUEST =
+            "com.example.android.datasync.KEY_SYNC_REQUEST";
+    ...
+    &#64;Override
+    public void onReceive(Context context, Intent intent) {
+        // Get a GCM object instance
+        GoogleCloudMessaging gcm =
+                GoogleCloudMessaging.getInstance(context);
+        // Get the type of GCM message
+        String messageType = gcm.getMessageType(intent);
+        /*
+         * Test the message type and examine the message contents.
+         * Since GCM is a general-purpose messaging system, you
+         * may receive normal messages that don't require a sync
+         * adapter run.
+         * The following code tests for a a boolean flag indicating
+         * that the message is requesting a transfer from the device.
+         */
+        if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)
+            &amp;&amp;
+            intent.getBooleanExtra(KEY_SYNC_REQUEST)) {
+            /*
+             * Signal the framework to run your sync adapter. Assume that
+             * app initialization has already created the account.
+             */
+            ContentResolver.requestSync(ACCOUNT, AUTHORITY, null);
+            ...
+        }
+        ...
+    }
+    ...
+}
+</pre>
+<h2 id="RunDataChange">Run the Sync Adapter When Content Provider Data Changes</h2>
+<p>
+    If your app collects data in a content provider, and you want to update the server whenever
+    you update the provider, you can set up your app to run your sync adapter automatically. To do
+    this, you register an observer for the content provider. When data in your content provider
+    changes, the content provider framework calls the observer. In the observer, call
+    {@link android.content.ContentResolver#requestSync requestSync()} to tell the framework to run
+    your sync adapter.
+</p>
+<p class="note">
+    <strong>Note:</strong> If you're using a stub content provider, you don't have any data in
+    the content provider and {@link android.database.ContentObserver#onChange onChange()} is
+    never called. In this case, you have to provide your own mechanism for detecting changes to
+    device data. This mechanism is also responsible for calling
+    {@link android.content.ContentResolver#requestSync requestSync()} when the data changes.
+</p>
+<p>
+   To create an observer for your content provider, extend the class
+   {@link android.database.ContentObserver} and implement both forms of its
+   {@link android.database.ContentObserver#onChange onChange()} method.  In
+   {@link android.database.ContentObserver#onChange onChange()}, call
+   {@link android.content.ContentResolver#requestSync requestSync()} to start the sync adapter.
+</p>
+<p>
+   To register the observer, pass it as an argument in a call to
+   {@link android.content.ContentResolver#registerContentObserver registerContentObserver()}. In
+   this call, you also have to pass in a content URI for the data you want to watch. The content
+   provider framework compares this watch URI to content URIs passed in as arguments to
+   {@link android.content.ContentResolver} methods that modify your provider, such as
+   {@link android.content.ContentResolver#insert ContentResolver.insert()}. If there's a match, your
+   implementation of {@link android.database.ContentObserver#onChange ContentObserver.onChange()}
+   is called.
+</p>
+
+<p>
+    The following code snippet shows you how to define a {@link android.database.ContentObserver}
+    that calls {@link android.content.ContentResolver#requestSync requestSync()} when a table
+    changes:
+</p>
+<pre>
+public class MainActivity extends FragmentActivity {
+    ...
+    // Constants
+    // Content provider scheme
+    public static final String SCHEME = "content://";
+    // Content provider authority
+    public static final String AUTHORITY = "com.example.android.datasync.provider";
+    // Path for the content provider table
+    public static final String TABLE_PATH = "data_table";
+    // Account
+    public static final String ACCOUNT = "default_account";
+    // Global variables
+    // A content URI for the content provider's data table
+    Uri mUri;
+    // A content resolver for accessing the provider
+    ContentResolver mResolver;
+    ...
+    public class TableObserver extends ContentObserver {
+        /*
+         * Define a method that's called when data in the
+         * observed content provider changes.
+         * This method signature is provided for compatibility with
+         * older platforms.
+         */
+        &#64;Override
+        public void onChange(boolean selfChange) {
+            /*
+             * Invoke the method signature available as of
+             * Android platform version 4.1, with a null URI.
+             */
+            onChange(selfChange, null);
+        }
+        /*
+         * Define a method that's called when data in the
+         * observed content provider changes.
+         */
+        &#64;Override
+        public void onChange(boolean selfChange, Uri changeUri) {
+            /*
+             * Ask the framework to run your sync adapter.
+             * To maintain backward compatibility, assume that
+             * changeUri is null.
+            ContentResolver.requestSync(ACCOUNT, AUTHORITY, null);
+        }
+        ...
+    }
+    ...
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ...
+        // Get the content resolver object for your app
+        mResolver = getContentResolver();
+        // Construct a URI that points to the content provider data table
+        mUri = new Uri.Builder()
+                  .scheme(SCHEME)
+                  .authority(AUTHORITY)
+                  .path(TABLE_PATH)
+                  .build();
+        /*
+         * Create a content observer object.
+         * Its code does not mutate the provider, so set
+         * selfChange to "false"
+         */
+        TableObserver observer = new TableObserver(false);
+        /*
+         * Register the observer for the data table. The table's path
+         * and any of its subpaths trigger the observer.
+         */
+        mResolver.registerContentObserver(mUri, true, observer);
+        ...
+    }
+    ...
+}
+</pre>
+<h2 id="RunByNetwork">Run the Sync Adapter After a Network Message</h2>
+<p>
+    When a network connection is available, the Android system sends out a message
+    every few seconds to keep the device's TCP/IP connection open. This message also goes to
+    the {@link android.content.ContentResolver} of each app. By calling
+    {@link android.content.ContentResolver#setSyncAutomatically setSyncAutomatically()},
+    you can run the sync adapter whenever the {@link android.content.ContentResolver}
+    receives the message.
+</p>
+<p>
+    By scheduling your sync adapter to run when the network message is sent, you ensure that your
+    sync adapter is always scheduled to run while the network is available. Use this option if you
+    don't have to force a data transfer in response to data changes, but you do want to ensure
+    your data is regularly updated. Similarly, you can use this option if you don't want a fixed
+    schedule for your sync adapter, but you do want it to run frequently.
+</p>
+<p>
+    Since the method
+    {@link android.content.ContentResolver#setSyncAutomatically setSyncAutomatically()}
+    doesn't disable {@link android.content.ContentResolver#addPeriodicSync addPeriodicSync()}, your
+    sync adapter may be triggered repeatedly in a short period of time. If you do want to run
+    your sync adapter periodically on a regular schedule, you should disable
+    {@link android.content.ContentResolver#setSyncAutomatically setSyncAutomatically()}.
+</p>
+<p>
+    The following code snippet shows you how to configure your
+    {@link android.content.ContentResolver} to run your sync adapter in response to a network
+    message:
+</p>
+<pre>
+public class MainActivity extends FragmentActivity {
+    ...
+    // Constants
+    // Content provider authority
+    public static final String AUTHORITY = "com.example.android.datasync.provider";
+    // Account
+    public static final String ACCOUNT = "default_account";
+    // Global variables
+    // A content resolver for accessing the provider
+    ContentResolver mResolver;
+    ...
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ...
+        // Get the content resolver for your app
+        mResolver = getContentResolver();
+        // Turn on automatic syncing for the default account and authority
+        mResolver.setSyncAutomatically(ACCOUNT, AUTHORITY, true);
+        ...
+    }
+    ...
+}
+</pre>
+<h2 id="RunPeriodic">Run the Sync Adapter Periodically</h2>
+<p>
+    You can run your sync adapter periodically by setting a period of time to wait between runs,
+    or by running it at certain times of the day, or both. Running your sync adapter
+    periodically allows you to roughly match the update interval of your server.
+</p>
+<p>
+    Similarly, you can upload data from the device when your server is relatively idle, by
+    scheduling your sync adapter to run at night. Most users leave their powered on and plugged in
+    at night, so this time is usually available. Moreover, the device is not running other tasks at
+    the same time as your sync adapter. If you take this approach, however, you need to ensure that
+    each device triggers a data transfer at a slightly different time. If all devices run your
+    sync adapter at the same time, you are likely to overload your server and cell provider data
+    networks.
+</p>
+<p>
+    In general, periodic runs make sense if your users don't need instant updates, but expect to
+    have regular updates. Periodic runs also make sense if you want to balance the availability of
+    up-to-date data with the efficiency of smaller sync adapter runs that don't over-use device
+    resources.
+</p>
+<p>
+    To run your sync adapter at regular intervals, call
+    {@link android.content.ContentResolver#addPeriodicSync addPeriodicSync()}. This schedules your
+    sync adapter to run after a certain amount of time has elapsed. Since the sync adapter framework
+    has to account for other sync adapter executions and tries to maximize battery efficiency, the
+    elapsed time may vary by a few seconds. Also, the framework won't run your sync adapter if the
+    network is not available.
+</p>
+<p>
+    Notice that {@link android.content.ContentResolver#addPeriodicSync addPeriodicSync()} doesn't
+    run the sync adapter at a particular time of day. To run your sync adapter at roughly the
+    same time every day, use a repeating alarm as a trigger. Repeating alarms are described in more
+    detail in the reference documentation for {@link android.app.AlarmManager}. If you use the
+    method {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()} to set
+    time-of-day triggers that have some variation, you should still randomize the start time to
+    ensure that sync adapter runs from different devices are staggered.
+</p>
+<p>
+    The method {@link android.content.ContentResolver#addPeriodicSync addPeriodicSync()} doesn't
+    disable {@link android.content.ContentResolver#setSyncAutomatically 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
+    {@link android.content.ContentResolver#addPeriodicSync addPeriodicSync()}; the flags that are
+    not allowed are described in the referenced documentation for
+    {@link android.content.ContentResolver#addPeriodicSync addPeriodicSync()}.
+</p>
+<p>
+    The following code snippet shows you how to schedule periodic sync adapter runs:
+</p>
+<pre>
+public class MainActivity extends FragmentActivity {
+    ...
+    // Constants
+    // Content provider authority
+    public static final String AUTHORITY = "com.example.android.datasync.provider";
+    // Account
+    public static final String ACCOUNT = "default_account";
+    // Sync interval constants
+    public static final long MILLISECONDS_PER_SECOND = 1000L;
+    public static final long SECONDS_PER_MINUTE = 60L;
+    public static final long SYNC_INTERVAL_IN_MINUTES = 60L;
+    public static final long SYNC_INTERVAL =
+            SYNC_INTERVAL_IN_MINUTES *
+            SECONDS_PER_MINUTE *
+            MILLISECONDS_PER_SECOND;
+    // Global variables
+    // A content resolver for accessing the provider
+    ContentResolver mResolver;
+    ...
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ...
+        // Get the content resolver for your app
+        mResolver = getContentResolver();
+        /*
+         * Turn on periodic syncing
+         */
+        ContentResolver.addPeriodicSync(
+                ACCOUNT,
+                AUTHORITY,
+                null,
+                SYNC_INTERVAL);
+        ...
+    }
+    ...
+}
+</pre>
+<h2 id="RunOnDemand">Run the Sync Adapter On Demand</h2>
+<p>
+    Running your sync adapter in response to a user request is the least preferable strategy
+    for running a sync adapter. The framework is specifically designed to conserve battery power
+    when it runs sync adapters according to a schedule. Options that run a sync in response to data
+    changes use battery power effectively, since the power is used to provide new data.
+</p>
+<p>
+    In comparison, allowing users to run a sync on demand means that the sync runs by itself, which
+    is inefficient use of network and power resources. Also, providing sync on demand leads users to
+    request a sync even if there's no evidence that the data has changed, and running a sync that
+    doesn't refresh data is an ineffective use of battery power. In general, your app should either
+    use other signals to trigger a sync or schedule them at regular intervals, without user input.
+</p>
+<p>
+    However, if you still want to run the sync adapter on demand, set the sync adapter flags for a
+    manual sync adapter run, then call
+    {@link android.content.ContentResolver#requestSync ContentResolver.requestSync()}.
+</p>
+<p>
+    Run on demand transfers with the following flags:
+</p>
+<dl>
+    <dt>
+        {@link android.content.ContentResolver#SYNC_EXTRAS_MANUAL SYNC_EXTRAS_MANUAL}
+    </dt>
+    <dd>
+        Forces a manual sync. The sync adapter framework ignores the existing settings,
+        such as the flag set by {@link android.content.ContentResolver#setSyncAutomatically
+        setSyncAutomatically()}.
+    </dd>
+    <dt>
+        {@link android.content.ContentResolver#SYNC_EXTRAS_EXPEDITED SYNC_EXTRAS_EXPEDITED}
+    </dt>
+    <dd>
+        Forces the sync to start immediately. If you don't set this, the system may wait several
+        seconds before running the sync request, because it tries to optimize battery use by
+        scheduling many requests in a short period of time.
+    </dd>
+</dl>
+<p>
+    The following code snippet shows you how to call
+    {@link android.content.ContentResolver#requestSync requestSync()} in response to a button
+    click:
+</p>
+<pre>
+public class MainActivity extends FragmentActivity {
+    ...
+    // Constants
+    // Content provider authority
+    public static final String AUTHORITY =
+            "com.example.android.datasync.provider"
+    // Account type
+    public static final String ACCOUNT_TYPE = "com.example.android.datasync";
+    // Account
+    public static final String ACCOUNT = "default_account";
+    // Instance fields
+    Account mAccount;
+    ...
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ...
+        /*
+         * Create the dummy account. The code for CreateSyncAccount
+         * is listed in the lesson Creating a Sync Adapter
+         */
+
+        mAccount = CreateSyncAccount(this);
+        ...
+    }
+    /**
+     * Respond to a button click by calling requestSync(). This is an
+     * asynchronous operation.
+     *
+     * This method is attached to the refresh button in the layout
+     * XML file
+     *
+     * @param v The View associated with the method call,
+     * in this case a Button
+     */
+    public void onRefreshButtonClick(View v) {
+        ...
+        // Pass the settings flags by inserting them in a bundle
+        Bundle settingsBundle = new Bundle();
+        settingsBundle.putBoolean(
+                ContentResolver.SYNC_EXTRAS_MANUAL, true);
+        settingsBundle.putBoolean(
+                ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+        /*
+         * Request the sync for the default account, authority, and
+         * manual sync settings
+         */
+        ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle);
+    }
+</pre>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 58db404..cb57752 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -475,6 +475,37 @@
           </a>
           </li>
       </li>
+      <li class="nav-section">
+        <div class="nav-section-header">
+          <a href="<?cs var:toroot ?>training/sync-adapters/index.html"
+             description="How to transfer data between the cloud and the device using the Android
+             sync adapter framework"
+             >Transferring Data Using Sync Adapters</a>
+        </div>
+        <ul>
+            <li>
+                <a href="<?cs var:toroot ?>training/sync-adapters/creating-authenticator.html">
+                Creating a Stub Authenticator
+                </a>
+            </li>
+            <li>
+                <a href="<?cs var:toroot ?>training/sync-adapters/creating-stub-provider.html">
+                Creating a Stub Content Provider
+                </a>
+            </li>
+            <li>
+                <a href="<?cs var:toroot ?>training/sync-adapters/creating-sync-adapter.html">
+                Creating a Sync Adapter
+                </a>
+            </li>
+            <li>
+                <a href="<?cs var:toroot ?>training/sync-adapters/running-sync-adapter.html">
+                Running a Sync Adapter
+                </a>
+            </li>
+        </ul>
+      </li>
+
     </ul>
   </li>
   <!-- End connectivity and cloud -->