BluetoothPbapVcardManager.java revision 4446eaa935994bc91d6d308303e8d27526b4590d
1/* 2 * Copyright (c) 2008-2009, Motorola, Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Motorola, Inc. nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33package com.android.bluetooth.pbap; 34 35import com.android.bluetooth.R; 36 37import android.content.ContentResolver; 38import android.content.Context; 39import android.database.Cursor; 40import android.net.Uri; 41import android.provider.Contacts; 42import android.provider.CallLog.Calls; 43import android.provider.Contacts.Organizations; 44import android.provider.CallLog; 45import android.provider.Contacts.People; 46import android.provider.Contacts.Phones; 47import android.provider.Contacts.People.ContactMethods; 48import android.syncml.pim.vcard.ContactStruct; 49import android.syncml.pim.vcard.VCardComposer; 50import android.syncml.pim.vcard.VCardException; 51import android.syncml.pim.vcard.VCardParser; 52import android.util.Log; 53 54import java.util.ArrayList; 55import java.util.Arrays; 56import java.util.HashMap; 57import java.util.List; 58 59public class BluetoothPbapVcardManager { 60 static private final String TAG = "BluetoothPbapVcardManager"; 61 62 private static final boolean V = BluetoothPbapService.VERBOSE; 63 64 private ContentResolver mResolver; 65 66 private Context mContext; 67 68 private String mDefaultName = null; 69 70 private String mDefaultNumber = null; 71 72 /** The projection to use when querying the call log table */ 73 public static final String[] CALL_LOG_PROJECTION = new String[] { 74 Calls._ID, Calls.NUMBER, Calls.DATE, Calls.DURATION, Calls.TYPE, Calls.CACHED_NAME, 75 Calls.CACHED_NUMBER_TYPE, Calls.CACHED_NUMBER_LABEL 76 }; 77 78 public static final int ID_COLUMN_INDEX = 0; 79 80 public static final int NUMBER_COLUMN_INDEX = 1; 81 82 public static final int DATE_COLUMN_INDEX = 2; 83 84 public static final int DURATION_COLUMN_INDEX = 3; 85 86 public static final int CALL_TYPE_COLUMN_INDEX = 4; 87 88 public static final int CALLER_NAME_COLUMN_INDEX = 5; 89 90 public static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 6; 91 92 public static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 7; 93 94 /** The projection to use when querying the phone book table */ 95 public static final String[] CONTACT_PROJECTION = new String[] { 96 People._ID, // 0 97 People.NAME, // 1 98 People.NOTES, // 2 99 People.PRIMARY_PHONE_ID, // 3 100 People.PRESENCE_STATUS, // 4 101 People.STARRED, // 5 102 People.CUSTOM_RINGTONE, // 6 103 People.SEND_TO_VOICEMAIL, // 7 104 People.PHONETIC_NAME, // 8 105 People.PRIMARY_EMAIL_ID, // 9 106 People.PRIMARY_ORGANIZATION_ID, // 10 107 }; 108 109 public static final int CONTACT_ID_COLUMN = 0; 110 111 public static final int CONTACT_NAME_COLUMN = 1; 112 113 public static final int CONTACT_NOTES_COLUMN = 2; 114 115 public static final int CONTACT_PRIMARY_PHONE_ID_COLUMN = 3; 116 117 public static final int CONTACT_SERVER_STATUS_COLUMN = 4; 118 119 public static final int CONTACT_STARRED_COLUMN = 5; 120 121 public static final int CONTACT_CUSTOM_RINGTONE_COLUMN = 6; 122 123 public static final int CONTACT_SEND_TO_VOICEMAIL_COLUMN = 7; 124 125 public static final int CONTACT_PHONETIC_NAME_COLUMN = 8; 126 127 public static final int CONTACT_PRIMARY_EMAIL_ID_COLUMN = 9; 128 129 public static final int CONTACT_PRIMARY_ORGANIZATION_ID_COLUMN = 10; 130 131 public static final String[] PHONES_PROJECTION = new String[] { 132 Phones._ID, // 0 133 Phones.NUMBER, // 1 134 Phones.TYPE, // 2 135 Phones.LABEL, // 3 136 Phones.ISPRIMARY, // 4 137 Phones.PERSON_ID, // 5 138 }; 139 140 public static final int PHONES_ID_COLUMN = 0; 141 142 public static final int PHONES_NUMBER_COLUMN = 1; 143 144 public static final int PHONES_TYPE_COLUMN = 2; 145 146 public static final int PHONES_LABEL_COLUMN = 3; 147 148 public static final int PHONES_ISPRIMARY_COLUMN = 4; 149 150 public static final int PHONES_PERSON_ID_COLUMN = 5; 151 152 public static final String[] METHODS_PROJECTION = new String[] { 153 ContactMethods._ID, // 0 154 ContactMethods.KIND, // 1 155 ContactMethods.DATA, // 2 156 ContactMethods.TYPE, // 3 157 ContactMethods.LABEL, // 4 158 ContactMethods.ISPRIMARY, // 5 159 ContactMethods.AUX_DATA, // 6 160 Phones.PERSON_ID, // 7 161 }; 162 163 public static final int METHODS_ID_COLUMN = 0; 164 165 public static final int METHODS_KIND_COLUMN = 1; 166 167 public static final int METHODS_DATA_COLUMN = 2; 168 169 public static final int METHODS_TYPE_COLUMN = 3; 170 171 public static final int METHODS_LABEL_COLUMN = 4; 172 173 public static final int METHODS_ISPRIMARY_COLUMN = 5; 174 175 public static final int METHODS_AUX_DATA_COLUMN = 6; 176 177 public static final int METHODS_PERSON_COLUMN = 7; 178 179 public static final String[] ORGANIZATIONS_PROJECTION = new String[] { 180 Organizations._ID, // 0 181 Organizations.TYPE, // 1 182 Organizations.LABEL, // 2 183 Organizations.COMPANY, // 3 184 Organizations.TITLE, // 4 185 Organizations.ISPRIMARY, // 5 186 Organizations.PERSON_ID, // 6 187 }; 188 189 public static final int ORGANIZATIONS_ID_COLUMN = 0; 190 191 public static final int ORGANIZATIONS_TYPE_COLUMN = 1; 192 193 public static final int ORGANIZATIONS_LABEL_COLUMN = 2; 194 195 public static final int ORGANIZATIONS_COMPANY_COLUMN = 3; 196 197 public static final int ORGANIZATIONS_TITLE_COLUMN = 4; 198 199 public static final int ORGANIZATIONS_ISPRIMARY_COLUMN = 5; 200 201 public static final int ORGANIZATIONS_PERSON_ID_COLUMN = 6; 202 203 public static final String SORT_ORDER = "person ASC"; 204 205 private int QUERY_DB_ERROR = -1; 206 207 private int QUERY_DB_OK = 1; 208 209 private Cursor peopleCursor, phonesCursor, contactMethodsCursor, orgCursor, callLogCursor; 210 211 private HashMap<Integer, String> mPhones; 212 213 private HashMap<Integer, String> mContactMethods; 214 215 private HashMap<Integer, String> mOrganizations; 216 217 private HashMap<Integer, HashMap<Integer, String>> tableList; 218 219 public static final int TABLE_PHONE = 0; 220 221 public static final int TABLE_CONTACTMETHOD = 1; 222 223 public static final int TABLE_ORGANIZATION = 2; 224 225 public BluetoothPbapVcardManager(final Context context) { 226 mContext = context; 227 mResolver = mContext.getContentResolver(); 228 mDefaultName = context.getString(android.R.string.unknownName); 229 mDefaultNumber = context.getString(R.string.defaultnumber); 230 231 mPhones = new HashMap<Integer, String>(); 232 mContactMethods = new HashMap<Integer, String>(); 233 mOrganizations = new HashMap<Integer, String>(); 234 235 tableList = new HashMap<Integer, HashMap<Integer, String>>(); 236 tableList.put(TABLE_PHONE, mPhones); 237 tableList.put(TABLE_CONTACTMETHOD, mContactMethods); 238 tableList.put(TABLE_ORGANIZATION, mOrganizations); 239 } 240 241 private String getThisPhoneName() { 242 String name; 243 name = BluetoothPbapService.getLocalPhoneName(); 244 if (name == null || name.trim().length() == 0) { 245 name = mDefaultName; 246 } 247 return name; 248 } 249 250 private String getThisPhoneNumber() { 251 String number; 252 number = BluetoothPbapService.getLocalPhoneNum(); 253 if (number == null || number.trim().length() == 0) { 254 number = mDefaultNumber; 255 } 256 return number; 257 } 258 259 public final int getPhonebookSize() { 260 Uri myUri = Contacts.People.CONTENT_URI; 261 Cursor contactC = mResolver.query(myUri, null, null, null, null); 262 263 int mPhonebookSize = 0; 264 if (contactC != null) { 265 mPhonebookSize = contactC.getCount() + 1; // always has the 0.vcf 266 } 267 return mPhonebookSize; 268 } 269 270 /** 271 * For each table - phones/contact_methods/organization: 272 * Save the cursor positions for one person to hashMap. 273 * @hide 274 */ 275 private int fillDataToHashmap(int table) { 276 int person_column; 277 Cursor cursor; 278 279 if (table == TABLE_PHONE) { 280 cursor = phonesCursor; 281 person_column = PHONES_PERSON_ID_COLUMN; 282 283 } else if (table == TABLE_CONTACTMETHOD) { 284 cursor = contactMethodsCursor; 285 person_column = METHODS_PERSON_COLUMN; 286 287 } else if (table == TABLE_ORGANIZATION) { 288 cursor = orgCursor; 289 person_column = ORGANIZATIONS_PERSON_ID_COLUMN; 290 291 } else { 292 Log.w(TAG, "fillDataToHashmap(): - no such table-" + table); 293 return -1; 294 } 295 296 // Clear HashMap first 297 tableList.get(table).clear(); 298 299 // Represent the cursor position for phone_id or contactMethod_id or 300 // orgnization_id 301 int x_cursor_pos = 0; 302 int person_id = 0; 303 int previous_person_id = 0; 304 StringBuilder result = new StringBuilder(); 305 for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 306 person_id = cursor.getInt(person_column); 307 308 if (cursor.isFirst()) { 309 previous_person_id = person_id; 310 } 311 312 if (person_id != previous_person_id) { 313 tableList.get(table).put(previous_person_id, result.toString()); 314 result = result.delete(0, result.length()); 315 } 316 result.append(x_cursor_pos); 317 result.append(","); 318 previous_person_id = person_id; 319 x_cursor_pos++; 320 321 if (cursor.isLast()) { 322 tableList.get(table).put(previous_person_id, result.toString()); 323 } 324 } 325 return 1; 326 } 327 328 public final void closeContactsCursor() { 329 peopleCursor.close(); 330 contactMethodsCursor.close(); 331 orgCursor.close(); 332 } 333 334 public final void closeCallLogCursor() { 335 callLogCursor.close(); 336 } 337 338 public final int queryDataFromCallLogDB(int type) { 339 Uri myUri = CallLog.Calls.CONTENT_URI; 340 String selection = null; 341 switch (type) { 342 case BluetoothPbapObexServer.ContentType.INCOMING_CALL_HISTORY: 343 selection = Calls.TYPE + "=" + CallLog.Calls.INCOMING_TYPE; 344 break; 345 case BluetoothPbapObexServer.ContentType.OUTGOING_CALL_HISTORY: 346 selection = Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE; 347 break; 348 case BluetoothPbapObexServer.ContentType.MISSED_CALL_HISTORY: 349 selection = Calls.TYPE + "=" + CallLog.Calls.MISSED_TYPE; 350 break; 351 default: 352 break; 353 } 354 callLogCursor = mResolver.query(myUri, CALL_LOG_PROJECTION, selection, null, 355 CallLog.Calls.DEFAULT_SORT_ORDER); 356 357 if (callLogCursor == null) { 358 Log.w(TAG, "Query table - call Log failed."); 359 return QUERY_DB_ERROR; 360 } 361 return QUERY_DB_OK; 362 } 363 364 public final int queryDataFromContactsDB() { 365 Uri peopleUri = Contacts.People.CONTENT_URI; 366 peopleCursor = mResolver.query(peopleUri, CONTACT_PROJECTION, null, null, 367 People._ID + " ASC"); 368 if (peopleCursor == null) { 369 Log.w(TAG, "Query table - people failed."); 370 return QUERY_DB_ERROR; 371 } 372 373 Uri phonesUri = Contacts.Phones.CONTENT_URI; 374 phonesCursor = mResolver.query(phonesUri, PHONES_PROJECTION, null, null, SORT_ORDER); 375 if (phonesCursor == null) { 376 Log.w(TAG, "Query table - phone failed."); 377 return QUERY_DB_ERROR; 378 } 379 fillDataToHashmap(TABLE_PHONE); 380 381 Uri contactMethodsUri = Contacts.ContactMethods.CONTENT_URI; 382 contactMethodsCursor = mResolver.query(contactMethodsUri, METHODS_PROJECTION, null, null, 383 SORT_ORDER); 384 if (contactMethodsCursor == null) { 385 Log.w(TAG, "Query table - contact_method failed."); 386 return QUERY_DB_ERROR; 387 } 388 fillDataToHashmap(TABLE_CONTACTMETHOD); 389 390 Uri orgUri = Contacts.Organizations.CONTENT_URI; 391 orgCursor = mResolver.query(orgUri, ORGANIZATIONS_PROJECTION, null, null, SORT_ORDER); 392 if (orgCursor == null) { 393 Log.w(TAG, "Query table - organization failed."); 394 return QUERY_DB_ERROR; 395 } 396 fillDataToHashmap(TABLE_ORGANIZATION); 397 398 return QUERY_DB_OK; 399 } 400 401 private List<String> parseOutCursorPosForOnePerson(int table, int peopleId) { 402 if (V) Log.v(TAG, "parseOutCursorPos(): table=" + table + "; peopleId=" + peopleId); 403 404 String tmpStr = tableList.get(table).get(peopleId); 405 if (tmpStr == null || tmpStr.trim().length() == 0) { 406 Log.w(TAG, "Can not get curPosStr from HashMap."); 407 return null; 408 } 409 410 String[] splitStr = tmpStr.split(","); 411 412 List<String> list = Arrays.asList(splitStr); 413 414 if (V) Log.v(TAG, "parseOutIds(): list=" + list.toString()); 415 416 return list; 417 } 418 419 public final String getPhonebook(final int pos, final boolean vcardType) { 420 // Build up the phone entries 421 ContactStruct contactStruct = new ContactStruct(); 422 423 if (pos == 0) { 424 contactStruct.name = getThisPhoneName(); 425 contactStruct.addPhone(Contacts.PhonesColumns.TYPE_MOBILE, getThisPhoneNumber(), "", 426 true); 427 } else { 428 if (!peopleCursor.moveToPosition(pos - 1)) { 429 Log.w(TAG, "peopleCursor can not moveToPosition: " + (pos - 1)); 430 return null; 431 } 432 433 int peopleId = peopleCursor.getInt(CONTACT_ID_COLUMN); 434 int primary_phone = peopleCursor.getInt(CONTACT_PRIMARY_PHONE_ID_COLUMN); 435 int primary_contactMethod = peopleCursor.getInt(CONTACT_PRIMARY_EMAIL_ID_COLUMN); 436 int primary_org = peopleCursor.getInt(CONTACT_PRIMARY_ORGANIZATION_ID_COLUMN); 437 438 String name = peopleCursor.getString(CONTACT_NAME_COLUMN); 439 if (V) Log.v(TAG, "query data from table-people: name=" + name + "; primary_phone=" 440 + primary_phone + "; primary_contactmehtod=" + primary_contactMethod 441 + "; primary_org=" + primary_org); 442 443 444 // build basic info 445 if (name == null || name.trim().length() == 0) { 446 contactStruct.name = mDefaultName; 447 } else { 448 contactStruct.name = name; 449 } 450 contactStruct.notes.add(checkStrEnd(peopleCursor.getString(CONTACT_NOTES_COLUMN), 451 vcardType)); 452 453 String tmpStr = null; 454 List<String> posList = null; 455 String curPosStr = null; 456 int cursorPos = 0; 457 // build phone info 458 if (primary_phone != 0) { 459 posList = parseOutCursorPosForOnePerson(TABLE_PHONE, peopleId); 460 for (int i = 0; i < posList.size(); i++) { 461 curPosStr = posList.get(i).toString(); 462 cursorPos = Integer.parseInt(curPosStr); 463 if (cursorPos < 0 || cursorPos > phonesCursor.getCount()) { 464 Log.w(TAG, "Get incorrect cursor position from HashMap."); 465 return null; 466 } 467 if (phonesCursor.moveToPosition(cursorPos)) { 468 int type = phonesCursor.getInt(PHONES_TYPE_COLUMN); 469 String number = phonesCursor.getString(PHONES_NUMBER_COLUMN); 470 String label = phonesCursor.getString(PHONES_LABEL_COLUMN); 471 boolean isPrimary = phonesCursor.getInt(PHONES_ISPRIMARY_COLUMN) 472 == 1 ? true : false; 473 if (V) Log.v(TAG, "query data from table-phones: type=" + type + 474 "; number=" + number + "; label=" + label + "; isPrimary=" 475 + isPrimary); 476 477 contactStruct.addPhone(type, number, label, isPrimary); 478 } 479 } 480 } 481 482 // build contact_methods info 483 if (primary_contactMethod != 0) { 484 posList = parseOutCursorPosForOnePerson(TABLE_CONTACTMETHOD, peopleId); 485 for (int i = 0; i < posList.size(); i++) { 486 curPosStr = posList.get(i).toString(); 487 cursorPos = Integer.parseInt(curPosStr); 488 if (cursorPos < 0 || cursorPos > contactMethodsCursor.getCount()) { 489 Log.w(TAG, "Get incorrect method cursor position from HashMap."); 490 return null; 491 } 492 if (contactMethodsCursor.moveToPosition(cursorPos)) { 493 int kind = contactMethodsCursor.getInt(METHODS_KIND_COLUMN); 494 String label = contactMethodsCursor.getString(METHODS_LABEL_COLUMN); 495 String data = contactMethodsCursor.getString(METHODS_DATA_COLUMN); 496 int type = contactMethodsCursor.getInt(METHODS_TYPE_COLUMN); 497 boolean isPrimary = contactMethodsCursor.getInt(METHODS_ISPRIMARY_COLUMN) 498 == 1 ? true : false; 499 /* 500 * TODO Below code is totally depend on the 501 * implementation of package android.syncml.pim.vcard 502 * VcardComposer shall throw null pointer exception when 503 * label is not set function appendContactMethodStr is 504 * weak and shall be improved in the future 505 */ 506 if (kind == Contacts.KIND_EMAIL) { 507 if (type == Contacts.ContactMethodsColumns.TYPE_OTHER) { 508 if (label == null || label.trim().length() == 0) { 509 label = Integer.toString(type); 510 } 511 } 512 } 513 if (kind == Contacts.KIND_POSTAL) { 514 data = checkStrEnd(data, vcardType); 515 } 516 if (V) Log.v(TAG, "query data from table-contactMethods: kind=" + kind 517 + "; label=" + label + "; data=" + data); 518 519 contactStruct.addContactmethod(kind, type, data, label, isPrimary); 520 } 521 } 522 } 523 524 // build organization info 525 if (primary_org != 0) { 526 posList = parseOutCursorPosForOnePerson(TABLE_CONTACTMETHOD, peopleId); 527 for (int i = 0; i < posList.size(); i++) { 528 curPosStr = posList.get(i).toString(); 529 cursorPos = Integer.parseInt(curPosStr); 530 if (cursorPos < 0 || cursorPos > orgCursor.getCount()) { 531 Log.w(TAG, "Get incorrect cursor position from HashMap."); 532 return null; 533 } 534 if (orgCursor.moveToPosition(cursorPos)) { 535 int type = orgCursor.getInt(ORGANIZATIONS_TYPE_COLUMN); 536 String company = orgCursor.getString(ORGANIZATIONS_COMPANY_COLUMN); 537 String title = checkStrEnd(orgCursor.getString(ORGANIZATIONS_TITLE_COLUMN), 538 vcardType); 539 boolean isPrimary; 540 isPrimary = orgCursor.getInt(ORGANIZATIONS_ISPRIMARY_COLUMN) == 1 ? true 541 : false; 542 if (V) Log.v(TAG, "query data from table-organization: type=" + type 543 + "; company=" + company + "; title=" + title); 544 545 contactStruct.addOrganization(type, company, title, isPrimary); 546 } 547 } 548 } 549 } 550 551 String vcardStr; 552 // Generate vCard data. 553 try { 554 VCardComposer composer = new VCardComposer(); 555 if (vcardType) { 556 vcardStr = composer.createVCard(contactStruct, VCardParser.VERSION_VCARD21_INT); 557 } else { 558 vcardStr = composer.createVCard(contactStruct, VCardParser.VERSION_VCARD30_INT); 559 } 560 } catch (VCardException e) { 561 Log.e(TAG, "catch exception in loadPhonebook" + e.toString()); 562 return null; 563 } 564 return vcardStr; 565 } 566 567 public final int getCallHistorySize(final int type) { 568 Uri myUri = CallLog.Calls.CONTENT_URI; 569 String selection = null; 570 switch (type) { 571 case BluetoothPbapObexServer.ContentType.INCOMING_CALL_HISTORY: 572 selection = Calls.TYPE + "=" + CallLog.Calls.INCOMING_TYPE; 573 break; 574 case BluetoothPbapObexServer.ContentType.OUTGOING_CALL_HISTORY: 575 selection = Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE; 576 break; 577 case BluetoothPbapObexServer.ContentType.MISSED_CALL_HISTORY: 578 selection = Calls.TYPE + "=" + CallLog.Calls.MISSED_TYPE; 579 break; 580 default: 581 break; 582 } 583 Cursor callCursor = mResolver.query(myUri, null, selection, null, 584 CallLog.Calls.DEFAULT_SORT_ORDER); 585 int size = 0; 586 if (callCursor != null) { 587 size = callCursor.getCount(); 588 callCursor.close(); 589 } 590 return size; 591 } 592 593 public final String getCallHistory(final int pos, final boolean vCard21) { 594 try { 595 int size = callLogCursor.getCount(); 596 if (pos >= 0 && pos < size) { 597 ContactStruct contactStruct = new ContactStruct(); 598 if (callLogCursor.moveToPosition(pos)) { 599 contactStruct.name = callLogCursor.getString(CALLER_NAME_COLUMN_INDEX); 600 if (contactStruct.name == null || contactStruct.name.trim().length() == 0) { 601 contactStruct.name = callLogCursor.getString(NUMBER_COLUMN_INDEX); 602 } 603 String number = callLogCursor.getString(NUMBER_COLUMN_INDEX); 604 int type = callLogCursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX); 605 String label = callLogCursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX); 606 if (label == null || label.trim().length() == 0) { 607 label = Integer.toString(type); 608 } 609 contactStruct.addPhone(type, number, label, true); 610 } 611 612 try { 613 VCardComposer composer = new VCardComposer(); 614 if (vCard21) { 615 return composer.createVCard(contactStruct, 616 VCardParser.VERSION_VCARD21_INT); 617 } else { 618 return composer.createVCard(contactStruct, 619 VCardParser.VERSION_VCARD30_INT); 620 } 621 } catch (VCardException e) { 622 Log.e(TAG, "catch exception" + e.toString()); 623 } 624 } else { 625 Log.w(TAG, "pos invalid"); 626 } 627 } catch (Exception e) { 628 Log.e(TAG, "catch exception e" + e.toString()); 629 } 630 return null; 631 } 632 633 public final ArrayList<String> loadNameList() { 634 ArrayList<String> nameList = new ArrayList<String>(); 635 int size = getPhonebookSize(); 636 Uri myUri = Contacts.People.CONTENT_URI; 637 Cursor contactC = mResolver.query(myUri, null, null, null, null); 638 for (int pos = 0; pos < size; pos++) { 639 if (pos == 0) { 640 nameList.add(getThisPhoneName()); 641 } else { 642 if (contactC != null) { 643 contactC.moveToPosition(pos - 1); 644 String name = contactC.getString(contactC 645 .getColumnIndexOrThrow(Contacts.People.NAME)); 646 if (name == null || name.trim().length() == 0) { 647 name = mDefaultName; 648 } 649 nameList.add(name); 650 } 651 } 652 } 653 if (contactC != null) { 654 contactC.close(); 655 } 656 return nameList; 657 } 658 659 public final ArrayList<String> loadNumberList() { 660 ArrayList<String> numberList = new ArrayList<String>(); 661 if (numberList.size() > 0) { 662 numberList.clear(); 663 } 664 int size = getPhonebookSize(); 665 Uri myUri = Contacts.People.CONTENT_URI; 666 Cursor contactC = mResolver.query(myUri, null, null, null, null); 667 for (int pos = 0; pos < size; pos++) { 668 if (pos == 0) { 669 numberList.add(getThisPhoneNumber()); 670 } else { 671 contactC.moveToPosition(pos - 1); 672 String number = contactC.getString(contactC 673 .getColumnIndexOrThrow(Contacts.People.PRIMARY_PHONE_ID)); 674 if (number == null || number.trim().length() == 0) { 675 number = mDefaultNumber; 676 } 677 numberList.add(number); 678 } 679 } 680 return numberList; 681 } 682 683 public final ArrayList<String> loadCallHistoryList(final int type) { 684 int size = 0; 685 String selection = null; 686 Uri myUri = CallLog.Calls.CONTENT_URI; 687 ArrayList<String> list = new ArrayList<String>(); 688 switch (type) { 689 case BluetoothPbapObexServer.ContentType.INCOMING_CALL_HISTORY: 690 selection = Calls.TYPE + "=" + CallLog.Calls.INCOMING_TYPE; 691 break; 692 case BluetoothPbapObexServer.ContentType.OUTGOING_CALL_HISTORY: 693 selection = Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE; 694 break; 695 case BluetoothPbapObexServer.ContentType.MISSED_CALL_HISTORY: 696 selection = Calls.TYPE + "=" + CallLog.Calls.MISSED_TYPE; 697 break; 698 default: 699 break; 700 } 701 size = getCallHistorySize(type); 702 Cursor callCursor = mResolver.query(myUri, CALL_LOG_PROJECTION, selection, null, 703 CallLog.Calls.DEFAULT_SORT_ORDER); 704 if (callCursor != null) { 705 for (int pos = 0; pos < size; pos++) { 706 callCursor.moveToPosition(pos); 707 String name = callCursor.getString(CALLER_NAME_COLUMN_INDEX); 708 if (name == null || name.trim().length() == 0) { 709 // name not found,use number instead 710 name = callCursor.getString(NUMBER_COLUMN_INDEX); 711 } 712 list.add(name); 713 } 714 callCursor.close(); 715 } 716 return list; 717 } 718 719 /** 720 * This function is to check the string end to avoid function 721 * foldingString's returning null in package android.syncml.pim.vcard 722 */ 723 private final String checkStrEnd(String str, final boolean vCard21) { 724 if (str == null || str.trim().length() == 0) { 725 return str; 726 } 727 if (str.charAt(str.length() - 1) != '\n') { 728 if (vCard21) { 729 str += "\r\n"; 730 } else { 731 str += "\n"; 732 } 733 } 734 return str; 735 } 736} 737