La chiamata requestSync()
funzionerà solo su una coppia {Account, ContentAuthority} nota al sistema. La tua app deve eseguire una serie di passaggi per dire ad Android che sei in grado di sincronizzare un tipo specifico di contenuto utilizzando un tipo specifico di account. Lo fa in AndroidManifest.
1. Avvisare Android che il pacchetto dell'applicazione fornisce la sincronizzazione
Prima di tutto, in AndroidManifest.xml, devi dichiarare di avere un servizio di sincronizzazione:
<service android:name=".sync.mySyncService" android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/sync_myapp" />
</service>
L'attributo name del <service>
tag è il nome della tua classe per connettere la sincronizzazione ... parlerò di questo tra un secondo.
L'impostazione di exported true lo rende visibile ad altri componenti (necessario quindi è ContentResolver
possibile chiamarlo).
Il filtro intento consente di rilevare un intento che richiede la sincronizzazione. (Questo Intent
deriva dalla ContentResolver
chiamata ContentResolver.requestSync()
o dai metodi di pianificazione correlati.)
Il <meta-data>
tag verrà discusso di seguito.
2. Fornire ad Android un servizio utilizzato per trovare il SyncAdapter
Quindi la classe stessa ... Ecco un esempio:
public class mySyncService extends Service {
private static mySyncAdapter mSyncAdapter = null;
public SyncService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
if (mSyncAdapter == null) {
mSyncAdapter = new mySyncAdapter(getApplicationContext(), true);
}
}
@Override
public IBinder onBind(Intent arg0) {
return mSyncAdapter.getSyncAdapterBinder();
}
}
La tua classe deve estendere Service
o una delle sue sottoclassi, deve implementare public IBinder onBind(Intent)
e deve restituire un SyncAdapterBinder
quando viene chiamata ... Hai bisogno di una variabile di tipo AbstractThreadedSyncAdapter
. Quindi, come puoi vedere, è praticamente tutto in quella classe. L'unico motivo per cui è lì è fornire un servizio, che offre un'interfaccia standard per Android per interrogare la tua classe su cosa sia la tua SyncAdapter
stessa.
3. Fornire un class SyncAdapter
per eseguire effettivamente la sincronizzazione.
mySyncAdapter è il luogo in cui viene archiviata la logica di sincronizzazione reale. Il suo onPerformSync()
metodo viene chiamato quando è il momento di sincronizzare. Immagino che tu abbia già questo a posto.
4. Stabilire un legame tra un tipo di account e un'autorità per i contenuti
Ripensando ad AndroidManifest, quello strano <meta-data>
tag nel nostro servizio è l'elemento chiave che stabilisce il legame tra un ContentAuthority e un account. Fa riferimento esternamente a un altro file xml (chiamalo come preferisci, qualcosa di rilevante per la tua app.) Diamo un'occhiata a sync_myapp.xml:
<?xml version="1.0" encoding="utf-8" ?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="com.google"
android:userVisible="true" />
Ok, quindi cosa fa questo? Indica ad Android che l'adattatore di sincronizzazione che abbiamo definito (la classe che è stata chiamata nell'elemento name del <service>
tag che include il <meta-data>
tag che fa riferimento a questo file ...) sincronizzerà i contatti utilizzando un account in stile com.google.
Tutti i tuoi contenuti Le stringhe dell'autorità devono corrispondere e corrispondere a ciò che stai sincronizzando: questa dovrebbe essere una stringa che definisci, se stai creando il tuo database, o dovresti usare alcune stringhe del dispositivo esistenti se stai sincronizzando noto tipi di dati (come contatti, eventi di calendario o altro). Il precedente ("com.android.contacts") sembra essere la stringa ContentAuthority per i dati del tipo di contatti (sorpresa, sorpresa.)
accountType deve anche corrispondere a uno di quei tipi di account conosciuti che sono già inseriti, o deve corrispondere a quello che stai creando (ciò comporta la creazione di una sottoclasse di AccountAuthenticator per ottenere l'autenticazione sul tuo server ... Vale un articolo, a sua volta.) Ancora una volta, "com.google" è la stringa definita che identifica ... le credenziali dell'account in stile google.com (di nuovo, questa non dovrebbe essere una sorpresa).
5. Abilita la sincronizzazione su una determinata coppia Account / ContentAuthority
Infine, la sincronizzazione deve essere abilitata. Puoi farlo nella pagina Account e sincronizzazione nel pannello di controllo accedendo alla tua app e impostando la casella di controllo accanto alla tua app all'interno dell'account corrispondente. In alternativa, puoi farlo in un codice di configurazione nella tua app:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Affinché la sincronizzazione avvenga, la tua coppia account / autorità deve essere abilitata per la sincronizzazione (come sopra) e deve essere impostato il flag di sincronizzazione globale globale sul sistema e il dispositivo deve avere la connettività di rete.
Se la sincronizzazione dell'account / autorità o la sincronizzazione globale sono disabilitate, la chiamata a RequestSync () ha un effetto: imposta un contrassegno che la sincronizzazione è stata richiesta e verrà eseguita non appena la sincronizzazione sarà abilitata.
Inoltre, per mgv , l'impostazione ContentResolver.SYNC_EXTRAS_MANUAL
su true nel pacchetto extra di requestSync chiederà ad Android di forzare una sincronizzazione anche se la sincronizzazione globale è disattivata (sii rispettoso del tuo utente qui!)
Infine, puoi impostare una sincronizzazione pianificata periodica, sempre con le funzioni ContentResolver.
6. Considera le implicazioni di più account
È possibile avere più di un account dello stesso tipo (due account @ gmail.com configurati su un dispositivo o due account Facebook, o due account Twitter, ecc ...) Dovresti considerare le implicazioni dell'applicazione di farlo. .. Se hai due account, probabilmente non vorrai provare a sincronizzarli entrambi nelle stesse tabelle di database. Forse è necessario specificare che solo uno può essere attivo alla volta e svuotare le tabelle e risincronizzarle se si cambia account. (tramite una pagina delle proprietà che interroga gli account presenti). Forse crei un database diverso per ogni account, forse tabelle diverse, forse una colonna chiave in ogni tabella. Tutte specifiche per applicazioni e meritevoli di riflessione. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
potrebbe essere di interesse qui. setSyncAutomatically()
controlla se una coppia account / autorità è controllata odeselezionato , mentre setIsSyncable()
fornisce un modo per deselezionare e disattivare la linea in modo che l'utente non possa accenderlo. È possibile impostare un account sincronizzabile e l'altro non sincronizzabile (disattivato).
7. Sii consapevole di ContentResolver.notifyChange ()
Una cosa complicata. ContentResolver.notifyChange()
è una funzione utilizzata da ContentProvider
s per notificare ad Android che il database locale è stato modificato. Questo ha due funzioni, in primo luogo, farà sì che i cursori che seguono quell'URI di contenuto si aggiornino e, a loro volta, richiedano e invalidano e ridisegnano un ListView
, ecc ... È molto magico, il database cambia e il tuo si ListView
aggiorna automaticamente. Eccezionale. Inoltre, quando il database cambia, Android richiederà la sincronizzazione per te, anche al di fuori della tua normale pianificazione, in modo che tali modifiche vengano rimosse dal dispositivo e sincronizzate con il server il più rapidamente possibile. Anche fantastico.
C'è però un caso limite. Se esegui il pull dal server e ContentProvider
inserisci un aggiornamento in , verrà chiamato doverosamente notifyChange()
e Android dirà, "Oh, modifiche al database, meglio metterle sul server!" (Doh!) Ben scritto ContentProviders
avrà alcuni test per vedere se le modifiche provengono dalla rete o dall'utente, e imposterà il syncToNetwork
flag booleano false in tal caso, per evitare questa doppia sincronizzazione dispendiosa. Se stai inserendo i dati in un ContentProvider
, ti conviene capire come farlo funzionare - Altrimenti finirai per eseguire sempre due sincronizzazioni quando ne serve solo una.
8. Sentiti felice!
Una volta che hai tutti questi metadati xml a posto e la sincronizzazione abilitata, Android saprà come connettere tutto per te e la sincronizzazione dovrebbe iniziare a funzionare. A questo punto, molte cose belle andranno a posto e sembreranno magiche. Godere!