2013-03-26 3 views
11

Я пытаюсь выяснить, как работает syncAdapter, я использовал примерSync Adapter в качестве примера/отправной точки, и я основывал свой первый тест на нем. Единственное различие заключается в том, что я не работаю с поставщиком контактов по умолчанию, но мне нужен один из моих собственных.SyncAdapter periodicsync() not triggering

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

public void finishLogin(String authToken) { 
    Log.i(TAG, "finishLogin()"); 
    final Account account = new Account(mUsername, "be.company.syncAdapterTest"); 
    if(mRequestNewAccount) { 
     mAccountManager.addAccountExplicitly(account, mPassword, null); 
     ContentResolver.setIsSyncable(account, MY_AUTHORITY, 1); 

     Bundle params = new Bundle(); 
     params.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false); 
     params.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false); 
     params.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);   
     ContentResolver.addPeriodicSync(account, MY_AUTHORITY, params, 30); 
     ContentResolver.setSyncAutomatically(account, MY_AUTHORITY, true); 
     ContentResolver.requestSync(account,MY_AUTHORITY,params); 
    } else { 
     mAccountManager.setPassword(account, mPassword); 
    } 
    final Intent intent = new Intent(); 
    intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, "ACCOUNT_TEST"); 
    intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, "be.company.syncAdapterTest"); 
    setAccountAuthenticatorResult(intent.getExtras()); 
    setResult(RESULT_OK, intent); 
    finish(); 
} 

В методе perfomSync() У меня есть следующий метод:

