2012-06-18 1 views
15

J'ai un SyncAdapter pour mon application, et un AccountManager pour ajouter mes comptes d'applications au gestionnaire de compte Android. Mon code quand j'ajouter un compte au gestionnaire de compte ressemble:Android SyncAdapter Initialiser automatiquement la synchronisation

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()); 
} 

Je peux ajouter le compte au gestionnaire de compte avec succès via les paramètres, mais je dois activer manuellement la synchronisation pour le compte dans les paramètres aussi, même Bien que les données d'arrière-plan et les paramètres de synchronisation automatique soient activés sur l'émulateur. Si j'active manuellement la synchronisation, la synchronisation est effectuée correctement, elle n'est pas démarrée par défaut.

Répondre

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

Comme Blehi dit amorcera la synchronisation automatique du compte donné, compte tenu des paramètres globaux, « données de base » et « Synchronisation automatique » sont activées.

Pour éviter que la synchronisation en arrière-à-dos (from jcwenger) assurez-vous que si une méthode dans les SyncAdapter.onPerformSync(...) appels ContentResolver.notifyChange(...) utilise ContentResolver.notifyChange(uri, observer, false) pour marquer le avisez pas déclencher un appel de synchronisation (le troisième paramètre est syncToNetwork).

Si vous utilisez le ContentProvider pour effectuer les insertions/suppressions/mises à jour pour vous SyncAdapter il est logique d'appeler ContentResolver.notifyChange(...) de sorte que lorsque l'application est visible, l'utilisateur peut recevoir des mises à jour de la SyncAdapter, qui signifie que vous aurez la ContentProvider faisant ContentResolver.notifyChange(...) appels. Pour que cette configuration fonctionne, j'ai ajouté (en suivant le dev guide) le paramètre de requête CALLER_IS_SYNC_ADAPTER à chaque URI utilisé pour le SyncAdapter. Ajouter cette méthode à la ContentProvider pour tester les URIs entrants

/** 
* 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"); 
} 

alors vous pouvez faire

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

chaque fois que vous devez envoyer une notification de changement.

Et si vous souhaitez programmer la synchronisation à exécuter périodiquement à une fréquence (interrogation du serveur), ajoutez-la avec l'appel ContentResolver.setSyncAutomatically(...).

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

Vous devez définir le compte être synchronisable par défaut:

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

J'utilise les 2 lignes ci-dessus et il fonctionne correctement.

+0

Ajout de ContentResolver.setSyncAutomatically (compte, AUTHORITY, true); C'est ce dont j'avais besoin, mais il semble que ce ne soit pas en reconnaissant la synchronisation périodique. Après avoir ajouté un compte, il ne cesse de se synchroniser. –

+0

Essayez d'appeler la fonction ContentResolver.addPeriodicSync() avec le nouveau Bundle() au lieu des extras. – Blehi

+0

extras est un nouveau Bundle(), je l'essaie même sans essayer de définir l'un des drapeaux (Bundle extras = new Bundle(); addPeriodicSync (compte, AUTHORITY, extras, 900);) –

13

Juste pour souligner, il semble que addPeriodicSync() besoins setSyncAutomatically(), même si la documentation indique que setSyncAutomatically() est seulement pour la détection réseau chatouille.

Notez que la période sera corrigée à> 60s s'il est inférieur à une minute.

+2

La documentation de Google est mauvaise sur ce point – cja

+1

Comment se fait-il que rien de tout cela ne se trouve dans leur documentation? – toobsco42

2

Créez d'abord un compte et vérifiez la prise en charge de la synchronisation à l'aide de AccountManager. Si le compte prend en charge la synchronisation, appelez setIsSyncable() et setSyncAutomatically().

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

Ensuite, vous pouvez déclencher la synchronisation à tout moment.Cela va déclencher.

Remarque: onPerformSync() de setSyncAutomatically() sera appelée en premier, puis seule une autre requête de synchronisation sera déclenchée. Mais pour forcer la synchronisation, il suffit d'ajouter 2 drapeaux supplémentaires.

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