| /* |
| * Copyright (C) 2007 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.voicedialer; |
| |
| import android.app.Activity; |
| import android.database.Cursor; |
| import android.database.DatabaseUtils; |
| import android.provider.ContactsContract.CommonDataKinds.Phone; |
| import android.provider.CallLog; |
| import android.util.Log; |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| |
| /** |
| * This class represents a person who may be called via the VoiceDialer app. |
| * The person has a name and a list of phones (home, mobile, work, other). |
| */ |
| public class VoiceContact { |
| private static final String TAG = "VoiceContact"; |
| |
| /** |
| * Corresponding row doesn't exist. |
| */ |
| public static final long ID_UNDEFINED = -1; |
| |
| public final String mName; |
| public final long mContactId; |
| public final long mPrimaryId; |
| public final long mHomeId; |
| public final long mMobileId; |
| public final long mWorkId; |
| public final long mOtherId; |
| |
| /** |
| * Constructor. |
| * |
| * @param name person's name. |
| * @param contactId ID in person table. |
| * @param primaryId primary ID in phone table. |
| * @param homeId home ID in phone table. |
| * @param mobileId mobile ID in phone table. |
| * @param workId work ID in phone table. |
| * @param otherId other ID in phone table. |
| */ |
| private VoiceContact(String name, long contactId, long primaryId, |
| long homeId, long mobileId, long workId,long otherId) { |
| mName = name; |
| mContactId = contactId; |
| mPrimaryId = primaryId; |
| mHomeId = homeId; |
| mMobileId = mobileId; |
| mWorkId = workId; |
| mOtherId = otherId; |
| } |
| |
| @Override |
| public int hashCode() { |
| final int LARGE_PRIME = 1610612741; |
| int hash = 0; |
| hash = LARGE_PRIME * (hash + (int)mContactId); |
| hash = LARGE_PRIME * (hash + (int)mPrimaryId); |
| hash = LARGE_PRIME * (hash + (int)mHomeId); |
| hash = LARGE_PRIME * (hash + (int)mMobileId); |
| hash = LARGE_PRIME * (hash + (int)mWorkId); |
| hash = LARGE_PRIME * (hash + (int)mOtherId); |
| return mName.hashCode() + hash; |
| } |
| |
| @Override |
| public String toString() { |
| return "mName=" + mName |
| + " mPersonId=" + mContactId |
| + " mPrimaryId=" + mPrimaryId |
| + " mHomeId=" + mHomeId |
| + " mMobileId=" + mMobileId |
| + " mWorkId=" + mWorkId |
| + " mOtherId=" + mOtherId; |
| } |
| |
| /** |
| * @param activity The VoiceDialerActivity instance. |
| * @return List of {@link VoiceContact} from |
| * the contact list content provider. |
| */ |
| public static List<VoiceContact> getVoiceContacts(Activity activity) { |
| if (false) Log.d(TAG, "VoiceContact.getVoiceContacts"); |
| |
| List<VoiceContact> contacts = new ArrayList<VoiceContact>(); |
| |
| String[] phonesProjection = new String[] { |
| Phone._ID, |
| Phone.TYPE, |
| Phone.IS_PRIMARY, |
| // TODO: handle type != 0,1,2, and use LABEL |
| Phone.LABEL, |
| Phone.DISPLAY_NAME, |
| Phone.CONTACT_ID, |
| }; |
| |
| // Table is sorted by number of times contacted and name. If we cannot fit all contacts |
| // in the recognizer, we will at least have the commonly used ones. |
| Cursor cursor = activity.getContentResolver().query( |
| Phone.CONTENT_URI, phonesProjection, |
| Phone.NUMBER + " NOT NULL", null, |
| Phone.LAST_TIME_CONTACTED + " DESC, " + Phone.DISPLAY_NAME + " ASC"); |
| |
| final int phoneIdColumn = cursor.getColumnIndexOrThrow(Phone._ID); |
| final int typeColumn = cursor.getColumnIndexOrThrow(Phone.TYPE); |
| final int isPrimaryColumn = cursor.getColumnIndexOrThrow(Phone.IS_PRIMARY); |
| final int labelColumn = cursor.getColumnIndexOrThrow(Phone.LABEL); |
| final int nameColumn = cursor.getColumnIndexOrThrow(Phone.DISPLAY_NAME); |
| final int personIdColumn = cursor.getColumnIndexOrThrow(Phone.CONTACT_ID); |
| |
| // pieces of next VoiceContact |
| String name = null; |
| long personId = ID_UNDEFINED; |
| long primaryId = ID_UNDEFINED; |
| long homeId = ID_UNDEFINED; |
| long mobileId = ID_UNDEFINED; |
| long workId = ID_UNDEFINED; |
| long otherId = ID_UNDEFINED; |
| |
| // loop over phone table |
| for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { |
| long phoneIdAtCursor = cursor.getLong(phoneIdColumn); |
| int typeAtCursor = cursor.getInt(typeColumn); |
| long isPrimaryAtCursor = cursor.getLong(isPrimaryColumn); |
| String labelAtCursor = cursor.getString(labelColumn); |
| String nameAtCursor = cursor.getString(nameColumn); |
| long personIdAtCursor = cursor.getLong(personIdColumn); |
| |
| /* |
| if (false) { |
| Log.d(TAG, "phoneId=" + phoneIdAtCursor |
| + " type=" + typeAtCursor |
| + " isPrimary=" + isPrimaryAtCursor |
| + " label=" + labelAtCursor |
| + " name=" + nameAtCursor |
| + " personId=" + personIdAtCursor |
| ); |
| } |
| */ |
| |
| // encountered a new name, so generate current VoiceContact |
| if (name != null && !name.equals(nameAtCursor)) { |
| contacts.add(new VoiceContact(name, personId, primaryId, |
| homeId, mobileId, workId, otherId)); |
| name = null; |
| } |
| |
| // start accumulating pieces for a new VoiceContact |
| if (name == null) { |
| name = nameAtCursor; |
| personId = personIdAtCursor; |
| primaryId = ID_UNDEFINED; |
| homeId = ID_UNDEFINED; |
| mobileId = ID_UNDEFINED; |
| workId = ID_UNDEFINED; |
| otherId = ID_UNDEFINED; |
| } |
| |
| // if labeled, then patch to HOME/MOBILE/WORK/OTHER |
| if (typeAtCursor == Phone.TYPE_CUSTOM && |
| labelAtCursor != null) { |
| String label = labelAtCursor.toLowerCase(); |
| if (label.contains("home") || label.contains("house")) { |
| typeAtCursor = Phone.TYPE_HOME; |
| } |
| else if (label.contains("mobile") || label.contains("cell")) { |
| typeAtCursor = Phone.TYPE_MOBILE; |
| } |
| else if (label.contains("work") || label.contains("office")) { |
| typeAtCursor = Phone.TYPE_WORK; |
| } |
| else if (label.contains("other")) { |
| typeAtCursor = Phone.TYPE_OTHER; |
| } |
| } |
| |
| // save the home, mobile, or work phone id |
| switch (typeAtCursor) { |
| case Phone.TYPE_HOME: |
| homeId = phoneIdAtCursor; |
| if (isPrimaryAtCursor != 0) { |
| primaryId = phoneIdAtCursor; |
| } |
| break; |
| case Phone.TYPE_MOBILE: |
| mobileId = phoneIdAtCursor; |
| if (isPrimaryAtCursor != 0) { |
| primaryId = phoneIdAtCursor; |
| } |
| break; |
| case Phone.TYPE_WORK: |
| workId = phoneIdAtCursor; |
| if (isPrimaryAtCursor != 0) { |
| primaryId = phoneIdAtCursor; |
| } |
| break; |
| case Phone.TYPE_OTHER: |
| otherId = phoneIdAtCursor; |
| if (isPrimaryAtCursor != 0) { |
| primaryId = phoneIdAtCursor; |
| } |
| break; |
| } |
| } |
| |
| // generate the last VoiceContact |
| if (name != null) { |
| contacts.add(new VoiceContact(name, personId, primaryId, |
| homeId, mobileId, workId, otherId)); |
| } |
| |
| // clean up cursor |
| cursor.close(); |
| |
| if (false) Log.d(TAG, "VoiceContact.getVoiceContacts " + contacts.size()); |
| |
| return contacts; |
| } |
| |
| /** |
| * @param contactsFile File containing a list of names, |
| * one per line. |
| * @return a List of {@link VoiceContact} in a File. |
| */ |
| public static List<VoiceContact> getVoiceContactsFromFile(File contactsFile) { |
| if (false) Log.d(TAG, "getVoiceContactsFromFile " + contactsFile); |
| |
| List<VoiceContact> contacts = new ArrayList<VoiceContact>(); |
| |
| // read from a file |
| BufferedReader br = null; |
| try { |
| br = new BufferedReader(new FileReader(contactsFile), 8192); |
| String name; |
| for (int id = 1; (name = br.readLine()) != null; id++) { |
| contacts.add(new VoiceContact(name, id, ID_UNDEFINED, |
| ID_UNDEFINED, ID_UNDEFINED, ID_UNDEFINED, ID_UNDEFINED)); |
| } |
| } |
| catch (IOException e) { |
| if (false) Log.d(TAG, "getVoiceContactsFromFile failed " + e); |
| } |
| finally { |
| try { |
| br.close(); |
| } catch (IOException e) { |
| if (false) Log.d(TAG, "getVoiceContactsFromFile failed during close " + e); |
| } |
| } |
| |
| if (false) Log.d(TAG, "getVoiceContactsFromFile " + contacts.size()); |
| |
| return contacts; |
| } |
| |
| /** |
| * @param activity The VoiceDialerActivity instance. |
| * @return String of last number dialed. |
| */ |
| public static String redialNumber(Activity activity) { |
| Cursor cursor = activity.getContentResolver().query( |
| CallLog.Calls.CONTENT_URI, |
| new String[] { CallLog.Calls.NUMBER }, |
| CallLog.Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE, |
| null, |
| CallLog.Calls.DEFAULT_SORT_ORDER + " LIMIT 1"); |
| String number = null; |
| if (cursor.getCount() >= 1) { |
| cursor.moveToNext(); |
| int column = cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER); |
| number = cursor.getString(column); |
| } |
| cursor.close(); |
| |
| if (false) Log.d(TAG, "redialNumber " + number); |
| |
| return number; |
| } |
| |
| } |