2012-06-26 15 views
6

Moje pytanie zmienia się po przejściu do Ustawienia -> Konta & Synchronizuj i wybierz konto, które zostało utworzone, aby Twoja SyncAdapter była synchronizowana z serwerem w chmurze, i wybierz Usuń konto, co się dzieje, jeśli chodzi o twój numer SyncAdapter ? Pojawi się okno dialogowe z prośbą o potwierdzenie, a dane w telefonie powiązane z tym kontem zostaną usunięte. Nie mogę z łatwością uwierzyć, że framework może automatycznie usunąć dane przechowywane przez moją SyncAdapter w lokalnej bazie danych, ale wydaje się, że oznacza to, że usunięcie konta spowoduje (i zgodziłbym się, że to powinno) usunąć te dane. Czy istnieje dodatek do mojego SyncAdapter, który będzie służył jako wywołanie zwrotne dla usunięcia konta do obsługi usuwania wszystkich odpowiednich danych z lokalnej bazy danych? Może trzeba to zrobić poprzez AccountManager; mój AccountManager otrzymuje powiadomienie, gdy konto zostanie usunięte, a stamtąd mogę wyzwolić usunięcie danych bez numeru SyncAdapter.Czy SyncAdapter otrzyma powiadomienie, gdy AccountManager usunie konto?

EDYTOWANIE: Czy w powiązanej notatce menedżer synchronizacji dzwoni pod mój numer SyncAdapter dla każdego konta, które synchronizuje po dodaniu nowego konta? Widzę, że przy dodawaniu konta jest wykonywane onPerformSync(...) dla wcześniej dodanych kont wraz z dodanym kontem i chciałbym to zatrzymać.

Odpowiedz

7

Odkryłem, że rozwiązaniem jest wykonanie aplikacji . Zamocować ContentProvider jako detektor w onCreate sposobu z account_manager.addOnAccountsUpdatedListener(this, null, false) i zastosowania sposobu interfejsu jak

@Override 
public void onAccountsUpdated(final Account[] accounts) { 
    Ln.i("Accounts updated."); 
    final Iterable<String> account_list = new Iterable<String>() { 
     @Override 
     public Iterator<String> iterator() { 
      return new Iterator<String>() { 
       private final Iterator<Account> account_list = Arrays.asList(accounts).iterator(); 

       @Override 
       public boolean hasNext() { 
        return account_list.hasNext(); 
       } 

       /** Extracts the next account name and wraps it in single quotes. */ 
       @Override 
       public String next() { 
        return "'" + account_list.next().name + "'"; 
       } 

       @Override 
       public void remove() { throw new UnsupportedOperationException("Not implemented"); } 
      }; 
     } 
    }; 
    final String account_set = TextUtils.join(", ", account_list); 
    Ln.i("Current accounts: %s", account_set); 

    // Removes content that is associated with accounts that are not currently connected 
    final SelectionBuilder builder = new SelectionBuilder(); 
    builder.table(Tables.CALENDARS) 
      .where(Calendars.CALENDAR_USER + " NOT IN (?)", account_set); 

    new SafeAsyncTask() { 
     @Override 
     public Void call() throws Exception { 
      _model.openWritableDatabase(); 
      _model.delete(builder); 
      return null; 
     } 
    }.execute(); 


    getContext().getContentResolver().notifyChange(Calendars.NO_SYNC_URI, null, false); 
} 

skonstruować String z obecnie połączone konta, następnie utworzyć zapytań SQL z tym String. Wykonuję usuwanie w bazie danych w wątku w tle w tym zapytaniu, aby usunąć dane powiązane z kontami, które nie są aktualnie połączone. Powiadomię, że treść została zmieniona, ale nie musi być zsynchronizowana z serwerem.

+0

Czy mógłbyś nieco wyjaśnić swoją odpowiedź? O czym mówisz "onCreate"? – akirk

+0

... The ContentProvider, przeczytaj pierwszą linię bliżej.Nie wiem, co jeszcze chcesz "wymyślnego" d –

+0

Czy jest możliwe usunięcie OnAccountsUpdateListener w odpowiednim punkcie cyklu życia ContentProviders? – fr1550n

5

Nie, ale Twój Authenticator ma [1]. Ta metoda jest wywoływana zanim konto zostanie usunięte:

AbstractAccountAuthenticator.getAccountRemovalAllowed(AccountAuthenticatorResponse, Account) 

Konto param jest konto usunięciem - domyślne zachowanie, aby umożliwić usunięcie konta:

return super.getAccountRemovalAllowed(response, account); // returns Bundle[{booleanResult=true}] 

.. ale myślę, że to haczyk, którego możesz użyć do uporządkowania lub zablokowania konta, jeśli chcesz.

[1] - to jest brudny hack; zobacz komentarz Dandre.

+2

Nie sądzę, aby ta metoda była przeznaczona do "porządkowania rzeczy". Biorąc pod uwagę jego nazwę i lokalizację w 'AbstractAccountAuthenticator', jest to prawdopodobnie używane, aby zapobiec wewnętrznym kontom, których możesz użyć do usunięcia swojej aplikacji poza kontrolą. Nie znalazłem przypadkiem użycia osobiście. Głównym celem dla mnie jest "get" jako prefiks. Powinieneś unikać efektów ubocznych w metodach "get", utrudniając przepływ. Czy podejrzewasz "dostać", aby usunąć wszystkie swoje dane? –

+0

Bez wątpienia masz rację i to jest brudny hack. Zaktualizuję odpowiedź jako taką. – fr1550n

3

Inną opcją jest zarejestrowanie się do transmisji android.accounts.LOGIN_ACCOUNTS_CHANGED, którą wysyła AccountManager. Niestety, ta transmisja jest wysyłana po zmianie konta, a transmisja nie dostarcza dalszych informacji o tym, co się zmieniło.

Musisz więc zapytać menedżera konta i sprawdzić, ile pozostało "Twoich" kont i usunąć dane brakujących.

+0

Cóż, powyższe rozwiązanie @Dandre Allison opiera się na tym. Tak więc ta odpowiedź powinna być preferowana. Kiedy wywołujesz 'addOnAccountsUpdatedListener', AccountManager rejestruje dynamiczny odbiornik, który wywołuje detektor w swoim' onReceive'. Więc w zasadzie to samo. Oba rozwiązania są powiadamiane o każdej zmianie konta w urządzeniu (konto Google, konto Twitter itp.). – blindOSX