I'm creating a custom Android SyncAdapter and hit a snag following the SDK example "SampleSyncAdapter". - I'm creating my equivalent of the xml/syncadapter.xml
. Here's the parts I'm confused about:
android:contentAuthority="com.android.contacts"
android:accountType="com.example.android.samplesync"
The documentation of AbstractThreadedSyncAdapter states:
The android:contentAuthority
and android:accountType
attributes
indicate which content authority and for which account types this sync
adapter serves.
The documentation is circular in that it says nothing the name doesn't already tell you. I get the impression that both will start with my company's name com.acme.
but from there I have no clue. I suspect the strings can be anything, as long as they are globally unique so as not to conflict with any other apps that could be on the same device. I assume this means I will need to use these exact strings elsewhere in my code. However, I'd like to know, where I will need these strings?! I tried to grep for com.android.contacts
and the previously mentioned file is the only place it is used, I can find. So it is impossible to tell how the contentAuthority
is used by looking at the example.
If so, can I put them both in a string resource and reference them in by resource ID where needed? Exactly what are these attributes and how are they used? Is there any better way to figure out what values I should choose for my own application for these and other fields?
To understand what the authority is you need to see the documentation of ContentProvider:
It states: "it identifies the content provider. For third-party applications, this should be a fully-qualified class name (reduced to lowercase) to ensure uniqueness. The authority is declared in the element's authorities attribute"
The account type is an identificator of your Authenticator that will be used for example by the clients of the AccountManager to call getAccountsByType(String)
.
For the SampleSyncAdapter:
android:contentAuthority="com.android.contacts"
android:accountType="com.example.android.samplesync"
android:accountType is the same as that one defined by the authenticator.
So the content-Authority specifies which content provider will be synchronized locally and the accountType specifies which authenticator will be used to access the data remotely.
The accountType is also used to obtain the sync adapter's specific content-uri.
For example when you want to start a sync you need to call requestSync like this:
final Account account = new Account(accountName, ACCOUNT_TYPE);
ContentResolver.requestSync(account, CONTENT_AUTHORITY, new Bundle());
At the same time to build the content-uri for your sync adapter you can use something like:
Uri CONTENT_URI = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName).appendQueryParameter(RawContacts.ACCOUNT_TYPE, SyncAdapter.ACCOUNT_TYPE).build();
Have a look to android-sync-adapter
Meanwhile, the previously mentioned ContentProvider documentation has been revised. The latest version states:
Designing an authority
A provider usually has a single authority, which serves as its
Android-internal name. To avoid conflicts with other providers, you
should use Internet domain ownership (in reverse) as the basis of your
provider authority. Because this recommendation is also true for
Android package names, you can define your provider authority as an
extension of the name of the package containing the provider. For
example, if your Android package name is com.example.<appname>
, you
should give your provider the authority
com.example.<appname>.provider
.
The android:contentAuthority attribute in your SyncAdapter meta data file syncadapter.xml should match the android:authorities attribute for your provider declaration in your Manifest. Make this value your app's package name with the string ".provider" appended to it. This is from Android's developer site http://developer.android.com/training/sync-adapters
So in your Manifest:
<provider
android:name="com.example.android.datasync.provider.StubProvider"
android:authorities="com.example.android.datasync.provider"
android:exported="false"
android:syncable="true"/>
And in your syncadapter.xml
<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"/>