Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use one SyncAdapter-class for multiple authorities?

I want to reuse my SyncAdapter for multiple authorities. The Method onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) passes the authority as parameter. But how can I register it this way?

I started with following in the AndroidManifest.xml:

<service
    android:name=".sync.SyncService" >
    <intent-filter>
        <action android:name="android.content.SyncAdapter" />
    </intent-filter>

    <meta-data
        android:name="android.content.SyncAdapter"
        android:resource="@xml/syncadapter1" />
</service>

I tried different ways to register @xml/syncadapter2 without success. any ideas to achieve that without derived SyncAdapter-classes for each authority?

like image 708
oleh Avatar asked Sep 20 '12 10:09

oleh


2 Answers

This question was posed months ago, but I'd like to answer anyway...

onPerformSync() is called when a new SyncThread is spun up to perform the sync operation. Each SyncAdapter spins up a SyncThread that is bound to the authority defined in sync-adapter.xml, and multiple authorities cannot be defined in this xml file.

The AbstractThreadedSyncAdapter (the SyncAdapter super class) was simply not written to handle multiple authorities. It contains a final ISyncAdapterImpl class that was implemented as a Singleton, so every time startSync() is called, a sync will occur using the same authority.

Alternatively, were you initially trying to add @xml/syncadapter2 as additional meta-data within the SyncService? This is equivalent to registering multiple SyncAdapters to a single SyncService. It's technically doable (as you can define more than one meta-data tag within a service tag) however the OS itself is the culprit calling service.onBind(Intent intent) on your service when it goes to run a synchronization, and you cannot easily control the intent it passes. If you could control it, you could put a key in the intent's bundle that would determine which of your registered syncAdapters to bind. And even that seems tough.

All that said, it would be less effort to implement different SyncAdapters for each authority (also with their own service), and abstract similar operations into a Utility class that get called in onPerformSync(). This strategy is more maintainable in the long run anyway, because if one of the ContentProviders needed to be removed, it will be easier to remove its corresponding SyncAdapter and SyncService.

like image 122
kianatennyson Avatar answered Oct 31 '22 22:10

kianatennyson


I am not really sure this is a correct answer.

  1. onBind has nothing to do with an authority with which a sync adapter is associated. It just should return an interface which caller will use to communicate with the service.
  2. The service implementation (which provides an interface) is responsible for understanding what is an authority to be synchronized. This is done in the call onPerformSync.
  3. Implementation which derives from the AbstractThreadedSyncAdapter must be thread safe because it may be called for every sync.

So, it is not about "impossible" but about correct implementation of the service. Implementing several sync adapters in one service would be equivalent to registering several adapters just by switching inside implementation by the authority.

like image 34
LeonidVlad Avatar answered Oct 31 '22 22:10

LeonidVlad