2012-06-26 13 views
6

Bu yüzden, Ayarlar -> Hesaplar & Eşitleme'ye gittiğinizde ve SyncAdapter kodunuzun bir bulut sunucusu ile senkronize edildiği bir hesabı seçip hesabınızı kaldırmayı seçtiyseniz, hesabınızı kaldırdığınızda, SyncAdapter ürününüzün ne olduğuyla ilgili olarak sorun giderildi. ? Onayınızı isteyen ve söz konusu hesapla ilişkilendirilen telefondaki verilerin kaldırılacağını gösteren bir iletişim kutusu vardır. Çerçevenin SyncAdapter veri tabanımdaki veriyi otomatik olarak kaldırabileceğine kolayca inanamıyorum, ancak hesabın kaldırılacağını (ve buna katılıyorum) bu verileri kaldıracağını ima ediyor gibi görünüyor. SyncAdapter'umda, yerel veritabanından tüm uygun verileri silme işleminin gerçekleştirilmesi için hesabın kaldırılması için bir geri çağrı olarak hizmet verecek bir ek var mı? Belki de bunun yerine AccountManager üzerinden yapılması gerekir; AccountManager hesabım kaldırılır ve oradan SyncAdapter olmadan veri silme işlemini tetikleyebilir bildirilir.AccountManager hesabı kaldırdığında SyncAdapter bildirilir mi?

DÜZENLEME: İlgili bir notta, yeni bir hesap eklendiğinde senkronize ettiği her hesap için SyncAdapter numaralı telefonumu arayarak senkronizasyon yöneticisidir. Bir hesap eklediğimde yeni eklenen hesapla birlikte daha önce eklenen hesaplar için çalıştırılan bir onPerformSync(...) görüyorum ve bunu durdurmak istiyorum.

cevap

7

Uygulamanın, uygulamanın ContentProvider uygulamasını OnAccountsUpdateListener gerçekleştirmesini sağlamak olduğunu keşfettim. account_manager.addOnAccountsUpdatedListener(this, null, false) ile onCreate yönteminde bir dinleyici olarak ContentProvider takın ve sonra o String ile bir SQL sorgusu oluşturmak, şu anda bağlı hesaplarının bir String inşa

@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); 
} 

gibi arayüz yöntemi uygulamak. Şu anda bağlı olmayan hesaplarla ilişkili verileri kaldırmak için veritabanında bir veritabanında bir silme işlemi gerçekleştiriyorum. Ve bu içeriğin değiştiğini, ancak sunucuyla senkronize edilmesine gerek olmadığını bildiriyorum.

+0

Cevabınızı biraz açıklayabilir misiniz? Ne hakkında konuşuyorsun? – akirk

+0

... ContentProvider, ilk satırı daha yakından okuyun.Daha ne istediğini bilmiyorum "ayrıntılı" d –

+0

OnAccountsUpdateListener öğesini ContentProviders yaşam döngüsünün ilgili noktasında kaldırmak mümkün mü? – fr1550n

5

Hayır, ancak Authenticator'ınız [1] yapar. Hesap kaldırılmadan önce bu yöntem denir:

AbstractAccountAuthenticator.getAccountRemovalAllowed(AccountAuthenticatorResponse, Account) 

Hesap param siliniyor hesabıdır - varsayılan davranış hesabın kaldırılmasını sağlamaktır:

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

.. ama sanırım istediğiniz şeyleri düzeltmek veya kaldırılmak istenen hesabı engellemek için kullanabileceğiniz bir kanca.

[1] - bu kirli bir kırılmadır; lütfen Dandre'nin görüşüne bakın.

+2

Yöntemin "işleri düzeltmek" için kullanılması gerektiğine inanmıyorum. “AbstractAccountAuthenticator” daki adı ve konumu göz önünde bulundurulduğunda, uygulamanızın kontrolünüz dışında sabitlenebilmesi için kullanabileceğiniz dahili hesapları engellemek için kullanılır. Şahsen kullanma vakası bulamadım. Benim için büyük niyet önek olarak "olsun". "Get" yöntemlerinde yan etkilerden kaçınmalısınız, akışı takip etmeyi zorlaştırır. Tüm verilerinizi silmek için "al" dan şüphelenir misiniz? –

+0

Şüphesiz doğru ve kirli bir hack. Cevabımı öyle güncelleyeceğim. – fr1550n

3

AccountManager'un gönderdiği android.accounts.LOGIN_ACCOUNTS_CHANGED yayını için başka bir seçenek de gönderilir. Ne yazık ki, herhangi bir hesabı değiştiğinde ve yayın ne değiştiyse daha fazla bilgi vermediğinde, bu yayın gönderilir.

Bu nedenle, hesap yöneticisini sorgulamanız ve kaç tane "hesabınızın" kaldığını görün ve eksik olanların verilerini silin.

+0

Eh, bu konuda @Dandre Allison tarafından çözüm buna dayanmaktadır. Yani bu cevap tercih edilmeli. "AddOnAccountsUpdatedListener" öğesini çağırdığınızda, AccountManager dinleyiciyi 'onReceive' olarak çağıran bir dinamik yayın alıcısı kaydediyor. Yani, temelde aynı. Cihazdaki herhangi bir hesap (Google hesabı, Twitter hesabı, vb.) Değiştirildiğinde her iki çözüm de bilgilendirilir. – blindOSX

İlgili konular