Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07797c45 authored by Joe Malin's avatar Joe Malin Committed by Android Git Automerger
Browse files

am 5c27ec22: am c7d3d28b: am 8b3c7d0c: am c355a1c1: DOC: Sync Adapters Android Training

* commit '5c27ec22':
  DOC: Sync Adapters Android Training
parents eadad05c 5c27ec22
Loading
Loading
Loading
Loading
+2.24 MiB

File added.

No diff preview for this file type.

+290 −0
Original line number Diff line number Diff line
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>
+203 −0
Original line number Diff line number Diff line
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>
+658 −0

File added.

Preview size limit exceeded, changes collapsed.

+135 −0
Original line number Diff line number Diff line
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>
Loading