• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.voicedialer;
18 
19 import android.app.Activity;
20 import android.database.Cursor;
21 import android.database.DatabaseUtils;
22 import android.provider.ContactsContract.CommonDataKinds.Phone;
23 import android.provider.CallLog;
24 import android.util.Log;
25 import java.io.BufferedReader;
26 import java.io.File;
27 import java.io.FileReader;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 
33 /**
34  * This class represents a person who may be called via the VoiceDialer app.
35  * The person has a name and a list of phones (home, mobile, work, other).
36  */
37 public class VoiceContact {
38     private static final String TAG = "VoiceContact";
39 
40     /**
41      * Corresponding row doesn't exist.
42      */
43     public static final long ID_UNDEFINED = -1;
44 
45     public final String mName;
46     public final long mContactId;
47     public final long mPrimaryId;
48     public final long mHomeId;
49     public final long mMobileId;
50     public final long mWorkId;
51     public final long mOtherId;
52 
53     /**
54      * Constructor.
55      *
56      * @param name person's name.
57      * @param contactId ID in person table.
58      * @param primaryId primary ID in phone table.
59      * @param homeId home ID in phone table.
60      * @param mobileId mobile ID in phone table.
61      * @param workId work ID in phone table.
62      * @param otherId other ID in phone table.
63      */
VoiceContact(String name, long contactId, long primaryId, long homeId, long mobileId, long workId,long otherId)64     private VoiceContact(String name, long contactId, long primaryId,
65             long homeId, long mobileId, long workId,long otherId) {
66         mName = name;
67         mContactId = contactId;
68         mPrimaryId = primaryId;
69         mHomeId = homeId;
70         mMobileId = mobileId;
71         mWorkId = workId;
72         mOtherId = otherId;
73     }
74 
75     @Override
hashCode()76     public int hashCode() {
77         final int LARGE_PRIME = 1610612741;
78         int hash = 0;
79         hash = LARGE_PRIME * (hash + (int)mContactId);
80         hash = LARGE_PRIME * (hash + (int)mPrimaryId);
81         hash = LARGE_PRIME * (hash + (int)mHomeId);
82         hash = LARGE_PRIME * (hash + (int)mMobileId);
83         hash = LARGE_PRIME * (hash + (int)mWorkId);
84         hash = LARGE_PRIME * (hash + (int)mOtherId);
85         return mName.hashCode() + hash;
86     }
87 
88     @Override
toString()89     public String toString() {
90         return "mName=" + mName
91                 + " mPersonId=" + mContactId
92                 + " mPrimaryId=" + mPrimaryId
93                 + " mHomeId=" + mHomeId
94                 + " mMobileId=" + mMobileId
95                 + " mWorkId=" + mWorkId
96                 + " mOtherId=" + mOtherId;
97     }
98 
99     /**
100      * @param activity The VoiceDialerActivity instance.
101      * @return List of {@link VoiceContact} from
102      * the contact list content provider.
103      */
getVoiceContacts(Activity activity)104     public static List<VoiceContact> getVoiceContacts(Activity activity) {
105         if (false) Log.d(TAG, "VoiceContact.getVoiceContacts");
106 
107         List<VoiceContact> contacts = new ArrayList<VoiceContact>();
108 
109         String[] phonesProjection = new String[] {
110             Phone._ID,
111             Phone.TYPE,
112             Phone.IS_PRIMARY,
113             // TODO: handle type != 0,1,2, and use LABEL
114             Phone.LABEL,
115             Phone.DISPLAY_NAME,
116             Phone.CONTACT_ID,
117         };
118 
119         // Table is sorted by number of times contacted and name. If we cannot fit all contacts
120         // in the recognizer, we will at least have the commonly used ones.
121         Cursor cursor = activity.getContentResolver().query(
122                 Phone.CONTENT_URI, phonesProjection,
123                 Phone.NUMBER + " NOT NULL", null,
124                 Phone.LAST_TIME_CONTACTED + " DESC, " + Phone.DISPLAY_NAME + " ASC");
125 
126         final int phoneIdColumn = cursor.getColumnIndexOrThrow(Phone._ID);
127         final int typeColumn = cursor.getColumnIndexOrThrow(Phone.TYPE);
128         final int isPrimaryColumn = cursor.getColumnIndexOrThrow(Phone.IS_PRIMARY);
129         final int labelColumn = cursor.getColumnIndexOrThrow(Phone.LABEL);
130         final int nameColumn = cursor.getColumnIndexOrThrow(Phone.DISPLAY_NAME);
131         final int personIdColumn = cursor.getColumnIndexOrThrow(Phone.CONTACT_ID);
132 
133         // pieces of next VoiceContact
134         String name = null;
135         long personId = ID_UNDEFINED;
136         long primaryId = ID_UNDEFINED;
137         long homeId = ID_UNDEFINED;
138         long mobileId = ID_UNDEFINED;
139         long workId = ID_UNDEFINED;
140         long otherId = ID_UNDEFINED;
141 
142         // loop over phone table
143         for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
144             long phoneIdAtCursor = cursor.getLong(phoneIdColumn);
145             int typeAtCursor = cursor.getInt(typeColumn);
146             long isPrimaryAtCursor = cursor.getLong(isPrimaryColumn);
147             String labelAtCursor = cursor.getString(labelColumn);
148             String nameAtCursor = cursor.getString(nameColumn);
149             long personIdAtCursor = cursor.getLong(personIdColumn);
150 
151             /*
152             if (false) {
153                 Log.d(TAG, "phoneId=" + phoneIdAtCursor
154                         + " type=" + typeAtCursor
155                         + " isPrimary=" + isPrimaryAtCursor
156                         + " label=" + labelAtCursor
157                         + " name=" + nameAtCursor
158                         + " personId=" + personIdAtCursor
159                         );
160             }
161             */
162 
163             // encountered a new name, so generate current VoiceContact
164             if (name != null && !name.equals(nameAtCursor)) {
165                 contacts.add(new VoiceContact(name, personId, primaryId,
166                         homeId, mobileId, workId, otherId));
167                 name = null;
168             }
169 
170             // start accumulating pieces for a new VoiceContact
171             if (name == null) {
172                 name = nameAtCursor;
173                 personId = personIdAtCursor;
174                 primaryId = ID_UNDEFINED;
175                 homeId = ID_UNDEFINED;
176                 mobileId = ID_UNDEFINED;
177                 workId = ID_UNDEFINED;
178                 otherId = ID_UNDEFINED;
179             }
180 
181             // if labeled, then patch to HOME/MOBILE/WORK/OTHER
182             if (typeAtCursor == Phone.TYPE_CUSTOM &&
183                     labelAtCursor != null) {
184                 String label = labelAtCursor.toLowerCase();
185                 if (label.contains("home") || label.contains("house")) {
186                     typeAtCursor = Phone.TYPE_HOME;
187                 }
188                 else if (label.contains("mobile") || label.contains("cell")) {
189                     typeAtCursor = Phone.TYPE_MOBILE;
190                 }
191                 else if (label.contains("work") || label.contains("office")) {
192                     typeAtCursor = Phone.TYPE_WORK;
193                 }
194                 else if (label.contains("other")) {
195                     typeAtCursor = Phone.TYPE_OTHER;
196                 }
197             }
198 
199             // save the home, mobile, or work phone id
200             switch (typeAtCursor) {
201                 case Phone.TYPE_HOME:
202                     homeId = phoneIdAtCursor;
203                     if (isPrimaryAtCursor != 0) {
204                         primaryId = phoneIdAtCursor;
205                     }
206                     break;
207                 case Phone.TYPE_MOBILE:
208                     mobileId = phoneIdAtCursor;
209                     if (isPrimaryAtCursor != 0) {
210                         primaryId = phoneIdAtCursor;
211                     }
212                     break;
213                 case Phone.TYPE_WORK:
214                     workId = phoneIdAtCursor;
215                     if (isPrimaryAtCursor != 0) {
216                         primaryId = phoneIdAtCursor;
217                     }
218                     break;
219                 case Phone.TYPE_OTHER:
220                     otherId = phoneIdAtCursor;
221                     if (isPrimaryAtCursor != 0) {
222                         primaryId = phoneIdAtCursor;
223                     }
224                     break;
225             }
226         }
227 
228         // generate the last VoiceContact
229         if (name != null) {
230             contacts.add(new VoiceContact(name, personId, primaryId,
231                             homeId, mobileId, workId, otherId));
232         }
233 
234         // clean up cursor
235         cursor.close();
236 
237         if (false) Log.d(TAG, "VoiceContact.getVoiceContacts " + contacts.size());
238 
239         return contacts;
240     }
241 
242     /**
243      * @param contactsFile File containing a list of names,
244      * one per line.
245      * @return a List of {@link VoiceContact} in a File.
246      */
getVoiceContactsFromFile(File contactsFile)247     public static List<VoiceContact> getVoiceContactsFromFile(File contactsFile) {
248         if (false) Log.d(TAG, "getVoiceContactsFromFile " + contactsFile);
249 
250         List<VoiceContact> contacts = new ArrayList<VoiceContact>();
251 
252         // read from a file
253         BufferedReader br = null;
254         try {
255             br = new BufferedReader(new FileReader(contactsFile), 8192);
256             String name;
257             for (int id = 1; (name = br.readLine()) != null; id++) {
258                 contacts.add(new VoiceContact(name, id, ID_UNDEFINED,
259                         ID_UNDEFINED, ID_UNDEFINED, ID_UNDEFINED, ID_UNDEFINED));
260             }
261         }
262         catch (IOException e) {
263             if (false) Log.d(TAG, "getVoiceContactsFromFile failed " + e);
264         }
265         finally {
266             try {
267                 br.close();
268             } catch (IOException e) {
269                 if (false) Log.d(TAG, "getVoiceContactsFromFile failed during close " + e);
270             }
271         }
272 
273         if (false) Log.d(TAG, "getVoiceContactsFromFile " + contacts.size());
274 
275         return contacts;
276     }
277 
278     /**
279      * @param activity The VoiceDialerActivity instance.
280      * @return String of last number dialed.
281      */
redialNumber(Activity activity)282     public static String redialNumber(Activity activity) {
283         Cursor cursor = activity.getContentResolver().query(
284                 CallLog.Calls.CONTENT_URI,
285                 new String[] { CallLog.Calls.NUMBER },
286                 CallLog.Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE,
287                 null,
288                 CallLog.Calls.DEFAULT_SORT_ORDER + " LIMIT 1");
289         String number = null;
290         if (cursor.getCount() >= 1) {
291             cursor.moveToNext();
292             int column = cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER);
293             number = cursor.getString(column);
294         }
295         cursor.close();
296 
297         if (false) Log.d(TAG, "redialNumber " + number);
298 
299         return number;
300     }
301 
302 }
303