【问题标题】:How to get the first name and last name from Android contacts?如何从 Android 联系人中获取名字和姓氏?
【发布时间】:2011-05-17 02:37:14
【问题描述】:

如何从 Android 联系人中获取以下字段?我用的是安卓 2.2。

  1. 名称前缀
  2. 名字
  3. 中间名
  4. 姓氏
  5. 名称前缀
  6. 音名
  7. 拼音中间名
  8. 姓氏拼音

【问题讨论】:

标签: android android-contacts


【解决方案1】:

查看ContactsContract.CommonDataKinds.StructuredName 类。您可以在那里找到您正在寻找的所有列。试试这样:

    String whereName = ContactsContract.Data.MIMETYPE + " = ?";
    String[] whereNameParams = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE };
    Cursor nameCur = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
    while (nameCur.moveToNext()) {
        String given = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
        String family = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
        String display = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
    }
    nameCur.close();

它返回联系人中的所有姓名。更准确地说,您可以将联系人 ID 作为附加参数添加到查询中 - 您将获得特定联系人的地址。

【讨论】:

  • 请注意:以上查询返回您手机中的所有(我的意思是真的所有)联系人(甚至是没有指定姓名的电子邮件)。所以你应该过滤它们以获得你想要的联系人
  • 还有我的一个注意事项:MIMETYPE 确实是必需的,否则你最终得到的不是你所期望的。我忽略了这个细节,我花了一个小时来调试它。
  • 如何获取电话所有者的名字和姓氏?可行吗?
  • @KrzysztofWolny 那么我应该如何过滤结果呢?我能够检索数据,但我看到来自多个资源的这些联系人的重复项(尤其是 Google 联系人)
  • viber 和电报等应用程序更改名字
【解决方案2】:

对于指定的联系人,您可以这样做:

String whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?";
String[] whereNameParams = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, contact_ID };
Cursor nameCur = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
while (nameCur.moveToNext()) {
    String given = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
    String family = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
    String display = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
}
nameCur.close();

