通訊錄查詢和新增

weixin_34234823發表於2015-11-14

本文概要:
在獲取通訊錄的時候會遇到各種坑。雖然網上也有不少關於該部分的內容,但大多數不能滿足我的需求。所以按照一貫的風格,自己動手豐衣足食。

通訊錄中遇到的坑

通訊錄是我們每天都會用到的應用,算是我們再也熟悉不過的。最近一段時間一直在做關於電話的應用,或多或少的會獲取通訊錄資訊。這部分程式碼的分析網上有一大堆。感興趣的同學可以自己搜尋學習。但在我看來這部分的內容,其實還是有點複雜的。獲取通訊錄的時候會牽扯到很多張表,剛開始的時候確實會讓人摸不著脈。特別是網上的資料,因為作者出發的角度不同,所以使用的API也會不一樣。這樣會給初學者帶來很多煩惱,從而使他們無法清楚的知道該如何正確的定製屬於他們的需要。

填坑

通訊錄的使用無非就是查詢、新增和刪除。是的,你沒有聽錯就是萬能的增刪改查。在這裡我對查詢和新增做了一個封裝,在大多數情況下基本能夠滿足我們的需要了。

1、查詢

查詢的核心程式碼如下。

// 本地通訊錄資料
 public List<Contacts> contacts; //這裡的Contacts是我們自定義的類
 
//載入本地通訊錄
 public void loadContacts() {
  contacts = new ArrayList<Contacts>();
  new AsyncTask<Object, Object, String>(){
   protected String doInBackground(Object... arg0) {
    String id;
    String mimetype;
    ContentResolver contentResolver = BaseApplication.getContextObject().getContentResolver();
    //只需要從Contacts中獲取ID,其他的都可以不要,通過檢視上面編譯後的SQL語句,可以看出將第二個引數
    //設定成null,預設返回的列非常多,是一種資源浪費。
    Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,
      new String[]{android.provider.ContactsContract.Contacts._ID}, null, null, null);
    Contacts contactitem;
    while(cursor.moveToNext()) {
     contactitem = new Contacts();//查詢的要建立新的contacts物件
     id=cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID));
     //從一個Cursor獲取所有的資訊
     Cursor contactInfoCursor = contentResolver.query(
       android.provider.ContactsContract.Data.CONTENT_URI,
       new String[]{android.provider.ContactsContract.Data.CONTACT_ID,
         android.provider.ContactsContract.Data.MIMETYPE,
         android.provider.ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, //使用者名稱
         android.provider.ContactsContract.CommonDataKinds.Organization.COMPANY,//公司
         android.provider.ContactsContract.CommonDataKinds.Organization.TITLE,//職稱
         android.provider.ContactsContract.CommonDataKinds.Phone.TYPE,//電話屬性
         android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER,// 電話號碼
         android.provider.ContactsContract.CommonDataKinds.Email.TYPE,//郵件屬性
         android.provider.ContactsContract.CommonDataKinds.Email.DATA,//郵件資訊
         android.provider.ContactsContract.CommonDataKinds.Note.NOTE,//備註
         android.provider.ContactsContract.Data.DATA1,//查詢的細節
         android.provider.ContactsContract.Data.DATA5
       }, 
       android.provider.ContactsContract.Data.CONTACT_ID+"="+id, null, null);
     while(contactInfoCursor.moveToNext()) {
      mimetype = contactInfoCursor.getString(
        contactInfoCursor.getColumnIndex(android.provider.ContactsContract.Data.MIMETYPE));

      if (mimetype.equals(StructuredName.CONTENT_ITEM_TYPE)) {
       String name = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
       //LogUtils.E("====name==="+name);
       contactitem.setName(name);
      } else if (mimetype.equals(Organization.CONTENT_ITEM_TYPE)) {
       String org = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.Organization.COMPANY));
       String title = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.Organization.TITLE));
       String department = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.Organization.DEPARTMENT));
       //LogUtils.E("====org==="+org+","+title);
       contactitem.setOrganization(org);
       contactitem.setJobtitle(title);
       contactitem.setDepartment(department);
      } else if (mimetype.equals(Phone.CONTENT_ITEM_TYPE)) {
       String type = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.Phone.TYPE));
       String number;
       String phonename = null;
       int a = Integer.parseInt(type);
       switch (a){
       case Phone.TYPE_MOBILE:
        phonename = "mobile";
        break;
       case Phone.TYPE_MAIN:
        phonename = "main";
        break;
       case Phone.TYPE_HOME:
        phonename = "home";
        break;
       case Phone.TYPE_WORK:
        phonename = "work";
        break;
       case Phone.TYPE_FAX_WORK:
        phonename = "fax_work";
        break;
       case Phone.TYPE_FAX_HOME:
        phonename = "fax_home";
        break;
       case Phone.TYPE_OTHER:
        phonename = "other";
        break;
       case Phone.TYPE_CUSTOM:
        phonename = "custom";
        break;
       }
       number = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER));
       //LogUtils.E("====phone==="+phonename+","+number);
       ContactFields cf = new ContactFields("Contact::Phone", phonename, number);
       contactitem.contact_fields.add(cf);

      } else if (mimetype.equals(Email.CONTENT_ITEM_TYPE)) {
       String type = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.Email.TYPE));
       String emailname = null;
       switch (Integer.parseInt(type)) {
       case Email.TYPE_WORK:
        emailname = "work";
        break;
       case Email.TYPE_CUSTOM:
        emailname = "custom";
        break;
       case Email.TYPE_MOBILE:
        emailname = "mobile";
        break;
       case Email.TYPE_HOME:
        emailname = "home";
        break;
       case Email.TYPE_OTHER:
        emailname = "other";
        break;
       }
       String date = contactInfoCursor.getString(contactInfoCursor  
         .getColumnIndexOrThrow(android.provider.ContactsContract.CommonDataKinds.Email.DATA));
       //LogUtils.E("====email==="+emailname+","+date);
       ContactFields cf = new ContactFields("Contact::Email", emailname, date);//ContactFields也是我自定義的一個物件,你可以根據需要定義自己的bean類
       contactitem.contact_fields.add(cf);

      } else if (mimetype.equals(Note.CONTENT_ITEM_TYPE)) {
       String note = contactInfoCursor.getString(
         contactInfoCursor.getColumnIndex(android.provider.ContactsContract.CommonDataKinds.Note.NOTE));
//       LogUtils.E("====note==="+note);
       contactitem.setNote(note);
      }
     }
     contacts.add(contactitem);
