SyncAdapter: создана учетная запись, requestSync ОК, но setSyncAutomatically не работает

Я только что создал учетную запись для своего приложения.

  • Учетная запись видна в настройках
  • Я установил syncable = "true" в свой XML
  • Я могу выполнить ручную синхронизацию, нажав настройки → onPerformSync называется
  • Я могу выполнить "кодовую" синхронизацию, вызывая ContentResolver.requestSync → onPerformSync называется
  • И, конечно, да, синхронизация включена в настройках. Я не использую энергосбережение.

Я также выполнил все шаги отсюда: qaru.site/info/53206/...

Это мой код, чтобы получить синхронизацию по коду

AccountManager am = AccountManager.get(this); 
Account[] accounts = am.getAccountsByType(ACCOUNT);
//Log.e("DEBUG", "Accounts: " + accounts.length);
if (accounts.length == 0) {
    Account account = new Account(getString(R.string.app_name), ACCOUNT);
    ContentResolver.setIsSyncable(account, AUTHORITY, 1);
    ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), 7200);
    ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
    if (am.addAccountExplicitly(account, "pass1", null))
        Log.i("DEBUG", "account Created: " + account.name + ", " + account.type);
    else
        Log.i("DEBUG", "addAccountExplicitly returned false");
    }
else{
    ContentResolver.requestSync(accounts[0], AUTHORITY, new Bundle());// THIS IS WORKING!!!
    }
}

Итак, все выглядит правильно и прекрасно.

Но, к сожалению, я не могу получить периодическую синхронизацию! Когда я открываю настройки, учетные записи, я вижу учетную запись, а дата и время - это время, когда я выполнял синхронизацию по коду или вручную.

Любая идея о том, что я сделал не так, или что я забыл?

Ответ 1

Rewrite

Я собрал образец проекта на GitHub, который демонстрирует рабочий SyncAdapter. Проект здесь.

Я только пробовал это на эмуляторе с API 17, так как я не хотел ждать около часа или около того (может быть, больше сейчас) для синхронизации. Я бы посоветовал вам воспользоваться этим маршрутом.

В API 17 эта демонстрация будет выполнять синхронизацию каждые 30 секунд или около того. Все заканчивается из основной деятельности с помощью классов поддержки заглушек: SyncAdapter, StubProvider и т.д. Единственное, что делает адаптер синхронизации, - это зарегистрировать сообщение для logcat, которое оно выполнило.

Я действительно не вижу ничего плохого в вашем коде, кроме, может быть, порядок вызовов для настройки синхронизации неверен. Взгляните на порядок вызовов в демонстрационном примере на примере того, что работает.

Надеюсь, вы сочтете это полезным.

(Я сделал это на Android Studio 3.0 Canary 5. Надеюсь, это не проблема.)

Ответ 2

Важно помнить, что периодическое время синхронизации не гарантируется и может быть неточным, это упоминается в документации:

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

Я бы также попытался создать учетную запись с помощью AccountManager, а не путем создания new Account()

 manager.addAccountExplicitly(account, null, null)

И последнее, если эта учетная запись была создана только после того, как вы можете принудительно установить только первую синхронизацию сразу после установки параметров автоматической синхронизации:

 if (accountJustCreated) { 
   SyncAdapter.performSync();
 }