L'appel requestSync()
ne fonctionnera que sur une paire {Account, ContentAuthority} connue du système. Votre application doit suivre un certain nombre d'étapes pour indiquer à Android que vous êtes capable de synchroniser un type de contenu spécifique à l'aide d'un type de compte spécifique. Il le fait dans le fichier AndroidManifest.
1. Informez Android que votre package d'application permet la synchronisation
Tout d'abord, dans AndroidManifest.xml, vous devez déclarer que vous disposez d'un service de synchronisation:
<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'attribut name de la <service>
balise est le nom de votre classe pour connecter la synchronisation ... J'en parlerai dans une seconde.
Le paramètre exporté sur true le rend visible par les autres composants (nécessaire, vous ContentResolver
pouvez donc l' appeler).
Le filtre d'intention lui permet d'attraper un intent demandant une synchronisation. (Cela Intent
vient du ContentResolver
moment où vous appelez ContentResolver.requestSync()
ou des méthodes de planification associées.)
L' <meta-data>
étiquette sera discutée ci-dessous.
2. Fournissez à Android un service utilisé pour trouver votre SyncAdapter
Donc la classe elle-même ... Voici un exemple:
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();
}
}
Votre classe doit étendre Service
ou l'une de ses sous-classes, doit implémenter public IBinder onBind(Intent)
et doit renvoyer a SyncAdapterBinder
quand elle est appelée ... Vous avez besoin d'une variable de type AbstractThreadedSyncAdapter
. Donc, comme vous pouvez le voir, c'est à peu près tout dans cette classe. La seule raison pour laquelle il existe est de fournir un service, qui offre une interface standard pour Android pour interroger votre classe sur ce que vous SyncAdapter
êtes.
3. Fournissez un class SyncAdapter
pour effectuer réellement la synchronisation.
mySyncAdapter est l'endroit où la vraie logique de synchronisation elle-même est stockée. Sa onPerformSync()
méthode est appelée au moment de la synchronisation. Je suppose que vous l'avez déjà en place.
4. Établir une liaison entre un type de compte et une autorité de contenu
En regardant à nouveau AndroidManifest, cette <meta-data>
balise étrange dans notre service est l'élément clé qui établit la liaison entre un ContentAuthority et un compte. Il fait référence en externe à un autre fichier xml (appelez-le comme vous le souhaitez, quelque chose de pertinent pour votre application.) Regardons 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, alors qu'est-ce que ça fait? Il indique à Android que l'adaptateur de synchronisation que nous avons défini (la classe qui a été appelée dans l'élément de nom de la <service>
balise qui comprend la <meta-data>
balise qui fait référence à ce fichier ...) synchronisera les contacts à l'aide d'un compte de style com.google.
Toutes vos chaînes contentAuthority doivent toutes correspondre et correspondre à ce que vous synchronisez - Il doit s'agir d'une chaîne que vous définissez, si vous créez votre propre base de données, ou vous devez utiliser des chaînes d'appareils existantes si vous synchronisez types de données (comme les contacts ou les événements de calendrier ou tout le reste.) Ce qui précède ("com.android.contacts") se trouve être la chaîne ContentAuthority pour les données de type de contacts (surprise, surprise.)
accountType doit également correspondre à l'un de ces types de comptes connus qui sont déjà saisis, ou il doit correspondre à celui que vous créez (cela implique la création d'une sous-classe de AccountAuthenticator pour obtenir l'authentification sur votre serveur ... Vaut un article, lui-même.) Encore une fois, "com.google" est la chaîne définie identifiant ... les informations d'identification du compte de style google.com (encore une fois, cela ne devrait pas être une surprise.)
5. Activer la synchronisation sur une paire Compte / ContentAuthority donnée
Enfin, la synchronisation doit être activée. Vous pouvez le faire dans la page Comptes et synchronisation du panneau de configuration en accédant à votre application et en cochant la case à côté de votre application dans le compte correspondant. Vous pouvez également le faire dans un code de configuration dans votre application:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Pour que la synchronisation se produise, votre paire compte / autorité doit être activée pour la synchronisation (comme ci-dessus) et l'indicateur global de synchronisation globale sur le système doit être défini, et l'appareil doit disposer d'une connectivité réseau.
Si la synchronisation de votre compte / autorité ou la synchronisation globale sont désactivées, l'appel de RequestSync () a un effet - Il définit un indicateur indiquant que la synchronisation a été demandée et sera effectuée dès que la synchronisation sera activée.
De plus, par mgv , définir ContentResolver.SYNC_EXTRAS_MANUAL
sur true dans le bundle extras de votre requestSync demandera à android de forcer une synchronisation même si la synchronisation globale est désactivée (soyez respectueux de votre utilisateur ici!)
Enfin, vous pouvez configurer une synchronisation planifiée périodique, toujours avec les fonctions ContentResolver.
6. Examiner les implications de plusieurs comptes
Il est possible d'avoir plus d'un compte du même type (deux comptes @ gmail.com configurés sur un appareil ou deux comptes facebook, ou deux comptes Twitter, etc.). Vous devriez considérer les implications applicatives de cela. .. Si vous avez deux comptes, vous ne voudrez probablement pas essayer de les synchroniser tous les deux dans les mêmes tables de base de données. Vous devez peut-être spécifier qu'un seul peut être actif à la fois, vider les tables et resynchroniser si vous changez de compte. (via une page de propriétés qui demande quels comptes sont présents). Peut-être que vous créez une base de données différente pour chaque compte, peut-être des tables différentes, peut-être une colonne clé dans chaque table. Toutes les applications sont spécifiques et dignes de réflexion. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
pourrait être intéressant ici. setSyncAutomatically()
contrôle si une paire compte / autorité est cochée ounon cochée , alors que setIsSyncable()
fournit un moyen de décocher et de griser la ligne afin que l'utilisateur ne puisse pas l'activer. Vous pouvez définir un compte Syncable et l'autre non Syncable (dsabled).
7. Soyez conscient de ContentResolver.notifyChange ()
Une chose délicate. ContentResolver.notifyChange()
est une fonction utilisée par ContentProvider
s pour informer Android que la base de données locale a été modifiée. Cela remplit deux fonctions, premièrement, cela entraînera la mise à jour des curseurs suivant cet uri de contenu, et à son tour la requery et l'invalidation et le redessiner d'un ListView
, etc ... C'est très magique, la base de données change et votre ListView
juste mise à jour automatiquement. Impressionnant. De plus, lorsque la base de données change, Android demandera Sync pour vous, même en dehors de votre horaire normal, afin que ces modifications soient supprimées de l'appareil et synchronisées avec le serveur le plus rapidement possible. Aussi génial.
Il y a cependant un cas de pointe. Si vous tirez du serveur et poussez une mise à jour dans le ContentProvider
, il appellera consciencieusement notifyChange()
et Android dira, "Oh, les changements de base de données, mieux vaut les mettre sur le serveur!" (Doh!) Bien écrit ContentProviders
aura des tests pour voir si les changements viennent du réseau ou de l'utilisateur, et définira le syncToNetwork
drapeau booléen sur false si c'est le cas, pour éviter cette double synchronisation inutile. Si vous introduisez des données dans un ContentProvider
, il vous incombe de déterminer comment faire fonctionner cela - Sinon, vous finirez par toujours effectuer deux synchronisations quand une seule est nécessaire.
8. Sentez-vous heureux!
Une fois que toutes ces métadonnées xml sont en place et que la synchronisation est activée, Android saura comment tout connecter pour vous et la synchronisation devrait commencer à fonctionner. À ce stade, beaucoup de choses agréables se mettront en place et cela ressemblera beaucoup à de la magie. Prendre plaisir!