Pourquoi ne ContentResolver.requestSync de ne pas déclencher une synchronisation?
Je suis en train de mettre en œuvre le Fournisseur de Contenu de Synchronisation de l'Adaptateur tel que discuté à Google IO - diapositive 26. Mon fournisseur de contenu est au travail, et ma synchro fonctionne quand je le provoquer de la Dev Outils de Synchronisation de Testeur de l'application, cependant quand je l'appelle ContentResolver.requestSync(compte, l'autorité, le bundle) de mon ContentProvider, mon sync n'est jamais déclenché.
ContentResolver.requestSync(
account,
AUTHORITY,
new Bundle());
Edit -- ajoutée manifeste extrait de
Mon manifeste xml contient:
<service
android:name=".sync.SyncService"
android:exported="true">
<intent-filter>
<action
android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
--Edit
Mon syncadapter.xml associé avec mon service de synchronisation contient:
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="AUTHORITY"
android:accountType="myaccounttype"
android:supportsUploading="true"
/>
Pas sûr de ce que d'autres code serait utile. Le compte transmis à requestSync est de "myaccounttype" et l'AUTORITÉ transmise à l'appel à la hauteur de ma syc adaptateur xml.
Est ContentResolver.requestSync la bonne façon de demander une synchronisation? Il ressemble à la synchronisation outil de test se lie directement le service et les appels démarrer la synchronisation, mais qui semble comme il défait le but de s'intégrer dans l'architecture de synchronisation.
Si c'est la bonne façon de demander une synchronisation, alors pourquoi serait-sync testeur de travail, mais pas de mon appel à ContentResolver.requestSync? Il ya quelque chose que j'ai besoin de passer dans le bundle?
Je suis en train de tester dans l'émulateur sur les appareils exécutant 2.1 et 2.2.
- Mon problème était que mon point de rupture dans la synchronisation de l'adaptateur n'a pas été atteint... Puis j'ai réalisé que j'étais en train de déboguer un service... Espérons que cela aide d'autres personnes comme moi.
- Les points d'arrêt de la synchronisation de l'adaptateur de service ne parviennent pas à déclencher. C'est parce que la synchro adaptateur de service s'exécute dans un processus séparé. C'est ce que @danglang laissait présager. Voir aussi cette question: stackoverflow.com/questions/8559458/...
- Dans mon cas, la suppression
android:process=":sync"
du service de synchronisation de laisser le débogueur a frappé le bec points. Le service de synchronisation de lui-même travaillait avant que, parce que j'ai pu voir des messages de journauxonPerformSync
méthode pour le compte d'un autre processus. - Une autre cause est le WiFi désactivé, donc si vous essayez de synchroniser moqué de données, vérifiez votre connexion.
Vous devez vous connecter pour publier un commentaire.
Appel
requestSync()
ne fonctionne que sur un {Compte, ContentAuthority} paire qui est connu du système. Votre application doit passer par un certain nombre d'étapes à dire Android que vous êtes capable de synchroniser un type spécifique de contenu à l'aide d'un type de compte. Il le fait dans le AndroidManifest.1. Informer Android que votre application paquet fournit la synchronisation
Tout d'abord, dans AndroidManifest.xml, vous devez déclarer que vous avez un Service de Synchronisation:
L'attribut name de la
<service>
tag est le nom de votre classe de connecter jusqu'sync... je vais en parler à qui en une seconde.Réglage exporté vrai, il est visible à d'autres composants (nécessaire pour
ContentResolver
pouvez l'appeler comme ça).Le filtre d'intention permet d'attraper une intention demandant de synchronisation. (Ce
Intent
vient deContentResolver
lorsque vous appelezContentResolver.requestSync()
ou liées à la planification de méthodes.)La
<meta-data>
tag sera discuté ci-dessous.2. Fournir des Android un service permet de trouver votre SyncAdapter
De sorte que la classe elle-même... en Voici un exemple:
Votre classe doit étendre
Service
ou un de ses sous-classes, doivent mettre en œuvrepublic IBinder onBind(Intent)
, et doit retourner unSyncAdapterBinder
lorsque cela s'appelle... Vous avez besoin d'une variable de typeAbstractThreadedSyncAdapter
. Donc, comme vous pouvez le voir, c'est à peu près tout dans cette classe. La seule raison pour laquelle il est là pour fournir un Service, qui offre une interface standard pour Android pour la requête de votre classe, de votreSyncAdapter
est lui-même.3. Fournir un
class SyncAdapter
pour effectuer la synchronisation.mySyncAdapter est là que la vraie logique de synchronisation lui-même est stocké. Son
onPerformSync()
méthode est appelée lorsqu'il est temps de synchronisation. Je suppose que vous avez déjà en place.4. Établir une liaison entre un type de Compte et un Contenu Autorité
À la recherche de retour à nouveau à AndroidManifest, cette étrange
<meta-data>
balise dans notre service est l'élément clé qui établit la liaison entre un ContentAuthority et un compte. L'extérieur fait référence à un autre fichier xml (appelez ça comme vous voulez, quelque chose de pertinent à votre application.) Regardons sync_myapp.xml:D'accord, alors à quoi ça sert? Il raconte Android que la synchronisation de l'adaptateur que nous avons définie (la classe qui a été appelé le nom de l'élément de la
<service>
balise qui comprend le<meta-data>
balise qui fait référence à ce fichier...) permettra de synchroniser les contacts à l'aide d'un com.google compte style.Tous vos contentAuthority chaînes correspondent à tous, et en correspondance avec ce que vous synchronisez -- Ce doit être une chaîne de caractères que vous définissez, si vous êtes en train de créer votre propre base de données, ou vous devez utiliser certaines de périphérique existant chaînes si vous êtes à la synchronisation connu des types de données (comme les contacts ou le calendrier d'événements ou de ce que vous avez.) Le ci-dessus ("com.android.les contacts") se trouve être le ContentAuthority chaîne pour les contacts de type de données (surprise, surprise).
accountType doit également correspondre à l'un de ceux qu'on appelle les types de comptes qui sont déjà entrés, ou elle doit correspondre à celui que vous êtes en train de créer (Ce qui implique la création d'une sous-classe de AccountAuthenticator pour obtenir auth sur votre serveur... Vaut un article, lui-même.) Encore une fois, "com.google" est la chaîne définie par l'identification... google.com style informations d'identification du compte (encore une fois, cela ne devrait pas être une surprise).
5. Activer la Synchronisation sur un Compte donné /ContentAuthority paire
Enfin, la synchronisation doit être activé. Vous pouvez le faire dans les Comptes & Sync page dans le panneau de contrôle en allant à votre application et en cochant la case à côté de votre application dans le compte correspondant. Alternativement, vous pouvez le faire dans une certaine configuration de code dans votre application:
Pour la synchronisation, votre compte/autorité de la paire doit être activé pour la synchronisation (comme ci-dessus) et dans le monde de synchronisation drapeau sur le système doit être réglé, et l'appareil doit disposer d'une connectivité réseau.
Si votre compte/autorité de la synchronisation ou de la mondial de synchronisation sont désactivées, l'appel de RequestSync() n'ont un effet -- Il définit un indicateur que la synchronisation a été demandé, et sera réalisée dès que la synchronisation est activée.
Aussi, par mgv, réglage
ContentResolver.SYNC_EXTRAS_MANUAL
à true dans le bundle extras de votre requestSync demandera android pour forcer une synchronisation, même si global sync est désactivé (être respectueux de votre utilisateur ici!)Enfin, vous pouvez configurer un périodique planification de la synchronisation, de nouveau avec ContentResolver fonctions.
6. Examiner les implications de plusieurs comptes
Il est possible d'avoir plus d'un compte du même type (deux @gmail.com les comptes configurés sur un appareil ou deux facebook comptes, ou les deux comptes twitter, etc...), Vous devriez envisager l'application implications de ce que... Si vous avez deux comptes, vous ne voulez probablement pas à essayer de synchroniser les deux d'entre eux dans les mêmes tables de base de données. Peut-être vous avez besoin de spécifier qu'un seul peut être actif à la fois, et de vider les tables et resync si vous changez de compte. (par le biais d'une page de propriétés qui demande à ce que les 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 clé de colonne de chaque table. Tous spécifiques à l'application et digne de réflexion.
ContentResolver.setIsSyncable(Account account, String authority, int syncable)
pourrait être d'intérêt ici.setSyncAutomatically()
contrôle si un compte/autorité de la paire est vérifié ou décoché, alors quesetIsSyncable()
fournit un moyen de décocher et gris la ligne de sorte que l'utilisateur ne peut pas l'activer. Vous pouvez définir un compte Syncable et l'autre pas Syncable (dsabled).7. Être conscient de ContentResolver.notifyChange()
Une chose la plus délicate.
ContentResolver.notifyChange()
est une fonction utilisée parContentProvider
s de notifier Android que le local de la base de données a été modifié. Cela sert à deux fonctions, tout d'abord, il va provoquer les curseurs suivants que le contenu de l'uri pour la mise à jour, et à son tour, d'actualisation et de l'invalider et de redessiner unListView
, etc... C'est vraiment magique, les modifications de base de données et votreListView
juste les mises à jour automatiquement. Génial. Aussi, lorsque les modifications de base de données, Android demande de Synchronisation pour vous, même en dehors de votre horaire normal, de sorte que ces modifications sont prises hors tension de l'appareil et synchroniser avec le serveur le plus rapidement possible. Aussi génial.Il y a un bord de cas bien. Si vous tirez à partir du serveur, et de pousser une mise à jour dans le
ContentProvider
, il consciencieusement appelnotifyChange()
et android va aller, "Oh, modifications de base de données, de mieux les mettre sur le serveur!" (Doh!) Bien écritContentProviders
aura quelques tests pour voir si les changements sont venus à partir du réseau ou de l'utilisateur, et permet de définir le type booleansyncToNetwork
drapeau false si donc, pour éviter ce gaspillage double-sync. Si vous êtes à l'alimentation des données dans unContentProvider
, il vous appartient de comprendre comment obtenir ce travail, Sinon vous finirez toujours deux synchronise quand une seule est nécessaire.8. Se sentir heureux!
Une fois que vous avez toutes ces métadonnées xml en place, et activé la synchronisation, Android saurez comment connecter le tout en place pour vous, et sync devrait commencer à travailler. À ce stade, beaucoup de choses qui sont nice suffit de cliquer en place et il va se sentir un peu comme de la magie. Profitez-en!
ContentResolver.SYNC_EXTRAS_MANUAL
mettre à true pour le Bundle extras et vous force la synchronisation 🙂SyncService
dans la Google I/O 2012 (et leSampleSyncAdapter
mise en œuvre dans le SDK), il y a une synchronisation passe dansonCreate
... vous avez oublié de le mentionner?requestSync();
si je ne veux pas utiliseraccount
J'ai été caling
setIsSyncable
après AccountManagersetAuthToken
méthode. MaissetAuthToken
fonction renvoyée avantsetIsSyncable
a été atteint. Après des modifications d'ordre tout a bien fonctionné!