2012-06-26 36 views
6

所以,我的问题重申是,当你去设置 - >帐户&同步并选择创建一个帐户,您的SyncAdapter正在与云服务器同步,并选择删除帐户,会发生什么,只要您的SyncAdapter ?有一个对话框显示要求您确认,并且与该帐户关联的电话上的数据将被删除。我不能轻易相信该框架可以自动删除我的SyncAdapter已存储在本地数据库中的数据,但似乎暗示删除该帐户将(并且我会同意应该)删除该数据。我的SyncAdapter是否还有一个额外的功能,可以作为删除帐户的回调来处理从本地数据库中删除所有适当的数据?也许它必须通过AccountManager来完成;我的AccountManager会在帐户被删除时得到通知,并从那里我可以触发数据删除,而不需要SyncAdapter当AccountManager删除帐户时SyncAdapter是否会得到通知?

编辑: 在相关说明中,同步管理器会在添加新帐户时为每个同步帐户调用我的SyncAdapter?我看到一个onPerformSync(...)正在为以前添加的帐户执行以及刚刚添加的帐户,并且希望阻止该帐户。

回答

7

我发现解决方案是让应用程序ContentProvider实施OnAccountsUpdateListener。附上ContentProvider作为一名听众在其onCreateaccount_manager.addOnAccountsUpdatedListener(this, null, false)然后执行类似

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

我构建了当前连接账户的String,然后建立与String一个SQL查询的接口方式。我在该查询的后台线程上对数据库执行删除操作,以删除与当前未连接的帐户关联的数据。我通知内容已更改,但不需要与服务器同步。

+0

你能详细解释一下你的答案吗?你在谈论什么'onCreate'? – akirk

+0

... ContentProvider,阅读更接近的第一行。我不知道你想要什么“精心制作”d –

+0

是否可以在ContentProviders生命周期中的相关位置删除OnAccountsUpdateListener? – fr1550n

5

不,但您的身份验证器[1]。被删除的帐户之前,此方法被称为:

AbstractAccountAuthenticator.getAccountRemovalAllowed(AccountAuthenticatorResponse, Account) 

帐户参数是要删除的帐户 - 默认行为是允许移除帐户:

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

..但我想这是一个钩子,你可以用它来整理或阻止帐户被删除,如果你想。

[1] - 这是一个肮脏的黑客;请参阅Dandre的评论。

+2

我不相信这种方法是用来“整理”的。鉴于其在AbstractAccountAuthenticator中的名称和位置,它可能用于防止可能用于您的应用的内部帐户在您的控制之外被删除。我没有亲自找到用例。对我而言,最大的意图是“get”作为前缀。您应该避免“获取”方法中的副作用,使流程难以遵循。您是否怀疑“获得”删除所有数据? –

+0

毫无疑问,你是正确的,这是一个肮脏的黑客。我将更新我的答案。 – fr1550n

3

另一种选择是注册AccountManager发出的android.accounts.LOGIN_ACCOUNTS_CHANGED广播。不幸的是,只要有任何帐户被更改并且广播没有提供更改的信息,则该广播被发送出

因此,您必须查询帐户经理并查看已有多少个“您的”帐户,并删除缺少的帐户的数据。

+0

好吧,@Dandre Allison上面的解决方案就是基于此。所以这个答案应该是首选。当你调用'addOnAccountsUpdatedListener'时,AccountManager正在注册一个动态广播接收器,它在'onReceive'中调用监听器。所以,它基本上是一样的。只要设备中的任何帐户(Google帐户,Twitter帐户等)发生更改,都会通知这两种解决方案。 – blindOSX

相关问题