1 /* 2 * Copyright (C) 2009 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; 18 19 import com.android.contacts.Collapser.Collapsible; 20 import com.android.contacts.model.ContactsSource; 21 import com.android.contacts.model.Sources; 22 import com.android.contacts.model.ContactsSource.DataKind; 23 import com.android.contacts.model.ContactsSource.StringInflater; 24 25 import android.app.AlertDialog; 26 import android.content.ContentUris; 27 import android.content.ContentValues; 28 import android.content.Context; 29 import android.content.DialogInterface; 30 import android.database.Cursor; 31 import android.provider.ContactsContract.Data; 32 import android.provider.ContactsContract.RawContacts; 33 import android.provider.ContactsContract.CommonDataKinds.Phone; 34 import android.telephony.PhoneNumberUtils; 35 import android.view.LayoutInflater; 36 import android.view.View; 37 import android.view.ViewGroup; 38 import android.widget.ArrayAdapter; 39 import android.widget.CheckBox; 40 import android.widget.CompoundButton; 41 import android.widget.ListAdapter; 42 import android.widget.TextView; 43 44 import java.util.ArrayList; 45 import java.util.List; 46 47 /** 48 * Class used for displaying a dialog with a list of phone numbers of which 49 * one will be chosen to make a call or initiate an sms message. 50 */ 51 public class PhoneDisambigDialog implements DialogInterface.OnClickListener, 52 DialogInterface.OnDismissListener, CompoundButton.OnCheckedChangeListener{ 53 54 private boolean mMakePrimary = false; 55 private Context mContext; 56 private AlertDialog mDialog; 57 private boolean mSendSms; 58 private int mStickyTab; 59 private Cursor mPhonesCursor; 60 private ListAdapter mPhonesAdapter; 61 private ArrayList<PhoneItem> mPhoneItemList; 62 63 public PhoneDisambigDialog(Context context, Cursor phonesCursor, boolean sendSms, 64 int stickyTab) { 65 mContext = context; 66 mSendSms = sendSms; 67 mPhonesCursor = phonesCursor; 68 mStickyTab = stickyTab; 69 70 mPhoneItemList = makePhoneItemsList(phonesCursor); 71 Collapser.collapseList(mPhoneItemList); 72 73 mPhonesAdapter = new PhonesAdapter(mContext, mPhoneItemList, mSendSms); 74 75 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 76 Context.LAYOUT_INFLATER_SERVICE); 77 View setPrimaryView = inflater. 78 inflate(R.layout.set_primary_checkbox, null); 79 ((CheckBox) setPrimaryView.findViewById(R.id.setPrimary)). 80 setOnCheckedChangeListener(this); 81 82 // Need to show disambig dialogue. 83 AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext). 84 setAdapter(mPhonesAdapter, this). 85 setTitle(sendSms ? 86 R.string.sms_disambig_title : R.string.call_disambig_title). 87 setView(setPrimaryView); 88 89 mDialog = dialogBuilder.create(); 90 } 91 92 /** 93 * Show the dialog. 94 */ 95 public void show() { 96 if (mPhoneItemList.size() == 1) { 97 // If there is only one after collapse, just select it, and close; 98 onClick(mDialog, 0); 99 return; 100 } 101 mDialog.show(); 102 } 103 104 public void onClick(DialogInterface dialog, int which) { 105 if (mPhoneItemList.size() > which && which >= 0) { 106 PhoneItem phoneItem = mPhoneItemList.get(which); 107 long id = phoneItem.id; 108 String phone = phoneItem.phoneNumber; 109 110 if (mMakePrimary) { 111 ContentValues values = new ContentValues(1); 112 values.put(Data.IS_SUPER_PRIMARY, 1); 113 mContext.getContentResolver().update(ContentUris. 114 withAppendedId(Data.CONTENT_URI, id), values, null, null); 115 } 116 117 if (mSendSms) { 118 ContactsUtils.initiateSms(mContext, phone); 119 } else { 120 StickyTabs.saveTab(mContext, mStickyTab); 121 ContactsUtils.initiateCall(mContext, phone); 122 } 123 } else { 124 dialog.dismiss(); 125 } 126 } 127 128 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 129 mMakePrimary = isChecked; 130 } 131 132 public void onDismiss(DialogInterface dialog) { 133 mPhonesCursor.close(); 134 } 135 136 private static class PhonesAdapter extends ArrayAdapter<PhoneItem> { 137 private final boolean sendSms; 138 private final Sources mSources; 139 140 public PhonesAdapter(Context context, List<PhoneItem> objects, boolean sendSms) { 141 super(context, R.layout.phone_disambig_item, 142 android.R.id.text2, objects); 143 this.sendSms = sendSms; 144 mSources = Sources.getInstance(context); 145 } 146 147 @Override 148 public View getView(int position, View convertView, ViewGroup parent) { 149 View view = super.getView(position, convertView, parent); 150 151 PhoneItem item = getItem(position); 152 ContactsSource source = mSources.getInflatedSource(item.accountType, 153 ContactsSource.LEVEL_SUMMARY); 154 155 // Obtain a string representation of the phone type specific to the 156 // ContactSource associated with that phone number 157 TextView typeView = (TextView)view.findViewById(android.R.id.text1); 158 DataKind kind = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); 159 if (kind != null) { 160 ContentValues values = new ContentValues(); 161 values.put(Phone.TYPE, item.type); 162 values.put(Phone.LABEL, item.label); 163 StringInflater header = sendSms ? kind.actionAltHeader : kind.actionHeader; 164 typeView.setText(header.inflateUsing(getContext(), values)); 165 } else { 166 typeView.setText(R.string.call_other); 167 } 168 return view; 169 } 170 } 171 172 private class PhoneItem implements Collapsible<PhoneItem> { 173 174 final long id; 175 final String phoneNumber; 176 final String accountType; 177 final long type; 178 final String label; 179 180 public PhoneItem(long id, String phoneNumber, String accountType, int type, String label) { 181 this.id = id; 182 this.phoneNumber = (phoneNumber != null ? phoneNumber : ""); 183 this.accountType = accountType; 184 this.type = type; 185 this.label = label; 186 } 187 188 public boolean collapseWith(PhoneItem phoneItem) { 189 if (!shouldCollapseWith(phoneItem)) { 190 return false; 191 } 192 // Just keep the number and id we already have. 193 return true; 194 } 195 196 public boolean shouldCollapseWith(PhoneItem phoneItem) { 197 if (PhoneNumberUtils.compare(PhoneDisambigDialog.this.mContext, 198 phoneNumber, phoneItem.phoneNumber)) { 199 return true; 200 } 201 return false; 202 } 203 204 @Override 205 public String toString() { 206 return phoneNumber; 207 } 208 } 209 210 private ArrayList<PhoneItem> makePhoneItemsList(Cursor phonesCursor) { 211 ArrayList<PhoneItem> phoneList = new ArrayList<PhoneItem>(); 212 213 phonesCursor.moveToPosition(-1); 214 while (phonesCursor.moveToNext()) { 215 long id = phonesCursor.getLong(phonesCursor.getColumnIndex(Data._ID)); 216 String phone = phonesCursor.getString(phonesCursor.getColumnIndex(Phone.NUMBER)); 217 String accountType = 218 phonesCursor.getString(phonesCursor.getColumnIndex(RawContacts.ACCOUNT_TYPE)); 219 int type = phonesCursor.getInt(phonesCursor.getColumnIndex(Phone.TYPE)); 220 String label = phonesCursor.getString(phonesCursor.getColumnIndex(Phone.LABEL)); 221 222 phoneList.add(new PhoneItem(id, phone, accountType, type, label)); 223 } 224 225 return phoneList; 226 } 227 } 228