1 /* 2 * Copyright (C) 2014 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 17 package com.android.contacts.widget; 18 19 import android.app.AlertDialog; 20 import android.app.Dialog; 21 import android.app.DialogFragment; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.os.Bundle; 25 import android.os.Handler; 26 import android.os.ResultReceiver; 27 import android.telecom.PhoneAccount; 28 import android.telecom.PhoneAccountHandle; 29 import android.telecom.TelecomManager; 30 import android.text.TextUtils; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.ArrayAdapter; 35 import android.widget.CheckBox; 36 import android.widget.CompoundButton; 37 import android.widget.ImageView; 38 import android.widget.LinearLayout; 39 import android.widget.ListAdapter; 40 import android.widget.TextView; 41 42 import com.android.contacts.R; 43 import com.android.contacts.compat.PhoneAccountCompat; 44 import com.android.contacts.compat.PhoneNumberUtilsCompat; 45 46 import java.util.ArrayList; 47 import java.util.List; 48 49 /** 50 * Dialog that allows the user to select a phone accounts for a given action. Optionally provides 51 * the choice to set the phone account as default. 52 */ 53 public class SelectPhoneAccountDialogFragment extends DialogFragment { 54 private static final String ARG_TITLE_RES_ID = "title_res_id"; 55 private static final String ARG_CAN_SET_DEFAULT = "can_set_default"; 56 private static final String ARG_ACCOUNT_HANDLES = "account_handles"; 57 private static final String ARG_IS_DEFAULT_CHECKED = "is_default_checked"; 58 private static final String ARG_LISTENER = "listener"; 59 60 private int mTitleResId; 61 private boolean mCanSetDefault; 62 private List<PhoneAccountHandle> mAccountHandles; 63 private boolean mIsSelected; 64 private boolean mIsDefaultChecked; 65 private TelecomManager mTelecomManager; 66 private SelectPhoneAccountListener mListener; 67 68 /** 69 * Create new fragment instance with default title and no option to set as default. 70 * 71 * @param accountHandles The {@code PhoneAccountHandle}s available to select from. 72 * @param listener The listener for the results of the account selection. 73 */ newInstance( List<PhoneAccountHandle> accountHandles, SelectPhoneAccountListener listener)74 public static SelectPhoneAccountDialogFragment newInstance( 75 List<PhoneAccountHandle> accountHandles, SelectPhoneAccountListener listener) { 76 return newInstance(R.string.select_account_dialog_title, false, 77 accountHandles, listener); 78 } 79 80 /** 81 * Create new fragment instance. 82 * This method also allows specifying a custom title and "set default" checkbox. 83 * 84 * @param titleResId The resource ID for the string to use in the title of the dialog. 85 * @param canSetDefault {@code true} if the dialog should include an option to set the selection 86 * as the default. False otherwise. 87 * @param accountHandles The {@code PhoneAccountHandle}s available to select from. 88 * @param listener The listener for the results of the account selection. 89 */ newInstance(int titleResId, boolean canSetDefault, List<PhoneAccountHandle> accountHandles, SelectPhoneAccountListener listener)90 public static SelectPhoneAccountDialogFragment newInstance(int titleResId, 91 boolean canSetDefault, List<PhoneAccountHandle> accountHandles, 92 SelectPhoneAccountListener listener) { 93 ArrayList<PhoneAccountHandle> accountHandlesCopy = new ArrayList<PhoneAccountHandle>(); 94 if (accountHandles != null) { 95 accountHandlesCopy.addAll(accountHandles); 96 } 97 SelectPhoneAccountDialogFragment fragment = new SelectPhoneAccountDialogFragment(); 98 final Bundle args = new Bundle(); 99 args.putInt(ARG_TITLE_RES_ID, titleResId); 100 args.putBoolean(ARG_CAN_SET_DEFAULT, canSetDefault); 101 args.putParcelableArrayList(ARG_ACCOUNT_HANDLES, accountHandlesCopy); 102 args.putParcelable(ARG_LISTENER, listener); 103 fragment.setArguments(args); 104 fragment.setListener(listener); 105 return fragment; 106 } 107 SelectPhoneAccountDialogFragment()108 public SelectPhoneAccountDialogFragment() { 109 } 110 setListener(SelectPhoneAccountListener listener)111 public void setListener(SelectPhoneAccountListener listener) { 112 mListener = listener; 113 } 114 115 public static class SelectPhoneAccountListener extends ResultReceiver { 116 static final int RESULT_SELECTED = 1; 117 static final int RESULT_DISMISSED = 2; 118 119 static final String EXTRA_SELECTED_ACCOUNT_HANDLE = "extra_selected_account_handle"; 120 static final String EXTRA_SET_DEFAULT = "extra_set_default"; 121 SelectPhoneAccountListener()122 public SelectPhoneAccountListener() { 123 super(new Handler()); 124 } 125 126 @Override onReceiveResult(int resultCode, Bundle resultData)127 protected void onReceiveResult(int resultCode, Bundle resultData) { 128 if (resultCode == RESULT_SELECTED) { 129 onPhoneAccountSelected( 130 (PhoneAccountHandle) resultData.getParcelable( 131 EXTRA_SELECTED_ACCOUNT_HANDLE), 132 resultData.getBoolean(EXTRA_SET_DEFAULT)); 133 } else if (resultCode == RESULT_DISMISSED) { 134 onDialogDismissed(); 135 } 136 } 137 onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle, boolean setDefault)138 public void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle, 139 boolean setDefault) {} 140 onDialogDismissed()141 public void onDialogDismissed() {} 142 } 143 144 @Override onSaveInstanceState(Bundle outState)145 public void onSaveInstanceState(Bundle outState) { 146 super.onSaveInstanceState(outState); 147 outState.putBoolean(ARG_IS_DEFAULT_CHECKED, mIsDefaultChecked); 148 } 149 150 @Override onCreateDialog(Bundle savedInstanceState)151 public Dialog onCreateDialog(Bundle savedInstanceState) { 152 mTitleResId = getArguments().getInt(ARG_TITLE_RES_ID); 153 mCanSetDefault = getArguments().getBoolean(ARG_CAN_SET_DEFAULT); 154 mAccountHandles = getArguments().getParcelableArrayList(ARG_ACCOUNT_HANDLES); 155 mListener = getArguments().getParcelable(ARG_LISTENER); 156 if (savedInstanceState != null) { 157 mIsDefaultChecked = savedInstanceState.getBoolean(ARG_IS_DEFAULT_CHECKED); 158 } 159 mIsSelected = false; 160 mTelecomManager = 161 (TelecomManager) getActivity().getSystemService(Context.TELECOM_SERVICE); 162 163 final DialogInterface.OnClickListener selectionListener = 164 new DialogInterface.OnClickListener() { 165 @Override 166 public void onClick(DialogInterface dialog, int which) { 167 mIsSelected = true; 168 PhoneAccountHandle selectedAccountHandle = mAccountHandles.get(which); 169 final Bundle result = new Bundle(); 170 result.putParcelable(SelectPhoneAccountListener.EXTRA_SELECTED_ACCOUNT_HANDLE, 171 selectedAccountHandle); 172 result.putBoolean(SelectPhoneAccountListener.EXTRA_SET_DEFAULT, 173 mIsDefaultChecked); 174 if (mListener != null) { 175 mListener.onReceiveResult(SelectPhoneAccountListener.RESULT_SELECTED, result); 176 } 177 } 178 }; 179 180 final CompoundButton.OnCheckedChangeListener checkListener = 181 new CompoundButton.OnCheckedChangeListener() { 182 @Override 183 public void onCheckedChanged(CompoundButton check, boolean isChecked) { 184 mIsDefaultChecked = isChecked; 185 } 186 }; 187 188 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 189 ListAdapter selectAccountListAdapter = new SelectAccountListAdapter( 190 builder.getContext(), 191 R.layout.select_account_list_item, 192 mAccountHandles); 193 194 AlertDialog dialog = builder.setTitle(mTitleResId) 195 .setAdapter(selectAccountListAdapter, selectionListener) 196 .create(); 197 198 if (mCanSetDefault) { 199 // Generate custom checkbox view 200 LinearLayout checkboxLayout = (LinearLayout) getActivity() 201 .getLayoutInflater() 202 .inflate(R.layout.default_account_checkbox, null); 203 204 CheckBox cb = 205 (CheckBox) checkboxLayout.findViewById(R.id.default_account_checkbox_view); 206 cb.setOnCheckedChangeListener(checkListener); 207 cb.setChecked(mIsDefaultChecked); 208 209 dialog.getListView().addFooterView(checkboxLayout); 210 } 211 212 return dialog; 213 } 214 215 private class SelectAccountListAdapter extends ArrayAdapter<PhoneAccountHandle> { 216 private int mResId; 217 SelectAccountListAdapter( Context context, int resource, List<PhoneAccountHandle> accountHandles)218 public SelectAccountListAdapter( 219 Context context, int resource, List<PhoneAccountHandle> accountHandles) { 220 super(context, resource, accountHandles); 221 mResId = resource; 222 } 223 224 @Override getView(int position, View convertView, ViewGroup parent)225 public View getView(int position, View convertView, ViewGroup parent) { 226 LayoutInflater inflater = (LayoutInflater) 227 getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 228 229 View rowView; 230 final ViewHolder holder; 231 232 if (convertView == null) { 233 // Cache views for faster scrolling 234 rowView = inflater.inflate(mResId, null); 235 holder = new ViewHolder(); 236 holder.labelTextView = (TextView) rowView.findViewById(R.id.label); 237 holder.numberTextView = (TextView) rowView.findViewById(R.id.number); 238 holder.imageView = (ImageView) rowView.findViewById(R.id.icon); 239 rowView.setTag(holder); 240 } 241 else { 242 rowView = convertView; 243 holder = (ViewHolder) rowView.getTag(); 244 } 245 246 PhoneAccountHandle accountHandle = getItem(position); 247 PhoneAccount account = mTelecomManager.getPhoneAccount(accountHandle); 248 if (account == null) { 249 return rowView; 250 } 251 holder.labelTextView.setText(account.getLabel()); 252 if (account.getAddress() == null || 253 TextUtils.isEmpty(account.getAddress().getSchemeSpecificPart())) { 254 holder.numberTextView.setVisibility(View.GONE); 255 } else { 256 holder.numberTextView.setVisibility(View.VISIBLE); 257 holder.numberTextView.setText( 258 PhoneNumberUtilsCompat.createTtsSpannable( 259 account.getAddress().getSchemeSpecificPart())); 260 } 261 holder.imageView.setImageDrawable(PhoneAccountCompat.createIconDrawable(account, 262 getContext())); 263 return rowView; 264 } 265 266 private class ViewHolder { 267 TextView labelTextView; 268 TextView numberTextView; 269 ImageView imageView; 270 } 271 } 272 273 @Override onStop()274 public void onStop() { 275 if (!mIsSelected && mListener != null) { 276 mListener.onReceiveResult(SelectPhoneAccountListener.RESULT_DISMISSED, null); 277 } 278 super.onStop(); 279 } 280 } 281