2012-06-18 14 views
15

Ho un SyncAdapter per la mia app e un AccountManager per aggiungere i miei account di app all'Account Manager di Android. Il mio codice per quando aggiungo un account per l'Account Manager si presenta come:SyncAdapter Android Inizializza automaticamente sincronizzazione

Bundle data = new Bundle(5); 
data.putString(_PEOPLE_ID, people_id); 
data.putString(_FIRST_NAME, first_name); 
data.putString(_LAST_NAME, last_name); 
data.putString(_PLAN, plan); 
data.putString(_BIRTHDAY, birthday); 
Account account = new Account(username, _ACCOUNT_TYPE); 
try { 
    boolean created; 
    created = _account_manager.addAccountExplicitly(account, 
            _cryptography.encrypt(_SEED, password), data); 
    response.accountCreated(created); 
    _account_manager.setAuthToken(account, _TOKEN_TYPE, session_token); 
    _model.updateActiveAccount(people_id, username, password); 
    SharedPreferences.Editor settings = _settings.edit(); 
    settings.putString(_ACCOUNT_TYPE, account.name); 
    settings.putString(_TOKEN_TYPE, session_token); 
    settings.commit(); 
    // Tells the content provider that it can sync this account 
    ContentResolver.setIsSyncable(account, AUTHORITY, 1); 
    final Bundle extras = new Bundle(1); 
    extras.putBoolean(SYNC_EXTRAS_INITIALIZE, true); 
    ContentResolver.addPeriodicSync(account, AUTHORITY, extras, 900); 
} catch (Exception e) { 
    Ln.e(e.getCause()); 
} 

posso aggiungere l'account al Account Manager con successo attraverso Impostazioni, ma devo abilitare manualmente la sincronizzazione per l'account in Impostazioni anche, anche sebbene i dati in background e le impostazioni di sincronizzazione automatica siano abilitati sull'emulatore. Se abilito manualmente la sincronizzazione, la sincronizzazione viene eseguita correttamente, ma non è avviata per impostazione predefinita.

risposta

28
ContentResolver.setIsSyncable(account, AUTHORITY, 1); 
ContentResolver.setSyncAutomatically(account, AUTHORITY, true); 

Come Blehi detto avvierà la sincronizzazione automatica del conto dato, date le impostazioni globali, "Dati in background" e "Auto-sync" sono abilitati.

Per evitare che il back-to-back sincronizzazione (from jcwenger) Assicurarsi che se qualsiasi metodo nelle SyncAdapter.onPerformSync(...) chiamate ContentResolver.notifyChange(...) utilizza ContentResolver.notifyChange(uri, observer, false) alla bandiera notificare non innescare una chiamata di sincronizzazione (il terzo parametro è syncToNetwork).

Se si sta utilizzando il ContentProvider per eseguire gli inserti/cancella/aggiornamenti per voi SyncAdapter ha senso chiamare ContentResolver.notifyChange(...) in modo che, mentre l'applicazione è visibile l'utente può ricevere gli aggiornamenti dal SyncAdapter, il che significa che si avrà la ContentProvider effettuare chiamate ContentResolver.notifyChange(...). Per far funzionare questo set up, ho aggiunto (seguendo il parametro dev guide) CALLER_IS_SYNC_ADAPTER a ogni URI utilizzato per lo SyncAdapter. Aggiungere questo metodo per il ContentProvider per testare gli URI in arrivo

/** 
* Determines if the given URI specifies that the request is coming from the sync adapter. 
* @param uri the given URI 
* @return true if the uri specifies that the request is coming from the sync adapter 
*/ 
private boolean callerIsSyncAdapter(Uri uri) { 
    final String is_sync_adapter = uri.getQueryParameter(CALLER_IS_SYNC_ADAPTER); 
    return is_sync_adapter != null && !is_sync_adapter.equals("0"); 
} 

allora si può fare

getContext().getContentResolver().notifyChange(uri, observer, !callerIsSyncAdapter(uri)); 

ogni volta che è necessario inviare una notifica di modifica.

E se si desidera pianificare la sincronizzazione da eseguire periodicamente a una frequenza (polling del server), aggiungere questo con la chiamata ContentResolver.setSyncAutomatically(...).

ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), frequency_in_seconds) 
6

è necessario impostare l'account per essere sincronizzabili per impostazione predefinita:

ContentResolver.setIsSyncable(account, AUTHORITY, 1); 
ContentResolver.setSyncAutomatically(account, AUTHORITY, true); 

Io uso le suddette linee 2 e sta funzionando correttamente.

+0

Aggiunta di ContentResolver.setSyncAutomatically (account, AUTHORITY, true); è quello di cui avevo bisogno, ma sembra che non stia riconoscendo la sincronizzazione periodica. Dopo aver aggiunto un account, continua a sincronizzarlo ripetutamente. –

+0

Provare a chiamare la funzione ContentResolver.addPeriodicSync() con il nuovo pacchetto() anziché gli extra. – Blehi

+0

extra è un nuovo pacchetto(), ci provo anche senza tentare di impostare nessuno dei flag (Bundle extras = new Bundle(); addPeriodicSync (account, AUTHORITY, extra, 900);) –

13

giusto per sottolineare, sembra che addPeriodicSync() esigenze setSyncAutomatically(), anche se la documentazione dice che setSyncAutomatically() è solo per il rilevamento della rete solletica.

Si noti che il periodo verrà corretto a> 60 se è inferiore a un minuto.

+2

La documentazione di Google non è buona su questo punto – cja

+1

Come mai nessuno di questi è nella loro documentazione? – toobsco42

2

Inizialmente creare un account e controllare il supporto di sincronizzazione per lo stesso utilizzando AccountManager. Se l'account supporta la sincronizzazione, chiama setIsSyncable() e setSyncAutomatically().

AccountManager accountManager = (AccountManager) this.getSystemService(ACCOUNT_SERVICE); 
if(accountManager.addAccountExplicitly(newAccount, null, null)){ 
     ContentResolver.setIsSyncable(account, AUTHORITY, 1); 
     ContentResolver.setSyncAutomatically(account, AUTHORITY, true); 
} 

Quindi è possibile attivare la sincronizzazione in qualsiasi momento.Si innescherà.

Nota: onPerformSync() di setSyncAutomatically() verrà chiamato per primo, quindi verrà attivata solo un'altra richiesta di sincronizzazione. Ma per rendere la sincronizzazione forzata basta aggiungere 2 flag extra.

Bundle bundle= new Bundle(); 
    bundle.putBoolean(
      ContentResolver.SYNC_EXTRAS_MANUAL, true); 
    bundle.putBoolean(
      ContentResolver.SYNC_EXTRAS_EXPEDITED, true); 
    ContentResolver.requestSync(account, AUTHORITY, bundle); 
Problemi correlati