ContactEditorUtils.java revision 69c182afb0e6d82a341a28b4317aa703af768906
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 android.accounts.Account; 20558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.accounts.AccountManager; 21558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.app.Activity; 227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.ContentUris; 23558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.content.Context; 24558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.content.Intent; 257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.net.Uri; 267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract; 27558669dab4109afebd19eade1f95a396215fb44dMakoto Onukiimport android.text.TextUtils; 28558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 2969c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.AccountTypeManager; 3069c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountType; 3169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountWithDataSet; 3269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.preference.ContactsPreferences; 33e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.annotations.VisibleForTesting; 34e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Sets; 35e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 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 46949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott private final ContactsPreferences mContactsPrefs; 47558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private final AccountTypeManager mAccountTypes; 48558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 49558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private ContactEditorUtils(Context context) { 50558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki this(context, AccountTypeManager.getInstance(context)); 51558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 52558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 53558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki @VisibleForTesting 54558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki ContactEditorUtils(Context context, AccountTypeManager accountTypes) { 55949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott mContactsPrefs = new ContactsPreferences(context); 56558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki mAccountTypes = accountTypes; 57558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 58558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 59949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott public static ContactEditorUtils create(Context context) { 60949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott return new ContactEditorUtils(context.getApplicationContext()); 61558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 62558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang /** 647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang * Returns a legacy version of the given contactLookupUri if a legacy Uri was originally 657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang * passed to the contact editor. 667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang * 677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang * @param contactLookupUri The Uri to possibly convert to legacy format. 687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang * @param requestLookupUri The lookup Uri originally passed to the contact editor 697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang * (via Intent data), may be null. 707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang */ 717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang static Uri maybeConvertToLegacyLookupUri(Context context, Uri contactLookupUri, 727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang Uri requestLookupUri) { 737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang final String legacyAuthority = "contacts"; 747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang final String requestAuthority = requestLookupUri == null 757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang ? null : requestLookupUri.getAuthority(); 767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang if (legacyAuthority.equals(requestAuthority)) { 777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang // Build a legacy Uri if that is what was requested by caller 787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang final long contactId = ContentUris.parseId(ContactsContract.Contacts.lookupContact( 797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang context.getContentResolver(), contactLookupUri)); 807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang final Uri legacyContentUri = Uri.parse("content://contacts/people"); 817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang return ContentUris.withAppendedId(legacyContentUri, contactId); 827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang } 837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang // Otherwise pass back a lookup-style Uri 847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang return contactLookupUri; 857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang } 867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang 87558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki void cleanupForTest() { 88949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott mContactsPrefs.clearDefaultAccount(); 89558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 90558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 91131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki void removeDefaultAccountForTest() { 92949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott mContactsPrefs.clearDefaultAccount(); 93131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 94131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki 95558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki private List<AccountWithDataSet> getWritableAccounts() { 96558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return mAccountTypes.getAccounts(true); 97558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 98558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 99558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 100949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott * Saves the default account, which can later be obtained with {@link #getOnlyOrDefaultAccount}. 101558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 102558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * This should be called when saving a newly created contact. 103558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 104fac695a36b227f5591eac064ded8e8dad3398400Marcus Hagerott * @param defaultAccount the account used to save a newly created contact. 105558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 106949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott public void saveDefaultAccount(AccountWithDataSet defaultAccount) { 107fac695a36b227f5591eac064ded8e8dad3398400Marcus Hagerott if (defaultAccount == null) { 108949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott mContactsPrefs.clearDefaultAccount(); 109131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } else { 110949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott mContactsPrefs.setDefaultAccount(defaultAccount); 111131e6ac666868645b48ae6932575d85751ff57c0Makoto Onuki } 112558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 113558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 114558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 115949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott * @return the first account if there is only a single account or the default account saved 116949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott * with {@link #saveDefaultAccount}. 117558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 118949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott * A null return value indicates that there is multiple accounts and a default hasn't been set 119558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 120558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Also note that the returned account may have been removed already. 121558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 122949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott public AccountWithDataSet getOnlyOrDefaultAccount() { 1234abdee91084b6ee89f1ef1a8b797a5a2e0272059Tingting Wang final List<AccountWithDataSet> currentWritableAccounts = getWritableAccounts(); 1244abdee91084b6ee89f1ef1a8b797a5a2e0272059Tingting Wang if (currentWritableAccounts.size() == 1) { 1254abdee91084b6ee89f1ef1a8b797a5a2e0272059Tingting Wang return currentWritableAccounts.get(0); 1264abdee91084b6ee89f1ef1a8b797a5a2e0272059Tingting Wang } 1274abdee91084b6ee89f1ef1a8b797a5a2e0272059Tingting Wang 128949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott return mContactsPrefs.getDefaultAccount(); 129558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 130558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 131558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public boolean shouldShowAccountChangedNotification() { 132949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott return mContactsPrefs.shouldShowAccountChangedNotification(getWritableAccounts()); 133558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 134558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 1353107b25dcaea54943c58f984084fa9b348ea1885Gary Mai /** 1363107b25dcaea54943c58f984084fa9b348ea1885Gary Mai * Sets the only non-device account to be default if it is not already. 1373107b25dcaea54943c58f984084fa9b348ea1885Gary Mai */ 1383107b25dcaea54943c58f984084fa9b348ea1885Gary Mai public void maybeUpdateDefaultAccount() { 1393107b25dcaea54943c58f984084fa9b348ea1885Gary Mai final List<AccountWithDataSet> currentWritableAccounts = getWritableAccounts(); 1403107b25dcaea54943c58f984084fa9b348ea1885Gary Mai if (currentWritableAccounts.size() == 1) { 1413107b25dcaea54943c58f984084fa9b348ea1885Gary Mai final AccountWithDataSet onlyAccount = currentWritableAccounts.get(0); 1423107b25dcaea54943c58f984084fa9b348ea1885Gary Mai if (!onlyAccount.isNullAccount() 1433107b25dcaea54943c58f984084fa9b348ea1885Gary Mai && !onlyAccount.equals(mContactsPrefs.getDefaultAccount())) { 1443107b25dcaea54943c58f984084fa9b348ea1885Gary Mai mContactsPrefs.setDefaultAccount(onlyAccount); 1453107b25dcaea54943c58f984084fa9b348ea1885Gary Mai } 1463107b25dcaea54943c58f984084fa9b348ea1885Gary Mai } 1473107b25dcaea54943c58f984084fa9b348ea1885Gary Mai } 1483107b25dcaea54943c58f984084fa9b348ea1885Gary Mai 149558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki @VisibleForTesting 150558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki String[] getWritableAccountTypeStrings() { 151558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final Set<String> types = Sets.newHashSet(); 152558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki for (AccountType type : mAccountTypes.getAccountTypes(true)) { 153558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki types.add(type.accountType); 154558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 155558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return types.toArray(new String[types.size()]); 156558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 157558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 158558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 159558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Create an {@link Intent} to start "add new account" setup wizard. Selectable account 160558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * types will be limited to ones that supports editing contacts. 161558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 162558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Use {@link Activity#startActivityForResult} or 163558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link android.app.Fragment#startActivityForResult} to start the wizard, and 164558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link Activity#onActivityResult} or {@link android.app.Fragment#onActivityResult} to 165558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * get the result. 166558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 167558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public Intent createAddWritableAccountIntent() { 168558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return AccountManager.newChooseAccountIntent( 169558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // selectedAccount 170558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki new ArrayList<Account>(), // allowableAccounts 171558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki getWritableAccountTypeStrings(), // allowableAccountTypes 172558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki false, // alwaysPromptForAccount 173558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // descriptionOverrideText 174558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // addAccountAuthTokenType 175558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null, // addAccountRequiredFeatures 176558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki null // addAccountOptions 177558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki ); 178558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 179558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 180558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki /** 181558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Parses a result from {@link #createAddWritableAccountIntent} and returns the created 182558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link Account}, or null if the user has canceled the wizard. Pass the {@code resultCode} 183558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * and {@code data} parameters passed to {@link Activity#onActivityResult} or 184558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * {@link android.app.Fragment#onActivityResult}. 185558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * 186558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * Note although the return type is {@link AccountWithDataSet}, return values from this method 187558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * will never have {@link AccountWithDataSet#dataSet} set, as there's no way to create an 188558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki * extension package account from setup wizard. 189558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki */ 190558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki public AccountWithDataSet getCreatedAccount(int resultCode, Intent resultData) { 191558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // Javadoc doesn't say anything about resultCode but that the data intent will be non null 192558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // on success. 193558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (resultData == null) return null; 194558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 195558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final String accountType = resultData.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE); 196558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki final String accountName = resultData.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); 197558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 198558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki // Just in case 199558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(accountName)) return null; 200558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki 201558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki return new AccountWithDataSet(accountName, accountType, null); 202558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki } 203558669dab4109afebd19eade1f95a396215fb44dMakoto Onuki} 204