| Joe Malin | c355a1c | 2013-06-07 13:38:00 -0700 | [diff] [blame] | 1 | page.title=Creating a Stub Authenticator |
| 2 | |
| 3 | trainingnavtop=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 | */ |
| 77 | public class Authenticator extends AbstractAccountAuthenticator { |
| 78 | // Simple constructor |
| 79 | public Authenticator(Context context) { |
| 80 | super(context); |
| 81 | } |
| 82 | // Editing properties is not supported |
| 83 | @Override |
| 84 | public Bundle editProperties( |
| 85 | AccountAuthenticatorResponse r, String s) { |
| 86 | throw new UnsupportedOperationException(); |
| 87 | } |
| 88 | // Don't add additional accounts |
| 89 | @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 | @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 | @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 | @Override |
| 117 | public String getAuthTokenLabel(String s) { |
| 118 | throw new UnsupportedOperationException(); |
| 119 | } |
| 120 | // Updating user credentials is not supported |
| 121 | @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 | @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 | */ |
| 157 | public class AuthenticatorService extends Service { |
| 158 | ... |
| 159 | // Instance field that stores the authenticator object |
| 160 | private Authenticator mAuthenticator; |
| 161 | @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 | @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><account-authenticator></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> |
| Joe Malin | a624137 | 2013-07-08 15:37:34 -0700 | [diff] [blame] | 238 | <pre> |
| Joe Malin | c355a1c | 2013-06-07 13:38:00 -0700 | [diff] [blame] | 239 | <?xml version="1.0" encoding="utf-8"?> |
| 240 | <account-authenticator |
| 241 | xmlns:android="http://schemas.android.com/apk/res/android" |
| 242 | android:accountType="example.com" |
| 243 | android:icon="@drawable/ic_launcher" |
| 244 | android:smallIcon="@drawable/ic_launcher" |
| 245 | android:label="@string/app_name"/> |
| 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"><service></a></code> |
| 254 | element as a child element of |
| 255 | <code><a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code>: |
| 256 | </p> |
| 257 | <pre> |
| 258 | <service |
| 259 | android:name="com.example.android.syncadapter.AuthenticatorService"> |
| 260 | <intent-filter> |
| 261 | <action android:name="android.accounts.AccountAuthenticator"/> |
| 262 | </intent-filter> |
| 263 | <meta-data |
| 264 | android:name="android.accounts.AccountAuthenticator" |
| 265 | android:resource="@xml/authenticator" /> |
| 266 | </service> |
| 267 | </pre> |
| 268 | <p> |
| 269 | The |
| 270 | <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></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"><meta-data></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> |