Does SyncAdapter get notified when AccountManager removes account?

后端 未结 3 1564
心在旅途
心在旅途 2020-12-30 14:46

So, my question restated is when you go to Settings -> Accounts & Sync and select the an account that was created that your SyncAdapter is syncing with a c

相关标签:
3条回答
  • 2020-12-30 15:06

    I discovered the solution is to make the app's ContentProvider implement OnAccountsUpdateListener. Attach the ContentProvider as a listener in its onCreate method with account_manager.addOnAccountsUpdatedListener(this, null, false) and then implement the interface method like

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

    I construct a String of the currently connected accounts, then build a SQL query with that String. I perform a delete on the database in a background thread on that query to remove the data associated with accounts not currently connected. And I notify that content changed, but does not need to synchronized with the server.

    0 讨论(0)
  • 2020-12-30 15:10

    Another option is to register for the android.accounts.LOGIN_ACCOUNTS_CHANGED broadcast that the AccountManager sends out. Unfortunately, this broadcast is sent out whenever any account is changed and the broadcast does not deliver further information what has changed either.

    So you'd have to query the account manager and look how many of "your" accounts it has left and delete the data of the missing ones.

    0 讨论(0)
  • 2020-12-30 15:22

    No, but your Authenticator does[1]. This method is called before the account is removed:

    AbstractAccountAuthenticator.getAccountRemovalAllowed(AccountAuthenticatorResponse, Account) 
    

    the Account param is the account being deleted - the default behaviour is to allow removal of the account:

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

    ..but I guess it's a hook that you can use to tidy things up or block the account being removed should you wish to.

    [1] - this is a dirty hack; please see Dandre's comment.

    0 讨论(0)
提交回复
热议问题