1558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki/* 2558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Copyright (C) 2011 The Android Open Source Project 3558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 4558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 5558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * you may not use this file except in compliance with the License. 6558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * You may obtain a copy of the License at 7558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 8558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 9558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 10558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Unless required by applicable law or agreed to in writing, software 11558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 12558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * See the License for the specific language governing permissions and 14558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * limitations under the License. 15558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 16558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 17558669dab4109afebd19eade1f95a396215fb44dMakoto Onukipackage com.android.contacts.editor; 18558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 19558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport com.android.contacts.model.AccountType; 20558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport com.android.contacts.model.AccountTypeManager; 21558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport com.android.contacts.model.AccountWithDataSet; 22558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport com.google.common.annotations.VisibleForTesting; 23558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport com.google.common.collect.ImmutableList; 24558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport com.google.common.collect.Sets; 25558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 26558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.accounts.Account; 27558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.accounts.AccountManager; 28558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.app.Activity; 29558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.content.Context; 30558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.content.Intent; 31558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.content.SharedPreferences; 32558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.preference.PreferenceManager; 33558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.text.TextUtils; 34131e6ac666868645b48ae6932575d85751ff57c0Makoto Onukiimport android.util.Log; 35558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 36558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport java.util.ArrayList; 37558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport java.util.List; 38558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport java.util.Set; 39558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 40558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki/** 41558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Utility methods for the "account changed" notification in the new contact creation flow. 42558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 43558669dab4109afebd19eade1f95a396215fb44dMakoto Onukipublic class ContactEditorUtils { 44558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private static final String TAG = "ContactEditorUtils"; 45558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 46558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private static final String KEY_DEFAULT_ACCOUNT = "ContactEditorUtils_default_account"; 47558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private static final String KEY_KNOWN_ACCOUNTS = "ContactEditorUtils_known_accounts"; 48558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // Key to tell the first time launch. 49558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private static final String KEY_ANYTHING_SAVED = "ContactEditorUtils_anything_saved"; 50558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 51558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private static final List<AccountWithDataSet> EMPTY_ACCOUNTS = ImmutableList.of(); 52558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 53558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private static ContactEditorUtils sInstance; 54558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 55558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private final Context mContext; 56558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private final SharedPreferences mPrefs; 57558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private final AccountTypeManager mAccountTypes; 58558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 59558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private ContactEditorUtils(Context context) { 60558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki this(context, AccountTypeManager.getInstance(context)); 61558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 62558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 63558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki @VisibleForTesting 64558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki ContactEditorUtils(Context context, AccountTypeManager accountTypes) { 6542342a7e91b5076bc222802379e12b56272ca366Makoto Onuki mContext = context.getApplicationContext(); 66558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); 67558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki mAccountTypes = accountTypes; 68558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 69558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 70558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public static synchronized ContactEditorUtils getInstance(Context context) { 71558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (sInstance == null) { 72558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki sInstance = new ContactEditorUtils(context); 73558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 74558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return sInstance; 75558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 76558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 77558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki void cleanupForTest() { 78558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki mPrefs.edit().remove(KEY_DEFAULT_ACCOUNT).remove(KEY_KNOWN_ACCOUNTS) 79558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki .remove(KEY_ANYTHING_SAVED).apply(); 80558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 81558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 82131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki void removeDefaultAccountForTest() { 83131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki mPrefs.edit().remove(KEY_DEFAULT_ACCOUNT).apply(); 84131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 85131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki 86131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki /** 87131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki * Sets the {@link #KEY_KNOWN_ACCOUNTS} and {@link #KEY_DEFAULT_ACCOUNT} preference values to 88131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki * empty strings to reset the state of the preferences file. 89131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki */ 90131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki private void resetPreferenceValues() { 91131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki mPrefs.edit().putString(KEY_KNOWN_ACCOUNTS, "").putString(KEY_DEFAULT_ACCOUNT, "").apply(); 92131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 93131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki 94558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private List<AccountWithDataSet> getWritableAccounts() { 95558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return mAccountTypes.getAccounts(true); 96558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 97558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 98558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 99558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * @return true if it's the first launch and {@link #saveDefaultAndAllAccounts} has never 100558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * been called. 101558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 102558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private boolean isFirstLaunch() { 103558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return !mPrefs.getBoolean(KEY_ANYTHING_SAVED, false); 104558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 105558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 106558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 107558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Saves all writable accounts and the default account, which can later be obtained 108558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * with {@link #getDefaultAccount}. 109558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 110558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * This should be called when saving a newly created contact. 111558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 112558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * @param defaultAccount the account used to save a newly created contact. Or pass {@code null} 113558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * If the user selected "local only". 114558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 115558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public void saveDefaultAndAllAccounts(AccountWithDataSet defaultAccount) { 116131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki final SharedPreferences.Editor editor = mPrefs.edit() 117131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki .putBoolean(KEY_ANYTHING_SAVED, true); 118131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki 119131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki if (defaultAccount == null) { 120131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // If the default is "local only", there should be no writable accounts. 121131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // This should always be the case with our spec, but because we load the account list 122131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // asynchronously using a worker thread, it is possible that there are accounts at this 123131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // point. So if the default is null always clear the account list. 124131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki editor.putString(KEY_KNOWN_ACCOUNTS, ""); 125131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki editor.putString(KEY_DEFAULT_ACCOUNT, ""); 126131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } else { 127131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki editor.putString(KEY_KNOWN_ACCOUNTS, 128131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki AccountWithDataSet.stringifyList(getWritableAccounts())); 129131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki editor.putString(KEY_DEFAULT_ACCOUNT, defaultAccount.stringify()); 130131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 131131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki editor.apply(); 132558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 133558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 134558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 135558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * @return the default account saved with {@link #saveDefaultAndAllAccounts}. 136558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 137558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Note the {@code null} return value can mean either {@link #saveDefaultAndAllAccounts} has 138558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * never been called, or {@code null} was passed to {@link #saveDefaultAndAllAccounts} -- 139558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * i.e. the user selected "local only". 140558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 141558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Also note that the returned account may have been removed already. 142558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 143558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public AccountWithDataSet getDefaultAccount() { 144558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final String saved = mPrefs.getString(KEY_DEFAULT_ACCOUNT, null); 145558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (TextUtils.isEmpty(saved)) { 146558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return null; 147558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 148131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki try { 149131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki return AccountWithDataSet.unstringify(saved); 150131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } catch (IllegalArgumentException exception) { 151131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki Log.e(TAG, "Error with retrieving default account " + exception.toString()); 152131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // unstringify()can throw an exception if the string is not in an expected format. 153131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // Hence, if the preferences file is corrupt, just reset the preference values 154131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki resetPreferenceValues(); 155131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki return null; 156131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 157558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 158558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 159558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 160558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * @return true if an account still exists. {@code null} is considered "local only" here, 161558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * so it's valid too. 162558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 163558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki @VisibleForTesting 164558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki boolean isValidAccount(AccountWithDataSet account) { 165558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (account == null) { 166558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return true; // It's "local only" account, which is valid. 167558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 168558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return getWritableAccounts().contains(account); 169558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 170558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 171558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 172558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * @return saved known accounts, or an empty list if none has been saved yet. 173558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 174558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki @VisibleForTesting 175558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki List<AccountWithDataSet> getSavedAccounts() { 176558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final String saved = mPrefs.getString(KEY_KNOWN_ACCOUNTS, null); 177558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (TextUtils.isEmpty(saved)) { 178558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return EMPTY_ACCOUNTS; 179558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 180131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki try { 181131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki return AccountWithDataSet.unstringifyList(saved); 182131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } catch (IllegalArgumentException exception) { 183131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki Log.e(TAG, "Error with retrieving saved accounts " + exception.toString()); 184131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // unstringifyList()can throw an exception if the string is not in an expected format. 185131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // Hence, if the preferences file is corrupt, just reset the preference values 186131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki resetPreferenceValues(); 187131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki return EMPTY_ACCOUNTS; 188131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 189558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 190558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 191558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 192558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * @return true if the contact editor should show the "accounts changed" notification, that is: 193558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * - If it's the first launch. 194558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * - Or, if an account has been added. 195558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * - Or, if the default account has been removed. 196131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki * (And some extra sanity check) 197558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 198558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Note if this method returns {@code false}, the caller can safely assume that 199558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link #getDefaultAccount} will return a valid account. (Either an account which still 200558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * exists, or {@code null} which should be interpreted as "local only".) 201558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 202558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public boolean shouldShowAccountChangedNotification() { 203558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (isFirstLaunch()) { 204558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return true; 205558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 206558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 207558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // Account added? 208558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final List<AccountWithDataSet> savedAccounts = getSavedAccounts(); 209131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki final List<AccountWithDataSet> currentWritableAccounts = getWritableAccounts(); 210131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki for (AccountWithDataSet account : currentWritableAccounts) { 211558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (!savedAccounts.contains(account)) { 212558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return true; // New account found. 213558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 214558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 215558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 216131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki final AccountWithDataSet defaultAccount = getDefaultAccount(); 217131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki 218558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // Does default account still exist? 219131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki if (!isValidAccount(defaultAccount)) { 220131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki return true; 221131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 222131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki 223131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // If there is an inconsistent state in the preferences file - default account is null 224131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // ("local" account) while there are multiple accounts, then show the notification dialog. 225131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // This shouldn't ever happen, but this should allow the user can get back into a normal 226131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki // state after they respond to the notification. 227131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki if (defaultAccount == null && currentWritableAccounts.size() > 0) { 228131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki Log.e(TAG, "Preferences file in an inconsistent state, request that the default account" 229131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki + " and current writable accounts be saved again"); 230558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return true; 231558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 232558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 233558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // All good. 234558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return false; 235558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 236558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 237558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki @VisibleForTesting 238558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki String[] getWritableAccountTypeStrings() { 239558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final Set<String> types = Sets.newHashSet(); 240558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki for (AccountType type : mAccountTypes.getAccountTypes(true)) { 241558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki types.add(type.accountType); 242558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 243558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return types.toArray(new String[types.size()]); 244558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 245558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 246558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 247558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Create an {@link Intent} to start "add new account" setup wizard. Selectable account 248558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * types will be limited to ones that supports editing contacts. 249558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 250558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Use {@link Activity#startActivityForResult} or 251558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link android.app.Fragment#startActivityForResult} to start the wizard, and 252558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link Activity#onActivityResult} or {@link android.app.Fragment#onActivityResult} to 253558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * get the result. 254558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 255558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public Intent createAddWritableAccountIntent() { 256558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return AccountManager.newChooseAccountIntent( 257558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // selectedAccount 258558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki new ArrayList<Account>(), // allowableAccounts 259558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki getWritableAccountTypeStrings(), // allowableAccountTypes 260558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki false, // alwaysPromptForAccount 261558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // descriptionOverrideText 262558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // addAccountAuthTokenType 263558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // addAccountRequiredFeatures 264558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null // addAccountOptions 265558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki ); 266558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 267558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 268558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 269558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Parses a result from {@link #createAddWritableAccountIntent} and returns the created 270558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link Account}, or null if the user has canceled the wizard. Pass the {@code resultCode} 271558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * and {@code data} parameters passed to {@link Activity#onActivityResult} or 272558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link android.app.Fragment#onActivityResult}. 273558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 274558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Note although the return type is {@link AccountWithDataSet}, return values from this method 275558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * will never have {@link AccountWithDataSet#dataSet} set, as there's no way to create an 276558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * extension package account from setup wizard. 277558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 278558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public AccountWithDataSet getCreatedAccount(int resultCode, Intent resultData) { 279558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // Javadoc doesn't say anything about resultCode but that the data intent will be non null 280558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // on success. 281558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (resultData == null) return null; 282558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 283558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final String accountType = resultData.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE); 284558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final String accountName = resultData.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); 285558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 286558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // Just in case 287558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(accountName)) return null; 288558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 289558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return new AccountWithDataSet(accountName, accountType, null); 290558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 291558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki} 292