What are Android SyncAdapter contentAuthority and

2019-04-28 12:17发布

问题:

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?

回答1:

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.



回答2:

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"/>