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