Wywołanie requestSync()
będzie działać tylko na parze {Account, ContentAuthority}, która jest znana w systemie. Twoja aplikacja musi wykonać szereg czynności, aby poinformować Androida, że możesz synchronizować określony rodzaj treści przy użyciu określonego rodzaju konta. Robi to w AndroidManifest.
1. Powiadom system Android, że pakiet aplikacji zapewnia synchronizację
Po pierwsze, w AndroidManifest.xml musisz zadeklarować, że masz usługę synchronizacji:
<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>
Atrybut name <service>
tagu to nazwa Twojej klasy, z którą chcesz się połączyć, synchronizować ... Porozmawiam o tym za chwilę.
Ustawienie exported true sprawia, że jest on widoczny dla innych komponentów (jest to potrzebne, aby ContentResolver
można było to wywołać).
Filtr intencji pozwala przechwycić intencję żądającą synchronizacji. (Wynika Intent
to z ContentResolver
wywołania ContentResolver.requestSync()
lub powiązanych metod planowania).
<meta-data>
Tag zostaną omówione poniżej.
2. Zapewnij Androidowi usługę używaną do znajdowania adaptera SyncAdapter
A więc sama klasa ... Oto przykład:
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();
}
}
Twoja klasa musi rozszerzać Service
lub jedną z jej podklas, musi implementować public IBinder onBind(Intent)
i musi zwracać, SyncAdapterBinder
gdy jest wywoływana ... Potrzebujesz zmiennej typu AbstractThreadedSyncAdapter
. Jak widać, to prawie wszystko w tej klasie. Jedynym powodem, dla którego istnieje, jest zapewnienie usługi, która oferuje standardowy interfejs dla Androida do wysyłania zapytań Twojej klasie o to, czym SyncAdapter
ona jest.
3. Podaj, class SyncAdapter
aby faktycznie wykonać synchronizację.
mySyncAdapter jest miejscem, w którym przechowywana jest sama logika synchronizacji. Jego onPerformSync()
metoda jest wywoływana, gdy nadejdzie czas na synchronizację. Myślę, że masz już to na miejscu.
4. Ustanów powiązanie między typem konta a uprawnieniami do treści
Patrząc ponownie na AndroidManifest, ten dziwny <meta-data>
tag w naszej usłudze jest kluczowym elementem, który ustanawia powiązanie między ContentAuthority a kontem. Zewnętrznie odwołuje się do innego pliku xml (nazwij go jak chcesz, coś związanego z twoją aplikacją). Spójrzmy na 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, więc co to robi? Mówi Androidowi, że zdefiniowany przez nas adapter synchronizacji (klasa, która została wywołana w elemencie name <service>
tagu zawierającym <meta-data>
tag odwołujący się do tego pliku ...) zsynchronizuje kontakty przy użyciu konta w stylu com.google.
Cała zawartość Ciągi autoryzacji muszą być zgodne i zgodne z tym, co synchronizujesz - powinien to być zdefiniowany przez Ciebie ciąg, jeśli tworzysz własną bazę danych, lub jeśli synchronizujesz znane, powinieneś użyć niektórych istniejących ciągów urządzeń typy danych (takie jak kontakty, wydarzenia w kalendarzu lub informacje o Tobie). Powyższe („com.android.contacts”) jest ciągiem ContentAuthority dla danych typu kontaktów (niespodzianka, niespodzianka).
accountType musi również pasować do jednego z tych znanych typów kont, które zostały już wprowadzone, lub musi pasować do tego, który tworzysz (obejmuje to utworzenie podklasy AccountAuthenticator w celu uzyskania autoryzacji na serwerze ... Warto sam artykuł). Ponownie „com.google” to zdefiniowany ciąg znaków identyfikujący dane logowania do konta w stylu ... google.com (znowu nie powinno to być zaskoczeniem).
5. Włącz synchronizację na danej parze Konto / ContentAuthority
Na koniec należy włączyć synchronizację. Możesz to zrobić na stronie Konta i synchronizacja w panelu sterowania, przechodząc do aplikacji i zaznaczając pole wyboru obok aplikacji na odpowiednim koncie. Alternatywnie możesz to zrobić w kodzie konfiguracji w swojej aplikacji:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Aby nastąpiła synchronizacja, Twoja para konto / uprawnienia musi być włączona do synchronizacji (jak powyżej), a ogólna flaga globalnej synchronizacji w systemie musi być ustawiona, a urządzenie musi mieć łączność z siecią.
Jeśli synchronizacja konta / uprawnień lub synchronizacja globalna są wyłączone, wywołanie RequestSync () ma wpływ - ustawia flagę, że zażądano synchronizacji i zostanie wykonana, gdy tylko synchronizacja zostanie włączona.
Ponadto, na mgv , ustawienie ContentResolver.SYNC_EXTRAS_MANUAL
na true w pakiecie dodatków twojego requestSync poprosi Androida o wymuszenie synchronizacji, nawet jeśli globalna synchronizacja jest wyłączona (szanuj tutaj swojego użytkownika!)
Na koniec możesz skonfigurować okresową zaplanowaną synchronizację, ponownie z funkcjami ContentResolver.
6. Rozważ konsekwencje wielu kont
Możliwe jest posiadanie więcej niż jednego konta tego samego typu (dwa konta @ gmail.com założone na jednym urządzeniu lub dwa konta na Facebooku, lub dwa konta na Twitterze, itd.). Należy rozważyć konsekwencje dla aplikacji. .. Jeśli masz dwa konta, prawdopodobnie nie chcesz próbować synchronizować ich obu w tych samych tabelach bazy danych. Może musisz określić, że tylko jeden może być aktywny w danym momencie, a także opróżnić tabele i ponownie zsynchronizować, jeśli zmienisz konto. (poprzez stronę właściwości, która pyta, jakie konta są obecne). Może tworzysz inną bazę danych dla każdego konta, może różne tabele, może kolumnę klucza w każdej tabeli. Wszystkie aplikacje specyficzne i warte przemyślenia. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
może być tutaj interesujące. setSyncAutomatically()
kontroluje, czy sprawdzana jest para konto / uprawnienia, czyniezaznaczone , ale setIsSyncable()
umożliwia odznaczenie i wyszarzenie linii, aby użytkownik nie mógł jej włączyć. Możesz ustawić jedno konto jako Syncable, a drugie jako Not Syncable (dsabled).
7. Pamiętaj o ContentResolver.notifyChange ()
Jedna trudna rzecz. ContentResolver.notifyChange()
to funkcja używana przez ContentProvider
s do powiadamiania systemu Android o zmianie lokalnej bazy danych. Służy to dwóm funkcjom, po pierwsze, spowoduje aktualizację kursorów podążających za tą zawartością uri, a następnie ponowne zażądanie, unieważnienie i ponowne narysowanie ListView
, itd. To bardzo magiczne, baza danych zmienia się, a ListView
po prostu aktualizuje się automatycznie. Niesamowite. Ponadto, gdy baza danych ulegnie zmianie, system Android zażąda synchronizacji, nawet poza normalnym harmonogramem, aby zmiany te zostały usunięte z urządzenia i zsynchronizowane z serwerem tak szybko, jak to możliwe. Również super.
Jest jednak jeden skrajny przypadek. Jeśli ściągniesz z serwera i wepchniesz aktualizację do ContentProvider
, to sumiennie zadzwoni, notifyChange()
a android powie: „Och, zmiany w bazie danych, lepiej umieść je na serwerze!” (Doh!) Dobrze napisany ContentProviders
będzie miał kilka testów, aby sprawdzić, czy zmiany pochodziły z sieci, czy od użytkownika, i ustawi syncToNetwork
flagę boolean na false, jeśli tak, aby zapobiec marnotrawnej podwójnej synchronizacji. Jeśli dostarczasz dane do a ContentProvider
, powinieneś dowiedzieć się, jak to działa - w przeciwnym razie zawsze będziesz wykonywać dwie synchronizacje, gdy tylko jedna będzie potrzebna.
8. Ciesz się!
Gdy masz już wszystkie te metadane xml i włączasz synchronizację, Android będzie wiedział, jak połączyć wszystko za Ciebie, a synchronizacja powinna zacząć działać. W tym momencie wiele fajnych rzeczy po prostu zatrzaśnie się na swoim miejscu i będzie to trochę jak magia. Cieszyć się!