One of the really neat things that Google has done with all of its Android applications is that they all share a common authentication mechanism in Accounts and Sync. There is no need to enter your Google credentials for each Google based application on your device, which centralizes password changes to a single location. It also groups those common authentication applications together in the Accounts and Sync settings activity, as I'm sure everyone is familiar with:
For CapTech, we have several internal Android applications under development and we too wanted to employ this single mechanism to support multiple accounts paradigm in use by Google. How to do it is in the documentation, but I had to hunt for it a bit. How you obtain the token in the authentication mechanism and how you use that token in your service call is out of scope for this prescription. However, this prescription will show you how to tie all these pieces together:
1. Create your authenticator (out of scope for this). Consult a previous blog I have on this subject for that prescription.
2. In the manifest for the application containing the authentication mechanism, alter the sharedUserId and put a static value. Here, we'll use com.captechventures.mobile.
<> xmlns:android="http://schemas.android.com/apk/res/android" package="com.captechventures.android.authenticator" android:versionCode="1" android:versionName="1.0.0" android:sharedUserId="com.captechventures.mobile">
3. In the authenticator descriptor (authenticator.xml in my example), add an label to give the grouping of accounts a generic name. While not necessary, this will allow you to name the account something other than the name of the application it's installed with (default behavior).
<> xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="com.captechventures.mobile" android:icon="@drawable/icon" android:smallIcon="@drawable/icon" android:label="@string/auth_token_label" />
4. Create the 2nd (or 3rd, 4th, etc) application that needs to leverage that authentication mechanism with a sync adapter. Follow the prescription outlined in step 1, however skip the steps to create the authentication mechanism. You're still going to need a SyncAdapter.
5. In the sync adapter descriptor (syncadapter.xml in my example), specify the same account as defined by the authentication mechanism created in step #1 in the accountType attribute.
<> xmlns:android="http://schemas.android.com/apk/res/android" android:contentAuthority="com.captechventures.test.hc1" android:accountType="com.captechventures.mobile" android:supportsUploading="false" />
6. In the 2nd application's manifest, specify a sharedUserId value and use the same value that was used in step #2. Optionally, provide a sharedUserLabel as this will be the name of your application under the account grouping.
<> xmlns:android="http://schemas.android.com/apk/res/android" package="com.captechventures.test.hc1" android:versionCode="1" android:versionName="1.0" android:sharedUserId="com.captechventures.mobile" android:sharedUserLabel="@string/app_name"> <> android:minSdkVersion="8" />
7. When ready to publish your application, you must sign your 2nd application with the same certificate used to sign your first app. Without signing your application, Android will not allow your two apps to share resources (which you've specified you'd like to do with the same sharedUserId attribute in the manifest).
You now have 2 applications that can share/use the same authentication mechanism to your back end services! This makes credential management much easier on the user of your apps. A couple of points to remember:
1. When you request a sync with a content resolver, you MUST provide the Account with the appropriate accountType created in step 1 in the API call.
2. Clients are responsible for identifying if the authentication token is invalid, by making an API call to the AccountManager.
3. The 2nd application requires that the 1st application be installed on the device for it work. You should install the authenticator with an application that will always be on your users' devices or think of breaking that mechanism out into its own application.