1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.contacts.list; 17 18 import android.content.Intent; 19 import android.content.Loader; 20 import android.database.Cursor; 21 import android.net.Uri; 22 import android.os.Bundle; 23 import android.text.TextUtils; 24 import android.util.Log; 25 import android.view.LayoutInflater; 26 import android.view.MenuItem; 27 import android.view.View; 28 import android.view.ViewGroup; 29 30 import com.android.contacts.R; 31 import com.android.contacts.ShortcutIntentBuilder; 32 import com.android.contacts.ShortcutIntentBuilder.OnShortcutIntentCreatedListener; 33 34 /** 35 * Fragment containing a phone number list for picking. 36 */ 37 public class PhoneNumberPickerFragment extends ContactEntryListFragment<ContactEntryListAdapter> 38 implements OnShortcutIntentCreatedListener, PhoneNumberListAdapter.Listener { 39 private static final String TAG = "PhoneNumberPicker"; 40 41 private static final String KEY_SHORTCUT_ACTION = "shortcutAction"; 42 43 private OnPhoneNumberPickerActionListener mListener; 44 private String mShortcutAction; 45 46 private ContactListFilter mFilter; 47 48 private static final String KEY_FILTER = "filter"; 49 50 /** true if the loader has started at least once. */ 51 private boolean mLoaderStarted; 52 53 private boolean mUseCallableUri; 54 55 private ContactListItemView.PhotoPosition mPhotoPosition = 56 ContactListItemView.getDefaultPhotoPosition(false /* normal/non opposite */); 57 58 /** 59 * Handles a click on the video call icon for a row in the list. 60 * 61 * @param position The position in the list where the click ocurred. 62 */ 63 @Override onVideoCallIconClicked(int position)64 public void onVideoCallIconClicked(int position) { 65 callNumber(position, true /* isVideoCall */); 66 } 67 PhoneNumberPickerFragment()68 public PhoneNumberPickerFragment() { 69 setQuickContactEnabled(false); 70 setPhotoLoaderEnabled(true); 71 setSectionHeaderDisplayEnabled(true); 72 setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE); 73 74 // Show nothing instead of letting caller Activity show something. 75 setHasOptionsMenu(true); 76 } 77 setDirectorySearchEnabled(boolean flag)78 public void setDirectorySearchEnabled(boolean flag) { 79 setDirectorySearchMode(flag ? DirectoryListLoader.SEARCH_MODE_DEFAULT 80 : DirectoryListLoader.SEARCH_MODE_NONE); 81 } 82 setOnPhoneNumberPickerActionListener(OnPhoneNumberPickerActionListener listener)83 public void setOnPhoneNumberPickerActionListener(OnPhoneNumberPickerActionListener listener) { 84 this.mListener = listener; 85 } 86 getOnPhoneNumberPickerListener()87 public OnPhoneNumberPickerActionListener getOnPhoneNumberPickerListener() { 88 return mListener; 89 } 90 91 @Override onCreateView(LayoutInflater inflater, ViewGroup container)92 protected void onCreateView(LayoutInflater inflater, ViewGroup container) { 93 super.onCreateView(inflater, container); 94 95 setVisibleScrollbarEnabled(getVisibleScrollbarEnabled()); 96 } 97 getVisibleScrollbarEnabled()98 protected boolean getVisibleScrollbarEnabled() { 99 return true; 100 } 101 102 @Override restoreSavedState(Bundle savedState)103 public void restoreSavedState(Bundle savedState) { 104 super.restoreSavedState(savedState); 105 106 if (savedState == null) { 107 return; 108 } 109 110 mFilter = savedState.getParcelable(KEY_FILTER); 111 mShortcutAction = savedState.getString(KEY_SHORTCUT_ACTION); 112 } 113 114 @Override onSaveInstanceState(Bundle outState)115 public void onSaveInstanceState(Bundle outState) { 116 super.onSaveInstanceState(outState); 117 outState.putParcelable(KEY_FILTER, mFilter); 118 outState.putString(KEY_SHORTCUT_ACTION, mShortcutAction); 119 } 120 121 @Override onOptionsItemSelected(MenuItem item)122 public boolean onOptionsItemSelected(MenuItem item) { 123 final int itemId = item.getItemId(); 124 if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled() 125 if (mListener != null) { 126 mListener.onHomeInActionBarSelected(); 127 } 128 return true; 129 } 130 return super.onOptionsItemSelected(item); 131 } 132 133 /** 134 * @param shortcutAction either {@link Intent#ACTION_CALL} or 135 * {@link Intent#ACTION_SENDTO} or null. 136 */ setShortcutAction(String shortcutAction)137 public void setShortcutAction(String shortcutAction) { 138 this.mShortcutAction = shortcutAction; 139 } 140 141 @Override onItemClick(int position, long id)142 protected void onItemClick(int position, long id) { 143 callNumber(position, false /* isVideoCall */); 144 } 145 146 /** 147 * Initiates a call to the number at the specified position. 148 * 149 * @param position The position. 150 * @param isVideoCall {@code true} if the call should be initiated as a video call, 151 * {@code false} otherwise. 152 */ callNumber(int position, boolean isVideoCall)153 private void callNumber(int position, boolean isVideoCall) { 154 final Uri phoneUri = getPhoneUri(position); 155 156 if (phoneUri != null) { 157 pickPhoneNumber(phoneUri, isVideoCall); 158 } else { 159 final String number = getPhoneNumber(position); 160 if (!TextUtils.isEmpty(number)) { 161 cacheContactInfo(position); 162 mListener.onPickPhoneNumber(number, isVideoCall, 163 getCallInitiationType(true /* isRemoteDirectory */)); 164 } else { 165 Log.w(TAG, "Item at " + position + " was clicked before" 166 + " adapter is ready. Ignoring"); 167 } 168 } 169 } 170 cacheContactInfo(int position)171 protected void cacheContactInfo(int position) { 172 // Not implemented. Hook for child classes 173 } 174 getPhoneNumber(int position)175 protected String getPhoneNumber(int position) { 176 final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter(); 177 return adapter.getPhoneNumber(position); 178 } 179 getPhoneUri(int position)180 protected Uri getPhoneUri(int position) { 181 final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter(); 182 return adapter.getDataUri(position); 183 } 184 getLookupKey(int position)185 protected String getLookupKey(int position) { 186 final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter(); 187 return adapter.getLookupKey(position); 188 } 189 190 @Override startLoading()191 protected void startLoading() { 192 mLoaderStarted = true; 193 super.startLoading(); 194 } 195 196 @Override onLoadFinished(Loader<Cursor> loader, Cursor data)197 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 198 super.onLoadFinished(loader, data); 199 200 // disable scroll bar if there is no data 201 setVisibleScrollbarEnabled(data != null && !data.isClosed() && data.getCount() > 0); 202 } 203 setUseCallableUri(boolean useCallableUri)204 public void setUseCallableUri(boolean useCallableUri) { 205 mUseCallableUri = useCallableUri; 206 } 207 usesCallableUri()208 public boolean usesCallableUri() { 209 return mUseCallableUri; 210 } 211 212 @Override createListAdapter()213 protected ContactEntryListAdapter createListAdapter() { 214 PhoneNumberListAdapter adapter = new PhoneNumberListAdapter(getActivity()); 215 adapter.setDisplayPhotos(true); 216 adapter.setUseCallableUri(mUseCallableUri); 217 return adapter; 218 } 219 220 @Override configureAdapter()221 protected void configureAdapter() { 222 super.configureAdapter(); 223 224 final ContactEntryListAdapter adapter = getAdapter(); 225 if (adapter == null) { 226 return; 227 } 228 229 if (!isSearchMode() && mFilter != null) { 230 adapter.setFilter(mFilter); 231 } 232 233 setPhotoPosition(adapter); 234 } 235 setPhotoPosition(ContactEntryListAdapter adapter)236 protected void setPhotoPosition(ContactEntryListAdapter adapter) { 237 ((PhoneNumberListAdapter) adapter).setPhotoPosition(mPhotoPosition); 238 } 239 240 @Override inflateView(LayoutInflater inflater, ViewGroup container)241 protected View inflateView(LayoutInflater inflater, ViewGroup container) { 242 return inflater.inflate(R.layout.contact_list_content, null); 243 } 244 pickPhoneNumber(Uri uri, boolean isVideoCall)245 public void pickPhoneNumber(Uri uri, boolean isVideoCall) { 246 if (mShortcutAction == null) { 247 mListener.onPickDataUri(uri, isVideoCall, 248 getCallInitiationType(false /* isRemoteDirectory */)); 249 } else { 250 startPhoneNumberShortcutIntent(uri, isVideoCall); 251 } 252 } 253 startPhoneNumberShortcutIntent(Uri uri, boolean isVideoCall)254 protected void startPhoneNumberShortcutIntent(Uri uri, boolean isVideoCall) { 255 ShortcutIntentBuilder builder = new ShortcutIntentBuilder(getActivity(), this); 256 builder.createPhoneNumberShortcutIntent(uri, mShortcutAction); 257 } 258 259 @Override onShortcutIntentCreated(Uri uri, Intent shortcutIntent)260 public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) { 261 mListener.onShortcutIntentCreated(shortcutIntent); 262 } 263 264 @Override onPickerResult(Intent data)265 public void onPickerResult(Intent data) { 266 mListener.onPickDataUri(data.getData(), false /* isVideoCall */, 267 getCallInitiationType(false /* isRemoteDirectory */)); 268 } 269 setFilter(ContactListFilter filter)270 public void setFilter(ContactListFilter filter) { 271 if ((mFilter == null && filter == null) || 272 (mFilter != null && mFilter.equals(filter))) { 273 return; 274 } 275 276 mFilter = filter; 277 if (mLoaderStarted) { 278 reloadData(); 279 } 280 } 281 setPhotoPosition(ContactListItemView.PhotoPosition photoPosition)282 public void setPhotoPosition(ContactListItemView.PhotoPosition photoPosition) { 283 mPhotoPosition = photoPosition; 284 285 final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter(); 286 if (adapter != null) { 287 adapter.setPhotoPosition(photoPosition); 288 } 289 } 290 291 /** 292 * @param isRemoteDirectory {@code true} if the call was initiated using a contact/phone number 293 * not in the local contacts database 294 */ getCallInitiationType(boolean isRemoteDirectory)295 protected int getCallInitiationType(boolean isRemoteDirectory) { 296 return OnPhoneNumberPickerActionListener.CALL_INITIATION_UNKNOWN; 297 } 298 } 299