| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package com.android.contacts.common.widget; |
| |
| import android.annotation.SuppressLint; |
| import android.app.AlertDialog; |
| import android.app.Dialog; |
| import android.app.DialogFragment; |
| import android.content.Context; |
| import android.content.DialogInterface; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.ResultReceiver; |
| import android.support.annotation.NonNull; |
| import android.support.annotation.Nullable; |
| import android.support.annotation.VisibleForTesting; |
| import android.telecom.PhoneAccount; |
| import android.telecom.PhoneAccountHandle; |
| import android.telecom.TelecomManager; |
| import android.telephony.SubscriptionInfo; |
| import android.text.TextUtils; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.ArrayAdapter; |
| import android.widget.CheckBox; |
| import android.widget.CompoundButton; |
| import android.widget.ImageView; |
| import android.widget.LinearLayout; |
| import android.widget.ListAdapter; |
| import android.widget.TextView; |
| import com.android.contacts.common.compat.PhoneAccountCompat; |
| import com.android.dialer.contacts.resources.R; |
| import com.android.dialer.location.GeoUtil; |
| import com.android.dialer.phonenumberutil.PhoneNumberHelper; |
| import com.android.dialer.protos.ProtoParsers; |
| import com.android.dialer.telecom.TelecomUtil; |
| import com.google.common.base.Optional; |
| |
| /** |
| * Dialog that allows the user to select a phone accounts for a given action. Optionally provides |
| * the choice to set the phone account as default. |
| */ |
| public class SelectPhoneAccountDialogFragment extends DialogFragment { |
| |
| @VisibleForTesting public static final String ARG_OPTIONS = "options"; |
| |
| private static final String ARG_IS_DEFAULT_CHECKED = "is_default_checked"; |
| |
| private SelectPhoneAccountDialogOptions options = |
| SelectPhoneAccountDialogOptions.getDefaultInstance(); |
| private SelectPhoneAccountListener listener; |
| |
| private boolean isDefaultChecked; |
| private boolean isSelected; |
| |
| /** Create new fragment instance. */ |
| public static SelectPhoneAccountDialogFragment newInstance( |
| SelectPhoneAccountDialogOptions options, SelectPhoneAccountListener listener) { |
| SelectPhoneAccountDialogFragment fragment = new SelectPhoneAccountDialogFragment(); |
| fragment.setListener(listener); |
| Bundle arguments = new Bundle(); |
| ProtoParsers.put(arguments, ARG_OPTIONS, options); |
| fragment.setArguments(arguments); |
| return fragment; |
| } |
| |
| public void setListener(SelectPhoneAccountListener listener) { |
| this.listener = listener; |
| } |
| |
| @Nullable |
| @VisibleForTesting |
| public SelectPhoneAccountListener getListener() { |
| return listener; |
| } |
| |
| @VisibleForTesting |
| public boolean canSetDefault() { |
| return options.getCanSetDefault(); |
| } |
| |
| @Override |
| public void onSaveInstanceState(Bundle outState) { |
| super.onSaveInstanceState(outState); |
| outState.putBoolean(ARG_IS_DEFAULT_CHECKED, isDefaultChecked); |
| } |
| |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| options = |
| ProtoParsers.getTrusted( |
| getArguments(), ARG_OPTIONS, SelectPhoneAccountDialogOptions.getDefaultInstance()); |
| if (savedInstanceState != null) { |
| isDefaultChecked = savedInstanceState.getBoolean(ARG_IS_DEFAULT_CHECKED); |
| } |
| isSelected = false; |
| |
| final DialogInterface.OnClickListener selectionListener = |
| new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| isSelected = true; |
| PhoneAccountHandle selectedAccountHandle = |
| SelectPhoneAccountDialogOptionsUtil.getPhoneAccountHandle( |
| options.getEntriesList().get(which)); |
| Bundle result = new Bundle(); |
| result.putParcelable( |
| SelectPhoneAccountListener.EXTRA_SELECTED_ACCOUNT_HANDLE, selectedAccountHandle); |
| result.putBoolean(SelectPhoneAccountListener.EXTRA_SET_DEFAULT, isDefaultChecked); |
| result.putString(SelectPhoneAccountListener.EXTRA_CALL_ID, getCallId()); |
| if (listener != null) { |
| listener.onReceiveResult(SelectPhoneAccountListener.RESULT_SELECTED, result); |
| } |
| } |
| }; |
| |
| final CompoundButton.OnCheckedChangeListener checkListener = |
| new CompoundButton.OnCheckedChangeListener() { |
| @Override |
| public void onCheckedChanged(CompoundButton check, boolean isChecked) { |
| isDefaultChecked = isChecked; |
| } |
| }; |
| |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| ListAdapter selectAccountListAdapter = |
| new SelectAccountListAdapter( |
| builder.getContext(), R.layout.select_account_list_item, options); |
| |
| AlertDialog dialog = |
| builder |
| .setTitle( |
| options.hasTitle() ? options.getTitle() : R.string.select_account_dialog_title) |
| .setAdapter(selectAccountListAdapter, selectionListener) |
| .create(); |
| |
| if (options.getCanSetDefault()) { |
| // Generate custom checkbox view, lint suppressed since no appropriate parent (is dialog) |
| @SuppressLint("InflateParams") |
| LinearLayout checkboxLayout = |
| (LinearLayout) |
| LayoutInflater.from(builder.getContext()) |
| .inflate(R.layout.default_account_checkbox, null); |
| |
| CheckBox checkBox = checkboxLayout.findViewById(R.id.default_account_checkbox_view); |
| checkBox.setOnCheckedChangeListener(checkListener); |
| checkBox.setChecked(isDefaultChecked); |
| |
| TextView textView = checkboxLayout.findViewById(R.id.default_account_checkbox_text); |
| int setDefaultResId = |
| options.hasSetDefaultLabel() |
| ? options.getSetDefaultLabel() |
| : R.string.set_default_account; |
| textView.setText(setDefaultResId); |
| textView.setOnClickListener((view) -> checkBox.performClick()); |
| checkboxLayout.setOnClickListener((view) -> checkBox.performClick()); |
| checkboxLayout.setContentDescription(getString(setDefaultResId)); |
| dialog.getListView().addFooterView(checkboxLayout); |
| } |
| |
| return dialog; |
| } |
| |
| @Override |
| public void onCancel(DialogInterface dialog) { |
| if (!isSelected && listener != null) { |
| Bundle result = new Bundle(); |
| result.putString(SelectPhoneAccountListener.EXTRA_CALL_ID, getCallId()); |
| listener.onReceiveResult(SelectPhoneAccountListener.RESULT_DISMISSED, result); |
| } |
| super.onCancel(dialog); |
| } |
| |
| @Nullable |
| private String getCallId() { |
| return options.getCallId(); |
| } |
| |
| public static class SelectPhoneAccountListener extends ResultReceiver { |
| |
| static final int RESULT_SELECTED = 1; |
| static final int RESULT_DISMISSED = 2; |
| |
| static final String EXTRA_SELECTED_ACCOUNT_HANDLE = "extra_selected_account_handle"; |
| static final String EXTRA_SET_DEFAULT = "extra_set_default"; |
| static final String EXTRA_CALL_ID = "extra_call_id"; |
| |
| protected SelectPhoneAccountListener() { |
| super(new Handler()); |
| } |
| |
| @Override |
| protected void onReceiveResult(int resultCode, Bundle resultData) { |
| if (resultCode == RESULT_SELECTED) { |
| onPhoneAccountSelected( |
| resultData.getParcelable(EXTRA_SELECTED_ACCOUNT_HANDLE), |
| resultData.getBoolean(EXTRA_SET_DEFAULT), |
| resultData.getString(EXTRA_CALL_ID)); |
| } else if (resultCode == RESULT_DISMISSED) { |
| onDialogDismissed(resultData.getString(EXTRA_CALL_ID)); |
| } |
| } |
| |
| public void onPhoneAccountSelected( |
| PhoneAccountHandle selectedAccountHandle, boolean setDefault, @Nullable String callId) {} |
| |
| public void onDialogDismissed(@Nullable String callId) {} |
| } |
| |
| static class SelectAccountListAdapter |
| extends ArrayAdapter<SelectPhoneAccountDialogOptions.Entry> { |
| |
| private int mResId; |
| private final SelectPhoneAccountDialogOptions options; |
| |
| SelectAccountListAdapter( |
| Context context, int resource, SelectPhoneAccountDialogOptions options) { |
| super(context, resource, options.getEntriesList()); |
| this.options = options; |
| mResId = resource; |
| } |
| |
| @Override |
| public boolean areAllItemsEnabled() { |
| return false; |
| } |
| |
| @Override |
| public boolean isEnabled(int position) { |
| return options.getEntries(position).getEnabled(); |
| } |
| |
| @Override |
| public View getView(int position, View convertView, ViewGroup parent) { |
| LayoutInflater inflater = |
| (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| |
| View rowView; |
| final ViewHolder holder; |
| |
| if (convertView == null) { |
| // Cache views for faster scrolling |
| rowView = inflater.inflate(mResId, null); |
| holder = new ViewHolder(); |
| holder.labelTextView = (TextView) rowView.findViewById(R.id.label); |
| holder.numberTextView = (TextView) rowView.findViewById(R.id.number); |
| holder.hintTextView = rowView.findViewById(R.id.hint); |
| holder.imageView = (ImageView) rowView.findViewById(R.id.icon); |
| rowView.setTag(holder); |
| } else { |
| rowView = convertView; |
| holder = (ViewHolder) rowView.getTag(); |
| } |
| |
| SelectPhoneAccountDialogOptions.Entry entry = getItem(position); |
| PhoneAccountHandle accountHandle = |
| SelectPhoneAccountDialogOptionsUtil.getPhoneAccountHandle(entry); |
| PhoneAccount account = |
| getContext().getSystemService(TelecomManager.class).getPhoneAccount(accountHandle); |
| if (account == null) { |
| return rowView; |
| } |
| holder.labelTextView.setText(account.getLabel()); |
| if (account.getAddress() == null |
| || TextUtils.isEmpty(account.getAddress().getSchemeSpecificPart())) { |
| holder.numberTextView.setVisibility(View.GONE); |
| } else { |
| holder.numberTextView.setVisibility(View.VISIBLE); |
| holder.numberTextView.setText( |
| PhoneNumberHelper.formatNumberForDisplay( |
| getContext(), |
| account.getAddress().getSchemeSpecificPart(), |
| getCountryIso(getContext(), accountHandle))); |
| } |
| holder.imageView.setImageDrawable( |
| PhoneAccountCompat.createIconDrawable(account, getContext())); |
| |
| if (TextUtils.isEmpty(entry.getHint())) { |
| holder.hintTextView.setVisibility(View.GONE); |
| } else { |
| holder.hintTextView.setVisibility(View.VISIBLE); |
| holder.hintTextView.setText(entry.getHint()); |
| } |
| holder.labelTextView.setEnabled(entry.getEnabled()); |
| holder.numberTextView.setEnabled(entry.getEnabled()); |
| holder.hintTextView.setEnabled(entry.getEnabled()); |
| holder.imageView.setImageAlpha(entry.getEnabled() ? 255 : 97 /* 38%*/); |
| return rowView; |
| } |
| |
| private static String getCountryIso( |
| Context context, @NonNull PhoneAccountHandle phoneAccountHandle) { |
| Optional<SubscriptionInfo> info = |
| TelecomUtil.getSubscriptionInfo(context, phoneAccountHandle); |
| if (!info.isPresent()) { |
| return GeoUtil.getCurrentCountryIso(context); |
| } |
| return info.get().getCountryIso().toUpperCase(); |
| } |
| |
| static final class ViewHolder { |
| |
| TextView labelTextView; |
| TextView numberTextView; |
| TextView hintTextView; |
| ImageView imageView; |
| } |
| } |
| } |