@Override 
public void onPerformSync(Account account, Bundle extras, String authority, 
     ContentProviderClient provider, SyncResult syncResult) { 
    Log.d(TAG, "onPerformSync() start"); 
    // Testje 
    try { 
     final String authToken = mAccountManager.blockingGetAuthToken(account, "be.company.syncAdapterTest", NOTIFY_AUTH_FAILURE); 
     Log.d(TAG, SAPNetworkUtilities.getWeek(account, authToken, getRandomDate())); 
    } catch (OperationCanceledException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (AuthenticatorException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    Log.d(TAG, "onPerformSync() end"); 
} 

Здесь я просто называю простой SAP WebService и показать его в журнале. Теперь у меня есть два вопроса:

  1. SYNC не запускается автоматически, когда я добавляю свою учетную запись в настройки. Мне нужно войти в учетную запись и установить флажок, чтобы начать синхронизацию?
  2. Синхронизация не запускается каждые 30 секунд в этом примере ... Нужно ли что-то добавить в методе perfomSync(), чтобы система узнала, что синхронизация выполнена и что может запускаться следующий запуск?

В настоящий момент я не пишу значения в contentProvider, просто потому, что пытаюсь выяснить, как работает синхронизация.

В настоящее время я тестирую эмулятор Android.

Заранее благодарю вас.

С наилучшими пожеланиями,

Робин

+0

возможный дубликат [Почему ContentResolver.requestSync не вызывает синхронизацию?] (http://stackoverflow.com/questions/5253858/why-does-contentresolver-requestsync-not-trigger-a-sync) – jcwenger

+0

Я установил периодическую синхронизацию с частотой <60 с и увидел сообщение logcat, которое система округлила это до 60 с - минимум, не упомянутый в документации. Конечно, я бы не читал эту страницу, если бы она вообще вообще синхронизировалась - для меня не работало периодическоеSync, независимо от setIsSyncable или http://stackoverflow.com/questions/7925802/syncadapter- not-being-called-dependent-on-order-of-account-setup-calls –

+0

@rpan Вы нашли ответ на этот вопрос? –

ответ

1

Периодической синхронизация может выполняться только тогда, когда его настройка автоматической синхронизации включена, и это синхронизируемое = верно. Лучшим подходом к этой проблеме будет использование GCM. Сервер может отправлять push-уведомления устройству (-ам), когда есть какое-то изменение, о котором должен знать клиент. На клиенте мы запрашиваем синхронизацию вручную после получения такого сообщения. Это более эффективно, и мы обновляемся, как только наш сервер, не дожидаясь следующего цикла синхронизации.

5

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

  ContentResolver.addPeriodicSync(
        account, 
        authority, 
        Bundle.EMPTY, 
        90 
      ); 

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

13

Я также боролся с периодической синхронизацией с адаптером синхронизации. Я могу запустить мой SyncAdapter вручную с помощью requestSync, но addPeriodicSync не будет запускаться.

Я заметил, что в все примеров, входя в Настройки-> Учетные записи показали счета SyncAdapter с небольшим «синхронизации колеса» (обычно зеленый, если он синхронизируется отлично, красный, если он не в состоянии синхронизации в последнее время), а также временная метка «Последний синхронизированный». Моя учетная запись (фиктивная учетная запись, скопированная и вставленная с Google Docs) не имела ничего похожего на колесо синхронизации или временную метку.

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

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

/res/xml/sync_adapter.xml

<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" 
android:accountType="com.example.database" 
android:allowParallelSyncs="false" 
android:contentAuthority="com.example.database.data.provider" 
android:isAlwaysSyncable="true" 
android:supportsUploading="false" 
android:userVisible="true" /> 

/ком/пример/базы данных/данных/MySyncAdapter

public class MySyncAdapter extends AbstractThreadedSyncAdapter { 
    private static final String TAG = MySyncAdapter.class.getSimpleName(); 
    Context context; 

    public MySyncAdapter(Context context, boolean autoInitialize) { 
     super(context, autoInitialize); 
     this.context = context; 
    } 

    public MySyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) { 
     super(context, autoInitialize, allowParallelSyncs); 
     this.context = context; 
    } 

    @Override 
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { 
     Log.e(TAG, "Performing Sync"); 
    } 
} 

AndroidManifest.xml (НУЖДАЕТСЯ Ярлык для СОДЕРЖАНИЯ, чтобы показать в счетах)

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    package="com.example.database"> 

    <uses-sdk tools:node="replace" /> 

    <uses-permission 
     android:name="android.permission.WRITE_EXTERNAL_STORAGE" 
     android:maxSdkVersion="18" /> 

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.VIBRATE" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
    <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" /> 
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> 
    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" /> 
    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> 
    <uses-permission android:name="android.permission.READ_SYNC_STATS" /> 


    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:logo="@drawable/chef_collection_logo_white" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme"> 

     <provider 
      android:name="com.example.database.data.MyContentProvider" 
      android:authorities="com.example.database.data.provider" 
      android:label="my provider" 
      android:exported="false" 
      android:multiprocess="true" 
      android:syncable="true" /> 

     <activity 
      android:name=".app.MainActivity" 
      android:label="@string/title_activity_main"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

     <service 
      android:name="com.example.database.data.AuthenticatorService" 
      android:exported="true" 
      android:process=":auth"> 
      <intent-filter> 
       <action android:name="android.accounts.AccountAuthenticator" /> 
      </intent-filter> 
      <meta-data 
       android:name="android.accounts.AccountAuthenticator" 
       android:resource="@xml/authenticator" /> 
     </service> 

     <service 
      android:name="com.example.database.data.MySyncAdapterService" 
      android:exported="true" 
      android:process=":sync"> 
      <intent-filter> 
       <action android:name="android.content.SyncAdapter" /> 
      </intent-filter> 
      <meta-data 
       android:name="android.content.SyncAdapter" 
       android:resource="@xml/sync_adapter" /> 
     </service> 

    </application> 

</manifest> 

Основная информация. Я вызываю этот код после первого запуска мастера настройки, но вы можете его назвать в любом месте. Это попытается синхронизировать каждые 30 секунд (используется для тестирования). Обратите внимание, что Документы Google для этого в настоящее время ошибочны, так как он упоминает, что ему требуется миллисекунды вместо секунд. Другое дело, что вы не можете передать null как пакет. Это приведет к исключению IllegalArgumentException или что-то подобное.

//Create Account 
mAccount = createSyncAccount(this); 


//Turn on periodic syncing 
ContentResolver resolver = getContentResolver(); 
resolver.setIsSyncable(mAccount, AUTHORITY, 1); 
resolver.setSyncAutomatically(mAccount, AUTHORITY, true); 

resolver.addPeriodicSync(
     mAccount, 
     AUTHORITY, 
     Bundle.EMPTY, 
     30); 
+0

Это только на конкретных версиях Android? Я получил свою синхронизацию на всех устройствах без ярлыка на контент-провайдере, за исключением некоторых на клиенте. И я не хочу делать релиз, который ничего не фиксирует. – Roel

+0

@DalvikVM Возможно, что он работает без лейбла, и, если он работает для вас, я не буду исправлять то, что не сломано. Я работал с конкретным набором планшетов Samsung для Android, и это, похоже, заработало. – welshk91

+0

@ wwlshk91: Он разбит на некоторых планшетах клиента. Это Samsung Galaxy Notes 10.1 под управлением Android 4.1.2. Уил обновил эти планшеты до 4,4 справки? – Roel

12

Периодическая синхронизация не запускается на некоторых устройствах, если опция синхронизации не установлена. Я сходила с ума с этим вопросом с Samsung Galaxy Гранд 2 недавно ...

enter image description here

+0

Спасибо, что так много ... :) – W00di

+0

спасибо миллион – Trinity

0

Периодическая синхронизация не будет работать, если устройство внутренней памяти почти заполнена, даже если все ваши конфигурации Синхронизация устанавливаются в правой way.I думаю, синхронизация прекратит функционировать, если используется 96 или 97% памяти. Я не знаю, какое их положение должно сделать, даже если память почти заполнена. Вы можете наблюдать ту же проблему в приложении gmail на Android-телефоне, где синхронизация не будет работать, когда память почти заполнена. Вы не можете получать или отправлять сообщения с помощью приложения android gmail, когда память устройства почти заполнена.

0

Это один работает для меня Есть две ошибки в учебном руководстве, насколько это объяснить, как сделать addPeriodicSync работы:

  1. Вы должны назвать ContentResolver.setSyncAutomatically с истинным в качестве третьего (синхронно) параметр, чтобы включить синхронизацию для вашего адаптера перед addPeriodicSync. вот так: ContentResolver.setSyncAutomatically (учетная запись, MY_AUTHORITY, true);

  2. Четвертый (pollFrequency) параметр ContentResolver.addPeriodicSync - это количество секунд, как указано здесь, а не миллисекунды, что подразумевается в руководстве по обучению. Демонстрационный код для addPeriodicSync в учебном пособии вызовет синхронизацию один раз в тысячу часов вместо одного часа. Таким образом, минимальная частота составляет 1 минуту.

Обратитесь к этому http://digitalassassin.net/2014/03/contentresolver-addperiodicsync-doesnt-work-never-syncs/