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