//     System.out.println("*********");
     contactInfoCursor.close();
    }
    cursor.close();
   
    return null;
   }
   
  }.execute();
 }

在上面的程式碼中mimetype屬性是十分重要的。它是android.provider.ContactsContract.Data.MIMETYPE屬性的內容。通過它我們可以判斷當前獲取資料表的列是哪種CONTENT_ITEM_TYPE。之後根據需要在對應的mimetype下,通過android.provider.ContactsContract.CommonDataKind來獲取對應索引列下的內容。程式碼中的關鍵部分我都做了註釋。至於android.provider.ContactsContract的用法和詳細說明,請自行查詢相關文件,在此不做過多介紹。

2、新增

新增的道理也是一樣,根據需要通過mimetype往通訊錄資料庫中新增內容。內容不是很複雜,直接上程式碼

/** 
  * 新增新的聯絡人
  * @param name 名稱 -- 不可為空
  * @param company 公司
  * @param position 職位
  * @param numberlist 電話列表
  * @param emaillist 郵箱列表
  * @param note 備註
  */
 public static void addContacts(Bitmap avatar, String name, String company, String position, List<AddContactsNumberItem> numberlist,
   List<AddContactsNumberItem> emaillist, String note){//AddContactsNumberItem為我自定義類,用來存放phone,email這樣的存在多條記錄的屬性值

  ContentValues values = new ContentValues();
  // 首先向RawContacts.CONTENT_URI執行一個空值插入,目的是獲取系統返回的rawContactId
  Uri rawContactUri = EPApplication.getContextObject().getContentResolver().insert(
    RawContacts.CONTENT_URI, values);//EPApplication是我定義的Application的子類,getContextObject方法返回的是context
  long rawContactId = ContentUris.parseId(rawContactUri);
  // 表插入姓名資料
  values.clear();
  values.put(Data.RAW_CONTACT_ID, rawContactId);
  values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);// 內容型別
  values.put(StructuredName.GIVEN_NAME, name);
  EPApplication.getContextObject().getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
    values);

  //新增公司和地址
  if (company != null || position != null) {
   values.clear();
   values.put(Data.RAW_CONTACT_ID, rawContactId);
   values.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
   if(company != null){
    values.put(Organization.COMPANY, company);
   }
   if (position != null) {
    values.put(Organization.TITLE, position);
   }
   values.put(Organization.TYPE, Organization.TYPE_WORK);
   EPApplication.getContextObject().getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
     values);
  }
  
  // 插入電話資料
  if (numberlist != null && numberlist.size()>0) {
   for (AddContactsNumberItem item : numberlist) {
    int type = 0;
    if (item.getName().equals("手機")) {
     type = Phone.TYPE_MOBILE;
    } else if (item.getName().equals("工作")){
     type = Phone.TYPE_WORK;
    } else if (item.getName().equals("家庭")){
     type = Phone.TYPE_HOME;
    } else if (item.getName().equals("工作傳真")){
     type = Phone.TYPE_FAX_WORK;
    } else if (item.getName().equals("家庭傳真")){
     type = Phone.TYPE_FAX_HOME;
    } else if (item.getName().equals("其他")){
     type = Phone.TYPE_OTHER;
    }
    values.clear();
    values.put(Data.RAW_CONTACT_ID, rawContactId);
    values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
    values.put(Phone.NUMBER, item.getContent());
    values.put(Phone.TYPE, type);
    EPApplication.getContextObject().getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
      values);
   }
  }
  
  //新增郵箱
  if (emaillist != null && emaillist.size()>0) {
   for (AddContactsNumberItem item : emaillist) {
    int type = 0;
    if (item.name.equals("工作")) {
     type = Email.TYPE_WORK;
    } else if (item.name.equals("家庭")) {
     type = Email.TYPE_HOME;
    } else if (item.name.equals("其他")) {
     type = Email.TYPE_OTHER;
    }
    values.clear();
    values.put(Data.RAW_CONTACT_ID, rawContactId);
    values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
    values.put(Email.DATA, item.getContent());
    values.put(Email.TYPE, type);
    EPApplication.getContextObject().getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
      values);
   }
  }
  
  // 新增備註
  if (note != null && !note.isEmpty()) {
   values.clear();
   values.put(Data.RAW_CONTACT_ID, rawContactId);
   values.put(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE);
   values.put(Note.NOTE, note);
   EPApplication.getContextObject().getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
     values);
  }
  
  // 設定頭像
  if (avatar != null) {
   values.clear();
   values.put(Data.RAW_CONTACT_ID, rawContactId);
   values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
   ByteArrayOutputStream array = new ByteArrayOutputStream();
   avatar.compress(Bitmap.CompressFormat.JPEG, 80, array);
   values.put(Photo.PHOTO, array.toByteArray());
   EPApplication.getContextObject().getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
     values);
  }
 }

小結

每個人對通訊錄的理解都有不同,這也說明通訊錄使用的靈活性。不管是通訊錄還是其他的什麼知識,我們都可以用方便自己的形式進行記錄和理解。最近一段時間看了很多書,對IOS的開發也在繼續深入中。也許正是因為開始了一門新的語言swift,所以才會讓我對“吃飯的傢伙”Android,有了更深和更客觀的認識。如果可能的話,還是多瞭解一門語言吧。確實會有很多說不出的幫助和提升。也許明年會研究一下HTML5和JS吧。明天的事誰又說的準呢!

相關文章