1page.title=Creating a Stub Authenticator
2
3trainingnavtop=true
4@jd:body
5
6
7<div id="tb-wrapper">
8<div id="tb">
9
10<h2>This lesson teaches you to</h2>
11<ol>
12    <li>
13        <a href="#CreateAuthenticator">Add a Stub Authenticator Component</a>
14    </li>
15    <li>
16        <a href="#CreateAuthenticatorService">Bind the Authenticator to the Framework</a>
17    </li>
18    <li>
19        <a href="#CreateAuthenticatorFile">Add the Authenticator Metadata File</a>
20    </li>
21    <li>
22        <a href="#DeclareAuthenticator">Declare the Authenticator in the Manifest</a>
23    </li>
24</ol>
25
26<h2>You should also read</h2>
27<ul>
28    <li>
29        <a href="{@docRoot}guide/components/bound-services.html">Bound Services</a>
30    </li>
31</ul>
32
33<h2>Try it out</h2>
34
35<div class="download-box">
36 <a href="http://developer.android.com/shareables/training/BasicSyncAdapter.zip" class="button">Download the sample</a>
37 <p class="filename">BasicSyncAdapter.zip</p>
38</div>
39
40</div>
41</div>
42<p>
43    The sync adapter framework assumes that your sync adapter transfers data between device storage
44    associated with an account and server storage that requires login access. For this reason, the
45    framework expects you to provide a component called an authenticator as part of your sync
46    adapter. This component plugs into the Android accounts and authentication framework and
47    provides a standard interface for handling user credentials such as login information.
48</p>
49<p>
50    Even if your app doesn't use accounts, you still need to provide an authenticator component.
51    If you don't use accounts or server login, the information handled by the authenticator is
52    ignored, so you can provide an authenticator component that contains stub method
53    implementations. You also need to provide a bound {@link android.app.Service} that
54    allows the sync adapter framework to call the authenticator's methods.
55</p>
56<p>
57    This lesson shows you how to define all the parts of a stub authenticator that you need to
58    satisfy the requirements of the sync adapter framework. If you need to provide a real
59    authenticator that handles user accounts, read the reference documentation for
60    {@link android.accounts.AbstractAccountAuthenticator}.
61</p>
62
63<h2 id="CreateAuthenticator">Add a Stub Authenticator Component</h2>
64<p>
65    To add a stub authenticator component to your app, create a class that extends
66    {@link android.accounts.AbstractAccountAuthenticator}, and then stub out the required methods,
67    either by returning {@code null} or by throwing an exception.
68</p>
69<p>
70    The following snippet shows an example of a stub authenticator class:
71</p>
72<pre>
73/*
74 * Implement AbstractAccountAuthenticator and stub out all
75 * of its methods
76 */
77public class Authenticator extends AbstractAccountAuthenticator {
78    // Simple constructor
79    public Authenticator(Context context) {
80        super(context);
81    }
82    // Editing properties is not supported
83    &#64;Override
84    public Bundle editProperties(
85            AccountAuthenticatorResponse r, String s) {
86        throw new UnsupportedOperationException();
87    }
88    // Don't add additional accounts
89    &#64;Override
90    public Bundle addAccount(
91            AccountAuthenticatorResponse r,
92            String s,
93            String s2,
94            String[] strings,
95            Bundle bundle) throws NetworkErrorException {
96        return null;
97    }
98    // Ignore attempts to confirm credentials
99    &#64;Override
100    public Bundle confirmCredentials(
101            AccountAuthenticatorResponse r,
102            Account account,
103            Bundle bundle) throws NetworkErrorException {
104        return null;
105    }
106    // Getting an authentication token is not supported
107    &#64;Override
108    public Bundle getAuthToken(
109            AccountAuthenticatorResponse r,
110            Account account,
111            String s,
112            Bundle bundle) throws NetworkErrorException {
113        throw new UnsupportedOperationException();
114    }
115    // Getting a label for the auth token is not supported
116    &#64;Override
117    public String getAuthTokenLabel(String s) {
118        throw new UnsupportedOperationException();
119    }
120    // Updating user credentials is not supported
121    &#64;Override
122    public Bundle updateCredentials(
123            AccountAuthenticatorResponse r,
124            Account account,
125            String s, Bundle bundle) throws NetworkErrorException {
126        throw new UnsupportedOperationException();
127    }
128    // Checking features for the account is not supported
129    &#64;Override
130    public Bundle hasFeatures(
131        AccountAuthenticatorResponse r,
132        Account account, String[] strings) throws NetworkErrorException {
133        throw new UnsupportedOperationException();
134    }
135}
136</pre>
137<h2 id="CreateAuthenticatorService">Bind the Authenticator to the Framework</h2>
138<p>
139    In order for the sync adapter framework to access your authenticator, you must create a bound
140    Service for it. This service provides an Android binder object that allows the framework
141    to call your authenticator and pass data between the authenticator and the framework.
142</p>
143<p>
144    Since the framework starts this {@link android.app.Service} the first time it needs to
145    access the authenticator, you can also use the service to instantiate the authenticator,
146    by calling the authenticator constructor in the
147    {@link android.app.Service#onCreate Service.onCreate()} method of the service.
148</p>
149<p>
150    The following snippet shows you how to define the bound {@link android.app.Service}:
151</p>
152<pre>
153/**
154 * A bound Service that instantiates the authenticator
155 * when started.
156 */
157public class AuthenticatorService extends Service {
158    ...
159    // Instance field that stores the authenticator object
160    private Authenticator mAuthenticator;
161    &#64;Override
162    public void onCreate() {
163        // Create a new authenticator object
164        mAuthenticator = new Authenticator(this);
165    }
166    /*
167     * When the system binds to this Service to make the RPC call
168     * return the authenticator's IBinder.
169     */
170    &#64;Override
171    public IBinder onBind(Intent intent) {
172        return mAuthenticator.getIBinder();
173    }
174}
175</pre>
176
177<h2 id="CreateAuthenticatorFile">Add the Authenticator Metadata File</h2>
178<p>
179    To plug your authenticator component into the sync adapter and account frameworks, you need to
180    provide these framework with metadata that describes the component. This metadata declares the
181    account type you've created for your sync adapter and declares user interface elements
182    that the system displays if you want to make your account type visible to the user. Declare this
183    metadata in a XML file stored in the {@code /res/xml/} directory in your app project.
184    You can give any name to the file, although it's usually called {@code authenticator.xml}.
185</p>
186<p>
187    This XML file contains a single element <code>&lt;account-authenticator&gt;</code> that
188    has the following attributes:
189</p>
190<dl>
191    <dt>
192        <code>android:accountType</code>
193    </dt>
194    <dd>
195        The sync adapter framework requires each sync adapter to have an account type, in the form
196        of a domain name. The framework uses the account type as part of the sync adapter's
197        internal identification. For servers that require login, the account type along with a
198        user account is sent to the server as part of the login credentials.
199    <p>
200        If your server doesn't require login, you still have to provide an account type. For the
201        value, use a domain name that you control. While the framework uses it to manage your
202        sync adapter, the value is not sent to your server.
203    </p>
204    </dd>
205    <dt>
206        <code>android:icon</code>
207    </dt>
208    <dd>
209        Pointer to a <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a>
210        resource containing an icon. If you make the sync adapter visible by specifying the
211        attribute <code>android:userVisible="true"</code> in <code>res/xml/syncadapter.xml</code>,
212        then you must provide this icon resource. It appears in the <b>Accounts</b> section of
213        the system's Settings app.
214    </dd>
215    <dt>
216        <code>android:smallIcon</code>
217    </dt>
218    <dd>
219        Pointer to a <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a>
220        resource containing a small version of the icon. This resource may be used instead of
221        <code>android:icon</code> in the <b>Accounts</b> section of the system's Settings app,
222        depending on the screen size.
223    </dd>
224    <dt>
225        <code>android:label</code>
226    </dt>
227    <dd>
228        Localizable string that identifies the account type to users. If you make the sync adapter
229        visible by specifying the attribute <code>android:userVisible="true"</code> in
230        <code>res/xml/syncadapter.xml</code>, then you should provide this string. It appears in the
231        <b>Accounts</b> section of the system's Settings app, next to the icon you define for the
232        authenticator.
233    </dd>
234</dl>
235<p>
236    The following snippet shows the XML file for the authenticator you created previously:
237</p>
238<pre>
239&lt;?xml version="1.0" encoding="utf-8"?&gt;
240&lt;account-authenticator
241        xmlns:android="http://schemas.android.com/apk/res/android"
242        android:accountType="example.com"
243        android:icon="&#64;drawable/ic_launcher"
244        android:smallIcon="&#64;drawable/ic_launcher"
245        android:label="&#64;string/app_name"/&gt;
246</pre>
247
248<h2 id="DeclareAuthenticator">Declare the Authenticator in the Manifest</h2>
249<p>
250    In a previous step, you created a bound {@link android.app.Service} that links the authenticator
251    to the sync adapter framework. To identify this service to the system, declare it in your app
252    manifest by adding the following
253    <code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
254    element as a child element of
255<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>:
256</p>
257<pre>
258    &lt;service
259            android:name="com.example.android.syncadapter.AuthenticatorService"&gt;
260        &lt;intent-filter&gt;
261            &lt;action android:name="android.accounts.AccountAuthenticator"/&gt;
262        &lt;/intent-filter&gt;
263        &lt;meta-data
264            android:name="android.accounts.AccountAuthenticator"
265            android:resource="@xml/authenticator" /&gt;
266    &lt;/service&gt;
267</pre>
268<p>
269    The
270<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
271    element sets up a filter that's triggered by the intent action
272    {@code android.accounts.AccountAuthenticator}, which sent by the system to run the
273    authenticator. When the filter is triggered, the system starts {@code AuthenticatorService},
274    the bound {@link android.app.Service} you have provided to wrap the authenticator.
275</p>
276<p>
277    The
278<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
279    element declares the metadata for the authenticator. The
280<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
281    attribute links the meta-data to the authentication framework. The
282<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#rsrc">android:resource</a></code>
283    element specifies the name of the authenticator metadata file you created previously.
284</p>
285<p>
286    Besides an authenticator, a sync adapter also requires a content provider. If your app doesn't
287    use a content provider already, go to the next lesson to learn how to create a stub content
288    provider; otherwise, go to the lesson <a href="creating-sync-adapter.html"
289    >Creating a Sync Adapter</a>.
290</p>
291