【讨论】:

    【解决方案3】:

    尝试使用此代码获取有关联系人的所需信息,代码在这里-

    import android.provider.ContactsContract.Contacts;
    import android.database.Cursor;
    
    // Form an array specifying which columns to return, you can add more.
    String[] projection = new String[] {
                             ContactsContract.Contacts.DISPLAY_NAME,
                             ContactsContract.CommonDataKinds.Phone
                             ContactsContract.CommonDataKinds.Email
                          };
    
    Uri contacts =  ContactsContract.Contacts.CONTENT_LOOKUP_URI;
    // id of the Contact to return.
    long id = 3;
    
    // Make the query. 
    Cursor managedCursor = managedQuery(contacts,
                         projection, // Which columns to return 
                         null,       // Which rows to return (all rows)
                                     // Selection arguments (with a given ID)
                         ContactsContract.Contacts._ID = "id", 
                                     // Put the results in ascending order by name
                         ContactsContract.Contacts.DISPLAY_NAME + " ASC");
    

    【讨论】:

    • 这种使用projection 数组仅获取所需列是最简洁的方法。如果您不需要分开的名字和姓氏,DISPLAY_NAME 也比 StructuredName URI 更简单。所以,我喜欢这个。
    • DISPLAY_NAME 将是联系人没有姓名信息时的电话号码。
    【解决方案4】:

    作为另一个示例(只是为了好玩),但用于获取单个用户的联系人姓名:

    // A contact ID is fetched from ContactList
    Uri resultUri = data.getData(); 
    Cursor cont = getContentResolver().query(resultUri, null, null, null, null);
    if (!cont.moveToNext()) {   
        Toast.makeText(this, "Cursor contains no data", Toast.LENGTH_LONG).show(); 
                    return;
    }
    int columnIndexForId = cont.getColumnIndex(ContactsContract.Contacts._ID);
    String contactId = cont.getString(columnIndexForId);
    
    // Fetch contact name with a specific ID
    String whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = " + contactId; 
    String[] whereNameParams = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE };
    Cursor nameCur = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
    while (nameCur.moveToNext()) {
        String given = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
        String family = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
        String display = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
        Toast.makeText(this, "Name: " + given + " Family: " +  family + " Displayname: "  + display, Toast.LENGTH_LONG).show();
    }
    nameCur.close();
    cont.close();
    

    【讨论】:

      【解决方案5】:
      【解决方案6】:

      2015 年底在棉花糖上使用 ContactsContract.Data.CONTENT_URI 进行实验。我无法获得GIVEN_NAME 或类似字段。我认为后来的 api 已经弃用了这些。运行以下代码打印出您手机上的列

      Uri uri = ContactsContract.Data.CONTENT_URI;
      String selection = ContactsContract.Data.MIMETYPE + " = ?";
      String[] selectionArgs = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE};
      Cursor cursor = contentResolver.query(
                  uri,       // URI representing the table/resource to be queried
                  null,      // projection - the list of columns to return.  Null means "all"
                  selection, // selection - Which rows to return (condition rows must match)
                  selectionArgs,      // selection args - can be provided separately and subbed into selection.
                  null);   // string specifying sort order
      
      if (cursor.getCount() == 0) {
        return;
      }
      Log.i("Count:", Integer.toString(cursor.getCount())); // returns number of names on phone
      
      while (cursor.moveToNext()) {
        // Behold, the firehose!
        Log.d(TAG, "-------------------new record\n");
        for(String column : cursor.getColumnNames()) {
          Log.d(TAG, column + ": " + cursor.getString(cursor.getColumnIndex(column)) + "\n");
        }
      }
      

      【讨论】:

      【解决方案7】:

      试试这个,

      public void onActivityResult(int reqCode, int resultCode, Intent data) { super.onActivityResult(reqCode, resultCode, data);
      
          try {
              if (resultCode == Activity.RESULT_OK) {
                  Uri contactData = data.getData();
                  Cursor cur = managedQuery(contactData, null, null, null, null);
                  ContentResolver contect_resolver = getContentResolver();
      
                  if (cur.moveToFirst()) {
                      String id = cur.getString(cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
                      String name = "";
                      String no = "";
      
                      Cursor phoneCur = contect_resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                              ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);
      
                      if (phoneCur.moveToFirst()) {
                          name = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                          no = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                      }
      
                      Log.e("Phone no & name :***: ", name + " : " + no);
                      txt.append(name + " : " + no + "\n");
      
                      id = null;
                      name = null;
                      no = null;
                      phoneCur = null;
                  }
                  contect_resolver = null;
                  cur = null;
                  //                      populateContacts();
              }
          } catch (IllegalArgumentException e) {
              e.printStackTrace();
              Log.e("IllegalArgumentException::", e.toString());
          } catch (Exception e) {
              e.printStackTrace();
              Log.e("Error :: ", e.toString());
          }
      }
      

      【讨论】:

        【解决方案8】:

        在这里结合各种解决方案,并看到结果中有重复记录(由于多个帐户),我决定创建一个函数,将常见帐户类型优先于其他帐户类型。在这个示例中,我也忽略了完全为空/空名称的记录(如果都是这样的话),但您可以根据需要更改此设置:

        @RequiresPermission(
            allOf = [Manifest.permission.READ_CONTACTS])
        @WorkerThread
        fun getContactIdToContactNameMap(context: Context): LongSparseArray<ContactObject> {
            val contactIdToContactObjectMap = LongSparseArray<ContactObject>()
            val contentResolver = context.contentResolver
            contentResolver.query(ContactsContract.Data.CONTENT_URI,
                arrayOf(
                    ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID,
                    ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
                    ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
                    ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME,
                    ContactsContract.RawContacts.ACCOUNT_TYPE),
                ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.Data.IN_VISIBLE_GROUP + " = ?",
                arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, "1"),
                null)?.use { cursor ->
                //            Log.d("AppLog", "got ${cursor.count} records for names")
                val colContactId = cursor.getColumnIndex(
                    ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID)
                val colFirstName = cursor.getColumnIndex(
                    ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)
                val colFamilyName = cursor.getColumnIndex(
                    ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)
                val colMiddleName = cursor.getColumnIndex(
                    ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME)
                val colAccountType =
                    cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE)
                val googleAccount = "com.google"
                //https://stackoverflow.com/a/44802016/878126
                val prioritizedAccountTypes =
                    hashSetOf("vnd.sec.contact.phone", "com.htc.android.pcsc",
                        "com.sonyericsson.localcontacts", "com.lge.sync", "com.lge.phone",
                        "vnd.tmobileus.contact.phone", "com.android.huawei.phone",
                        "Local Phone Account",
                        "")
                val contactIdToAccountTypeMap = LongSparseArray<String>()
                while (cursor.moveToNext()) {
                    val contactId = cursor.getLong(colContactId)
                    val accountType = cursor.getString(colAccountType).orEmpty()
                    val existingContact = contactIdToContactObjectMap.get(contactId)
                    if (existingContact != null) {
                        //this can occur, as we go over all of the items, including duplicate ones made by various sources
                        //                        https://stackoverflow.com/a/4599474/878126
                        val previousAccountType = contactIdToAccountTypeMap.get(contactId)
                        //google account is most prioritized, so we skip current one if previous was of it
                        if (previousAccountType == googleAccount)
                            continue
                        if (accountType != googleAccount && previousAccountType != null && prioritizedAccountTypes.contains(
                                previousAccountType))
                        //we got now a name of an account that isn't prioritized, but we already had a prioritized one, so ignore
                            continue
                    }
                    contactIdToAccountTypeMap.put(contactId, accountType)
                    val firstName = cursor.getString(colFirstName)?.trim()
                    val lastName = cursor.getString(colFamilyName)?.trim()
                    val middleName = cursor.getString(colMiddleName)?.trim()
                    if (firstName.isNullOrBlank() && lastName.isNullOrBlank() && middleName.isNullOrBlank())
                        continue
                    val contactObject = existingContact ?: ContactObject()
                    contactObject.firstName = firstName
                    contactObject.lastName = lastName
                    contactObject.middleName = middleName
                    contactIdToContactObjectMap.put(contactId, contactObject)
                }
            }
            return contactIdToContactObjectMap
        }
        
        class ContactObject {
            var firstName: String? = null
            var middleName: String? = null
            var lastName: String? = null
        }
        

        用法:

        thread {
            if (ActivityCompat.checkSelfPermission(this,
                    Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
                val contactIdToContactNameMap = getContactIdToContactNameMap(this)
                Log.d("AppLog", "found ${contactIdToContactNameMap.size()} names for contacts")
            } else Log.d("AppLog", "no contacts permission...")
        }
        

        【讨论】:

          【解决方案9】:

          检查这里有完全适用的示例代码: http://developer.android.com/guide/topics/ui/layout/listview.html

          【讨论】:

            猜你喜欢
            • 2012-10-11
            • 1970-01-01
            • 2013-06-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-10-25
            • 2013-01-20
            • 2011-09-13
            相关资源
            最近更新 更多