Das Aufrufen requestSync()
funktioniert nur für ein dem Konto bekanntes Paar {Account, ContentAuthority}. Ihre App muss eine Reihe von Schritten durchlaufen, um Android mitzuteilen, dass Sie in der Lage sind, eine bestimmte Art von Inhalten mit einer bestimmten Art von Konto zu synchronisieren. Dies geschieht im AndroidManifest.
1. Benachrichtigen Sie Android, dass Ihr Anwendungspaket die Synchronisierung bietet
Zunächst müssen Sie in AndroidManifest.xml erklären, dass Sie über einen Synchronisierungsdienst verfügen:
<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>
Das Namensattribut des <service>
Tags ist der Name Ihrer Klasse, um die Synchronisierung herzustellen ... Ich werde gleich darauf eingehen.
Wenn Sie exported true festlegen, wird es für andere Komponenten sichtbar (erforderlich) ContentResolver
es aufgerufen werden kann).
Mit dem Absichtsfilter kann eine Absicht erfasst werden, die eine Synchronisierung anfordert. (Dies Intent
kommt von, ContentResolver
wenn Sie ContentResolver.requestSync()
oder verwandte Planungsmethoden aufrufen .)
Das <meta-data>
Tag wird unten diskutiert.
2. Stellen Sie Android einen Dienst zur Verfügung, mit dem Sie Ihren SyncAdapter finden
Also die Klasse selbst ... Hier ist ein Beispiel:
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();
}
}
Ihre Klasse muss eine Service
oder eine ihrer Unterklassen erweitern, implementieren public IBinder onBind(Intent)
und a zurückgeben, SyncAdapterBinder
wenn dies aufgerufen wird ... Sie benötigen eine Variable vom Typ AbstractThreadedSyncAdapter
. Wie Sie sehen, ist das so ziemlich alles in dieser Klasse. Der einzige Grund dafür ist die Bereitstellung eines Dienstes, der eine Standardschnittstelle für Android bietet, über die Sie Ihre Klasse nach Ihrer eigenen SyncAdapter
fragen können.
3. Geben Sie a class SyncAdapter
an, um die Synchronisierung tatsächlich durchzuführen.
In mySyncAdapter wird die eigentliche Synchronisierungslogik selbst gespeichert. Es istonPerformSync()
Methode wird aufgerufen, wenn die Synchronisierung abgeschlossen ist. Ich denke, Sie haben dies bereits eingerichtet.
4. Stellen Sie eine Bindung zwischen einem Kontotyp und einer Inhaltsbehörde her
Wenn wir noch einmal auf AndroidManifest zurückblicken, ist dieses seltsame <meta-data>
Tag in unserem Service das Schlüsselelement, das die Bindung zwischen einer ContentAuthority und einem Konto herstellt. Es verweist extern auf eine andere XML-Datei (nennen Sie es wie Sie möchten, etwas, das für Ihre App relevant ist.) Schauen wir uns sync_myapp.xml an:
<?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" />
Okay, was macht das? Es teilt Android mit, dass der von uns definierte Synchronisierungsadapter (die Klasse, die im name-Element des <service>
Tags aufgerufen wurde, das das Tag enthält, das <meta-data>
auf diese Datei verweist ...) Kontakte über ein Konto im com.google-Stil synchronisiert.
Alle Ihre contentAuthority-Zeichenfolgen müssen mit dem übereinstimmen, was Sie synchronisieren. Dies sollte eine Zeichenfolge sein, die Sie definieren, wenn Sie eine eigene Datenbank erstellen, oder Sie sollten einige vorhandene Gerätezeichenfolgen verwenden, wenn Sie die Synchronisierung durchführen Datentypen (wie Kontakte oder Kalenderereignisse oder was haben Sie). Das oben Gesagte ("com.android.contacts") ist zufällig die ContentAuthority-Zeichenfolge für Kontakttypdaten (Überraschung, Überraschung.)
accountType muss auch mit einem der bekannten Kontotypen übereinstimmen, die bereits eingegeben wurden, oder mit einem, den Sie erstellen (Dies beinhaltet das Erstellen einer Unterklasse von AccountAuthenticator, um die Authentifizierung auf Ihrem Server zu erhalten ... Ein Artikel ist es wert.) Wiederum ist "com.google" die definierte Zeichenfolge, die die Anmeldeinformationen eines Kontos im Google.com-Stil identifiziert (auch dies sollte keine Überraschung sein.)
5. Aktivieren Sie die Synchronisierung für ein bestimmtes Konto / ContentAuthority-Paar
Schließlich muss die Synchronisierung aktiviert werden. Sie können dies auf der Seite "Konten und Synchronisierung" in der Systemsteuerung tun, indem Sie zu Ihrer App gehen und das Kontrollkästchen neben Ihrer App im entsprechenden Konto aktivieren. Alternativ können Sie dies in einem Setup-Code in Ihrer App tun:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Damit eine Synchronisierung stattfinden kann, muss Ihr Konto- / Berechtigungspaar für die Synchronisierung aktiviert sein (wie oben), und das allgemeine globale Synchronisierungsflag auf dem System muss gesetzt sein, und das Gerät muss über eine Netzwerkverbindung verfügen.
Wenn die Synchronisierung Ihres Kontos / Ihrer Behörde oder die globale Synchronisierung deaktiviert ist, hat der Aufruf von RequestSync () Auswirkungen. Er setzt ein Flag, dass die Synchronisierung angefordert wurde, und wird ausgeführt, sobald die Synchronisierung aktiviert ist.
Auch pro mgv EinstellungContentResolver.SYNC_EXTRAS_MANUAL
im Extras-Bundle Ihrer auf true wird Android aufgefordert, eine Synchronisierung zu erzwingen, auch wenn die globale Synchronisierung ist (respektieren Sie Ihren Benutzer hier!).
Schließlich können Sie eine regelmäßige geplante Synchronisierung erneut mit ContentResolver-Funktionen einrichten.
6. Berücksichtigen Sie die Auswirkungen mehrerer Konten
Es ist möglich, mehr als ein Konto desselben Typs zu haben (zwei @ gmail.com-Konten auf einem Gerät oder zwei Facebook-Konten oder zwei Twitter-Konten usw.). Sie sollten die Auswirkungen der Anwendung berücksichtigen. .. Wenn Sie zwei Konten haben, möchten Sie wahrscheinlich nicht versuchen, beide mit denselben Datenbanktabellen zu synchronisieren. Möglicherweise müssen Sie angeben, dass jeweils nur eine aktiv sein kann, und die Tabellen leeren und erneut synchronisieren, wenn Sie das Konto wechseln. (über eine Eigenschaftsseite, die abfragt, welche Konten vorhanden sind). Vielleicht erstellen Sie für jedes Konto eine andere Datenbank, vielleicht verschiedene Tabellen, vielleicht eine Schlüsselspalte in jeder Tabelle. Alle anwendungsspezifisch und bedenkenswert. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
könnte hier von Interesse sein. setSyncAutomatically()
steuert, ob ein Konto / Berechtigungspaar geprüft wird oderdeaktiviert , während es setIsSyncable()
eine Möglichkeit bietet, die Linie zu deaktivieren und auszublenden, damit der Benutzer sie nicht aktivieren kann. Sie können festlegen, dass ein Konto synchronisierbar und das andere nicht synchronisierbar ist (dsabled).
7. Beachten Sie ContentResolver.notifyChange ()
Eine knifflige Sache. ContentResolver.notifyChange()
ist eine Funktion, mit der ContentProvider
s Android benachrichtigt, dass die lokale Datenbank geändert wurde. Dies hat zwei Funktionen: Erstens führt dies dazu, dass Cursor, die diesem Inhalts-Uri folgen, aktualisiert werden und im Gegenzug ein ListView
usw. anfordern und ungültig machen und neu zeichnen. Es ist sehr magisch, die Datenbank ändert sich und IhreListView
nur automatisch aktualisiert. Genial. Wenn sich die Datenbank ändert, fordert Android auch außerhalb Ihres normalen Zeitplans die Synchronisierung für Sie an, damit diese Änderungen vom Gerät entfernt und so schnell wie möglich mit dem Server synchronisiert werden. Auch super.
Es gibt jedoch einen Randfall. Wenn Sie vom Server ziehen und ein Update in den Server schieben ContentProvider
, wird es pflichtbewusst aufgerufen notifyChange()
und Android sagt: "Oh, Datenbankänderungen, stellen Sie sie besser auf den Server!" (Doh!) Gut geschrieben ContentProviders
hat einige Tests, um festzustellen, ob die Änderungen vom Netzwerk oder vom Benutzer stammen, und setzt syncToNetwork
in diesem Fall das boolesche Flag auf false, um diese verschwenderische Doppelsynchronisierung zu verhindern. Wenn Sie Daten in a ContentProvider
einspeisen, müssen Sie herausfinden, wie dies funktioniert. Andernfalls führen Sie immer zwei Synchronisierungen durch, wenn nur eine benötigt wird.
8. Fühle dich glücklich!
Sobald Sie alle diese XML-Metadaten eingerichtet und die Synchronisierung aktiviert haben, weiß Android, wie Sie alles für Sie verbinden, und die Synchronisierung sollte beginnen. An diesem Punkt rasten viele Dinge, die schön sind, einfach ein und es wird sich sehr nach Magie anfühlen. Genießen!