Кто-нибудь реализовал (или получил дополнительную информацию) на Android SyncObserver


Я разрабатываю приложение на Android, которое выполняет фоновую синхронизацию с сервером (используя SyncAdapter и аутентификацию и т. д.).

При запуске приложения переднего плана (с пользовательским интерфейсом), возможно, выполняется фоновая синхронизация, или по желанию она может запускаться с помощью кнопки пользовательского интерфейса.

Я хотел бы иметь возможность "подключаться" к текущей фоновой синхронизации (независимо от того, запускается ли она системой, настройкой периодической синхронизации или пользовательским интерфейсом) и показывать ее прогресс на переднем плане.

Документация ContentResolver (http://developer.android.com/reference/android/content/ContentResolver.html) упоминает таинственный "SyncObserver", который не имеет связи с javadoc и не документирован (что я могу найти).

Есть еще несколько страниц, на которых это упоминается (http://www.chinaup.org/docs/migrating/m5-0.9/changes/android.content.ContentResolver.html) но я не могу узнать об этом больше.

Кто-нибудь реализовал этого зверя?

Если нет, то есть ли у кого-нибудь пример кода или рекомендации по отслеживанию хода выполнения фоновой синхронизации на переднем плане?

2 5

2 ответа:

У меня была та же проблема, и в итоге я реализовал ее с помощью комбинации 1) широковещательной передачи от SyncAdapter и 2) использования SharedPreferences для указания статуса.

В Синкадаптере что-то вроде этого:

public static final String START_SYNC = "com.whatever.sync.start";
public static final String STOP_SYNC = "com.whatever.sync.stop";
public static final String SYNC_PROGRESS = "syncProgress";


public void onPerformSync(Account account, Bundle extras, String authority,
    ContentProviderClient provider, SyncResult syncResult) {

        // Add an integer to the shared settings to indicate the status
        SharedPreferences settings = mContext.getSharedPreferences(Constants.PREFS, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(SyncAdapter.SYNC_PROGRESS, 0);
        editor.commit();

        Intent intent = new Intent();
        intent.setAction(START_SYNC);
        mContext.sendBroadcast(intent);


        //... do some stuff, setting SYNC_PROGRESS to other values and
        // sending more broadcasts as the state changes

        // When we are done, remove the "in progress" setting and store some
        // other data
        editor.putString(SyncAdapter.LAST_UPDATED, new Date().toString());
        editor.remove(SyncAdapter.SYNC_PROGRESS);
        editor.commit();

        Intent stopIntent = new Intent();
        stopIntent.setAction(STOP_SYNC);
        mContext.sendBroadcast(stopIntent); 
      }

В этом упражнении мы делаем две вещи при возобновлении: 1) проверяем общие предпочтения на предмет того, выполняется ли синхронизация в данный момент; 2) регистрируемся для прослушивания радиопередач с приемником.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// .. do some UI stuff

    mReceiver = new SyncReceiver(this);
}

@Override
public void onResume() {
    super.onResume();

    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(SyncAdapter.START_SYNC);
    intentFilter.addAction(SyncAdapter.STOP_SYNC);
    registerReceiver(mReceiver, intentFilter);  

    showProgress();
}

public void showProgress() {
    SharedPreferences settings = getSharedPreferences(Constants.PREFS, 0);
    if (settings.contains(SyncAdapter.SYNC_PROGRESS)) {
        // ... set the UI to show that a sync is in progress
    } else {
        // ... set the UI to show that a sync is NOT in progress
    }
}

private class SyncReceiver extends BroadcastReceiver {

    private MyActivity mActivity;

    public SyncReceiver(MyActivity activity) {
        mActivity = activity;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(SyncAdapter.START_SYNC)) {
            Log.i("@string/app_name", "Started sync");
            mActivity.showProgress();
        }
        else if (intent.getAction().equals(SyncAdapter.STOP_SYNC)) {
            Log.i("@string/app_name", "Started sync");
            mActivity.showProgress();
        }
    }
}
Это, кажется, работает на меня. Должен признаться, у меня такое чувство, что есть некоторые потенциальные проблемы с этим из-за асинхронного характера передач. Любой вклад в улучшение моего подхода будет оценен!

Спасибо за ответ.

Из-за асинхронного характера фоновой синхронизации ваше приложение (действие) может быть запущено с уже выполненной фоновой синхронизацией, которую вы обнаруживаете с сохраненным в предпочтении статусом.

Что я сделал, так это реализовал класс SyncObserver, который реализует интерфейс SyncStatusObserver и создает / уничтожает при приостановке / возобновлении.

syncObserverHandle = ContentResolver.addStatusChangeListener( ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, new SyncObserver() );

Это получает информацию о любом событии, связанном с синхронизацией (ожидание, начало и т. д.), И я также проверяю статус использование

ContentResolver.isSyncActive();
API для Android для этого довольно просты, и вы должны уважать правила о том, что делается в потоке пользовательского интерфейса, а что нет, но если кто-то хочет увидеть мою реализацию, просто напишите вопрос и укажите мне на него, и я с удовольствием отвечу.