ContactLoaderFragment.java revision 2a45e35ab3273c8901d9df3671e51614dc0250c6
12eb969cc399d87b659a45568fa951d394c216917Katherine Kuan/* 22eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Copyright (C) 2011 The Android Open Source Project 32eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * 42eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Licensed under the Apache License, Version 2.0 (the "License"); 52eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * you may not use this file except in compliance with the License. 62eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * You may obtain a copy of the License at 72eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * 82eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * http://www.apache.org/licenses/LICENSE-2.0 92eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * 102eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Unless required by applicable law or agreed to in writing, software 112eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * distributed under the License is distributed on an "AS IS" BASIS, 122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * See the License for the specific language governing permissions and 142eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * limitations under the License 152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 172eb969cc399d87b659a45568fa951d394c216917Katherine Kuanpackage com.android.contacts.detail; 182eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 192eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport com.android.contacts.ContactLoader; 20683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelsonimport com.android.contacts.ContactSaveService; 212eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport com.android.contacts.R; 2258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener; 2358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport com.android.contacts.util.PhoneCapabilityTester; 242eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport com.android.internal.util.Objects; 252eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 262eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.Activity; 272eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.Fragment; 282eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.LoaderManager; 292eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.LoaderManager.LoaderCallbacks; 3058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.content.ActivityNotFoundException; 312eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.content.Context; 3258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.content.Intent; 332eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.content.Loader; 34683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelsonimport android.media.RingtoneManager; 352eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.net.Uri; 36410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoroimport android.os.AsyncTask; 372eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.os.Bundle; 38410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoroimport android.provider.ContactsContract; 3958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.provider.ContactsContract.Contacts; 402eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.util.Log; 4158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.KeyEvent; 422eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.LayoutInflater; 4358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.Menu; 4458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.MenuInflater; 4558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.MenuItem; 462eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.View; 472eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.ViewGroup; 4858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.widget.Toast; 492eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 502eb969cc399d87b659a45568fa951d394c216917Katherine Kuan/** 512eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * This is an invisible worker {@link Fragment} that loads the contact details for the contact card. 522eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * The data is then passed to the listener, who can then pass the data to other {@link View}s. 532eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 5458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanpublic class ContactLoaderFragment extends Fragment implements FragmentKeyListener { 552eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 562eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private static final String TAG = ContactLoaderFragment.class.getSimpleName(); 572eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 58683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson /** The launch code when picking a ringtone */ 59683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson private static final int REQUEST_CODE_PICK_RINGTONE = 1; 60683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 61683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 6258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan private boolean mOptionsMenuOptions; 6358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan private boolean mOptionsMenuEditable; 6458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan private boolean mOptionsMenuShareable; 65683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson private boolean mSendToVoicemailState; 66683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson private String mCustomRingtone; 6758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 682eb969cc399d87b659a45568fa951d394c216917Katherine Kuan /** 692eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * This is a listener to the {@link ContactLoaderFragment} and will be notified when the 7058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan * contact details have finished loading or if the user selects any menu options. 712eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 722eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public static interface ContactLoaderFragmentListener { 7358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan /** 7458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan * Contact was not found, so somehow close this fragment. This is raised after a contact 7558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan * is removed via Menu/Delete 7658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan */ 7758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public void onContactNotFound(); 7858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 7958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan /** 8058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan * Contact details have finished loading. 8158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan */ 822eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void onDetailsLoaded(ContactLoader.Result result); 8358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 8458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan /** 8558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan * User decided to go to Edit-Mode 8658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan */ 8758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public void onEditRequested(Uri lookupUri); 8858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 8958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan /** 9058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan * User decided to delete the contact 9158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan */ 9258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public void onDeleteRequested(Uri lookupUri); 9358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 942eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 952eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 962eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private static final int LOADER_DETAILS = 1; 972eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private static final String KEY_CONTACT_URI = "contactUri"; 992eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private static final String LOADER_ARG_CONTACT_URI = "contactUri"; 1002eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1012eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private Context mContext; 1022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private Uri mLookupUri; 1032eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private ContactLoaderFragmentListener mListener; 1042eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1052eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private ContactLoader.Result mContactData; 1062eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1072eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public ContactLoaderFragment() { 1082eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1092eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1102eb969cc399d87b659a45568fa951d394c216917Katherine Kuan @Override 1112eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void onCreate(Bundle savedInstanceState) { 1122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan super.onCreate(savedInstanceState); 1132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (savedInstanceState != null) { 1142eb969cc399d87b659a45568fa951d394c216917Katherine Kuan mLookupUri = savedInstanceState.getParcelable(KEY_CONTACT_URI); 1152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1172eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1182eb969cc399d87b659a45568fa951d394c216917Katherine Kuan @Override 1192eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void onSaveInstanceState(Bundle outState) { 1202eb969cc399d87b659a45568fa951d394c216917Katherine Kuan super.onSaveInstanceState(outState); 1212eb969cc399d87b659a45568fa951d394c216917Katherine Kuan outState.putParcelable(KEY_CONTACT_URI, mLookupUri); 1222eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1232eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1242eb969cc399d87b659a45568fa951d394c216917Katherine Kuan @Override 1252eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void onAttach(Activity activity) { 1262eb969cc399d87b659a45568fa951d394c216917Katherine Kuan super.onAttach(activity); 1272eb969cc399d87b659a45568fa951d394c216917Katherine Kuan mContext = activity; 1282eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1292eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1302eb969cc399d87b659a45568fa951d394c216917Katherine Kuan @Override 1312eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 13258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan setHasOptionsMenu(true); 1339c0e8ac3a90e01ebca4b83f1f8ef78e9e98a9922Makoto Onuki // This is an invisible view. This fragment is declared in a layout, so it can't be 1349c0e8ac3a90e01ebca4b83f1f8ef78e9e98a9922Makoto Onuki // "viewless". (i.e. can't return null here.) 1359c0e8ac3a90e01ebca4b83f1f8ef78e9e98a9922Makoto Onuki // See also the comment in the layout file. 1362eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return inflater.inflate(R.layout.contact_detail_loader_fragment, container, false); 1372eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1382eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1392eb969cc399d87b659a45568fa951d394c216917Katherine Kuan @Override 1402eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void onActivityCreated(Bundle savedInstanceState) { 1412eb969cc399d87b659a45568fa951d394c216917Katherine Kuan super.onActivityCreated(savedInstanceState); 1422eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1432eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (mLookupUri != null) { 1442eb969cc399d87b659a45568fa951d394c216917Katherine Kuan Bundle args = new Bundle(); 1452eb969cc399d87b659a45568fa951d394c216917Katherine Kuan args.putParcelable(LOADER_ARG_CONTACT_URI, mLookupUri); 1462eb969cc399d87b659a45568fa951d394c216917Katherine Kuan getLoaderManager().initLoader(LOADER_DETAILS, args, mDetailLoaderListener); 1472eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1482eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1492eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1502eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void loadUri(Uri lookupUri) { 1512eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (Objects.equal(lookupUri, mLookupUri)) { 1522eb969cc399d87b659a45568fa951d394c216917Katherine Kuan // Same URI, no need to load the data again 1532eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 1542eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1552eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1562eb969cc399d87b659a45568fa951d394c216917Katherine Kuan mLookupUri = lookupUri; 1572eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (mLookupUri == null) { 1582eb969cc399d87b659a45568fa951d394c216917Katherine Kuan getLoaderManager().destroyLoader(LOADER_DETAILS); 1592eb969cc399d87b659a45568fa951d394c216917Katherine Kuan mContactData = null; 1602eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (mListener != null) { 1612eb969cc399d87b659a45568fa951d394c216917Katherine Kuan mListener.onDetailsLoaded(mContactData); 1622eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1632eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } else if (getActivity() != null) { 1642eb969cc399d87b659a45568fa951d394c216917Katherine Kuan Bundle args = new Bundle(); 1652eb969cc399d87b659a45568fa951d394c216917Katherine Kuan args.putParcelable(LOADER_ARG_CONTACT_URI, mLookupUri); 1662eb969cc399d87b659a45568fa951d394c216917Katherine Kuan getLoaderManager().restartLoader(LOADER_DETAILS, args, mDetailLoaderListener); 1672eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1682eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1692eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1702eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void setListener(ContactLoaderFragmentListener value) { 1712eb969cc399d87b659a45568fa951d394c216917Katherine Kuan mListener = value; 1722eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1732eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1742eb969cc399d87b659a45568fa951d394c216917Katherine Kuan /** 1752eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * The listener for the detail loader 1762eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 1772eb969cc399d87b659a45568fa951d394c216917Katherine Kuan private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDetailLoaderListener = 1782eb969cc399d87b659a45568fa951d394c216917Katherine Kuan new LoaderCallbacks<ContactLoader.Result>() { 1792eb969cc399d87b659a45568fa951d394c216917Katherine Kuan @Override 1802eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) { 1812eb969cc399d87b659a45568fa951d394c216917Katherine Kuan Uri lookupUri = args.getParcelable(LOADER_ARG_CONTACT_URI); 1823915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro return new ContactLoader(mContext, lookupUri, true /* loadGroupMetaData */, 1833e6991e5ee91ea2cc82a02bd3ea4ed7e941b08afMakoto Onuki true /* loadStreamItems */, true /* load invitable account types */); 1842eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1852eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1862eb969cc399d87b659a45568fa951d394c216917Katherine Kuan @Override 1872eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) { 188685157e0635ee33350d3dd1c6551e188d3df9f22Daniel Lehmann if (!mLookupUri.equals(data.getRequestedUri())) { 1892eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 1902eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 1912eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 1929e7b5da669fcf92a6a627fb720749e5cb627684aMakoto Onuki if (data.isError()) { 1933acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan // This shouldn't ever happen, so throw an exception. The {@link ContactLoader} 1943acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan // should log the actual exception. 1959e7b5da669fcf92a6a627fb720749e5cb627684aMakoto Onuki throw new IllegalStateException("Failed to load contact", data.getException()); 1962621c5bb7049401c8bce740005fa60bf1b304b86Makoto Onuki } else if (data.isNotFound()) { 1972eb969cc399d87b659a45568fa951d394c216917Katherine Kuan Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri()); 1982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan mContactData = null; 1993acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan } else { 2003acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan mContactData = data; 2012eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 2022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 2032eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (mListener != null) { 20458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan if (mContactData == null) { 20558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan mListener.onContactNotFound(); 20658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } else { 20758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan mListener.onDetailsLoaded(mContactData); 20858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 2092eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 210683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Make sure the options menu is setup correctly with the loaded data. 211683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson getActivity().invalidateOptionsMenu(); 2122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 2132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 2144ff31284ff6bd263621771bbfa6b24e0da5af031Daniel Lehmann @Override 215fab516143c60565b9cc0d18fbe0af33902764546Katherine Kuan public void onLoaderReset(Loader<ContactLoader.Result> loader) {} 2162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan }; 21758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 21858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan @Override 21958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { 22058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan inflater.inflate(R.menu.view_contact, menu); 22158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 22258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 22358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public boolean isOptionsMenuChanged() { 22458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return mOptionsMenuOptions != isContactOptionsChangeEnabled() 22558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan || mOptionsMenuEditable != isContactEditable() 22658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan || mOptionsMenuShareable != isContactShareable(); 22758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 22858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 22958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan @Override 23058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public void onPrepareOptionsMenu(Menu menu) { 23158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan mOptionsMenuOptions = isContactOptionsChangeEnabled(); 23258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan mOptionsMenuEditable = isContactEditable(); 23358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan mOptionsMenuShareable = isContactShareable(); 234683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson if (mContactData != null) { 235683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mSendToVoicemailState = mContactData.isSendToVoicemail(); 236683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mCustomRingtone = mContactData.getCustomRingtone(); 237683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 23858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 239683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Hide telephony-related settings (ringtone, send to voicemail) 240683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // if we don't have a telephone 241683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson final MenuItem optionsSendToVoicemail = menu.findItem(R.id.menu_send_to_voicemail); 242683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson if (optionsSendToVoicemail != null) { 243683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson optionsSendToVoicemail.setChecked(mSendToVoicemailState); 244683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson optionsSendToVoicemail.setVisible(mOptionsMenuOptions); 245683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 246683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson final MenuItem optionsRingtone = menu.findItem(R.id.menu_set_ringtone); 247683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson if (optionsRingtone != null) { 248683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson optionsRingtone.setVisible(mOptionsMenuOptions); 249683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 25058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 25158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan final MenuItem editMenu = menu.findItem(R.id.menu_edit); 25258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan editMenu.setVisible(mOptionsMenuEditable); 25358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 25458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan final MenuItem deleteMenu = menu.findItem(R.id.menu_delete); 25558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan deleteMenu.setVisible(mOptionsMenuEditable); 25658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 25758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan final MenuItem shareMenu = menu.findItem(R.id.menu_share); 25858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan shareMenu.setVisible(mOptionsMenuShareable); 25958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 26058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 26158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public boolean isContactOptionsChangeEnabled() { 26258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return mContactData != null && !mContactData.isDirectoryEntry() 26358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan && PhoneCapabilityTester.isPhone(mContext); 26458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 26558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 26658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public boolean isContactEditable() { 26758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return mContactData != null && !mContactData.isDirectoryEntry(); 26858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 26958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 27058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public boolean isContactShareable() { 2714ff31284ff6bd263621771bbfa6b24e0da5af031Daniel Lehmann return mContactData != null && !mContactData.isDirectoryEntry(); 27258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 27358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 27458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan @Override 27558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public boolean onOptionsItemSelected(MenuItem item) { 27658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan switch (item.getItemId()) { 27758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan case R.id.menu_edit: { 27858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan if (mListener != null) mListener.onEditRequested(mLookupUri); 27958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan break; 28058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 28158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan case R.id.menu_delete: { 28258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan if (mListener != null) mListener.onDeleteRequested(mLookupUri); 28358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return true; 28458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 285683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson case R.id.menu_set_ringtone: { 28658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan if (mContactData == null) return false; 287683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson doPickRingtone(); 28858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return true; 28958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 29058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan case R.id.menu_share: { 29158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan if (mContactData == null) return false; 29258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 29358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan final String lookupKey = mContactData.getLookupKey(); 294410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey); 295410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro if (mContactData.isUserProfile()) { 296410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro // User is sharing the profile. We don't want to force the receiver to have 297410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro // the highly-privileged READ_PROFILE permission, so we need to request a 298410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro // pre-authorized URI from the provider. 299410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro shareUri = getPreAuthorizedUri(shareUri); 300410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro } 30158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 30258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan final Intent intent = new Intent(Intent.ACTION_SEND); 30358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan intent.setType(Contacts.CONTENT_VCARD_TYPE); 30458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan intent.putExtra(Intent.EXTRA_STREAM, shareUri); 30558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 30658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan // Launch chooser to share contact via 30758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan final CharSequence chooseTitle = mContext.getText(R.string.share_via); 30858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan final Intent chooseIntent = Intent.createChooser(intent, chooseTitle); 30958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 31058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan try { 31158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan mContext.startActivity(chooseIntent); 31258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } catch (ActivityNotFoundException ex) { 31358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan Toast.makeText(mContext, R.string.share_error, Toast.LENGTH_SHORT).show(); 31458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 31558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return true; 31658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 317683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson case R.id.menu_send_to_voicemail: { 318683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Update state and save 319683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mSendToVoicemailState = !mSendToVoicemailState; 320683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson item.setChecked(mSendToVoicemailState); 321683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson Intent intent = ContactSaveService.createSetSendToVoicemail( 322683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mContext, mLookupUri, mSendToVoicemailState); 323683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mContext.startService(intent); 324683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson return true; 325683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 32658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 32758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return false; 32858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 32958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan 330410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro /** 331410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro * Calls into the contacts provider to get a pre-authorized version of the given URI. 332410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro */ 333410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro private Uri getPreAuthorizedUri(Uri uri) { 334410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro Bundle uriBundle = new Bundle(); 335410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri); 336410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro Bundle authResponse = mContext.getContentResolver().call( 337410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro ContactsContract.AUTHORITY_URI, 338410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro ContactsContract.Authorization.AUTHORIZATION_METHOD, 339410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro null, 340410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro uriBundle); 341410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro if (authResponse != null) { 342410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro return (Uri) authResponse.getParcelable( 343410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro ContactsContract.Authorization.KEY_AUTHORIZED_URI); 344410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro } else { 345410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro return uri; 346410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro } 347410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro } 348410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro 34958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan @Override 35058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan public boolean handleKeyDown(int keyCode) { 35158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan switch (keyCode) { 35258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan case KeyEvent.KEYCODE_DEL: { 35358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan if (mListener != null) mListener.onDeleteRequested(mLookupUri); 35458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return true; 35558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 35658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 35758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan return false; 35858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan } 359683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 360683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson private void doPickRingtone() { 361683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 362683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); 363683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Allow user to pick 'Default' 364683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); 365683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Show only ringtones 366683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE); 367683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Don't show 'Silent' 368683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false); 369683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 370683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson Uri ringtoneUri; 371683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson if (mCustomRingtone != null) { 372683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson ringtoneUri = Uri.parse(mCustomRingtone); 373683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } else { 374683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Otherwise pick default ringtone Uri so that something is selected. 375683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); 376683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 377683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 378683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Put checkmark next to the current ringtone for this contact 379683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri); 380683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 381683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson // Launch! 382683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE); 383683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 384683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 385683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson @Override 386683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson public void onActivityResult(int requestCode, int resultCode, Intent data) { 387683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson if (resultCode != Activity.RESULT_OK) { 388683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson return; 389683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 390683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 391683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson switch (requestCode) { 392683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson case REQUEST_CODE_PICK_RINGTONE: { 393683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); 394683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson handleRingtonePicked(pickedUri); 395683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson break; 396683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 397683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 398683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 399683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson 400683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson private void handleRingtonePicked(Uri pickedUri) { 401683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) { 402683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mCustomRingtone = null; 403683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } else { 404683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mCustomRingtone = pickedUri.toString(); 405683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 406683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson Intent intent = ContactSaveService.createSetRingtone( 407683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mContext, mLookupUri, mCustomRingtone); 408683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson mContext.startService(intent); 409683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson } 4102a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann 4112a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann /** Toggles whether to load stream items. Just for debugging */ 4122a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann public void toggleLoadStreamItems() { 4132a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann Loader<ContactLoader.Result> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS); 4142a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann ContactLoader loader = (ContactLoader) loaderObj; 4152a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann loader.setLoadStreamItems(!loader.getLoadStreamItems()); 4162a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann } 4172a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann 4182a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann /** Returns whether to load stream items. Just for debugging */ 4192a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann public boolean getLoadStreamItems() { 4202a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann Loader<ContactLoader.Result> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS); 4212a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann ContactLoader loader = (ContactLoader) loaderObj; 4222a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann return loader != null && loader.getLoadStreamItems(); 4232a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann } 4242eb969cc399d87b659a45568fa951d394c216917Katherine Kuan} 425