I have the following scenario.
I use a SyncAdapter in my app to download data from a server.
When the user opens the app I call requestSync()
to make sure the latest data are available.
When the user requests it I call again requestSync()
passing a bundle of the specific datum I want to download.
The problem is the following:
I can use a SyncStatusObserver
to get notified about the status of the download, but that will not tell me which sync is completed:
For example:
at app start I start a "Total" sync,
then the user requests a refresh on a specific datum, hence I launch a "Specific sync of datum foo",
the SyncStatusObserver
will tell me that a sync is pending/active, but won't tell me if that is the "Total" sync or the "Specific sync of datum foo"
How can i do it?
Is intent broadcast the only way?
SyncStatusObserver
won't tell you that, but there are multiple ways to accomplish that and it depends a lot on your architecture.
Here's one that works for us:
We're planning to let our SyncAdapter
return another IBinder
and return that one when binding our SyncService
with a specific action. This IBinder
object will provide information about the current status of the sync adapter. This works because there's only one instance of a sync service and our sync service holds exactly one instance of the sync adapter.
Here's a quick example:
At present the onBind(Intent)
method of our sync service looks like this:
@Override
public IBinder onBind(Intent intent)
{
return sSyncAdapter.getSyncAdapterBinder();
}
Where sSyncAdapter
is a static instance of our sync adapter.
We're planing to change that to something like this:
public final static ACTION_SYNC_INFO = "com.example.SYNC_INFO";
@Override
public IBinder onBind(Intent intent)
{
if (ACTION_SYNC_INFO.equals(intent.getAction())
{
// sync info binder has been requested
return sSyncAdapter.getSyncInfoBinder();
}
// otherwise return the sync adapter binder
return sSyncAdapter.getSyncAdapterBinder();
}
In our activity we bind our sync service and set the action SyncService.ACTION_SYNC_INFO
. That tells the sync service to return the sync info binder instead of the sync adapter binder.
The binder will have an interface that could look like this:
public interface SyncInfoBinder extends IBinder
{
public boolean isTotalSync();
}
Of course, the sync adapter still needs to implement this method which (in your case) could look like this:
private abstract class AbstractSyncInfoBinder extends Binder implements SyncInfoBinder
{
}
private final IBinder mSyncInfoBinder = new AbstractSyncInfoBinder()
{
@Override
public boolean isTotalSync()
{
// return some field that was set by your onPerformSync method
return mCurrentSyncIsTotalSync;
}
}
public IBinder getSyncInfoBinder()
{
return mSyncInfoBinder
}
Of course that only works this easily if your sync adapter is set to be single threaded. For multi-threaded sync adapters you have to take additional steps to make sure you get the status of all ongoing syncs.
In any case this is a nice way of getting live results from the sync adapter to present them in your UI.