Android从联系人列表中获取电话号码

Posted

技术标签:

【中文标题】Android从联系人列表中获取电话号码【英文标题】:Android get phone number from contact list 【发布时间】:2017-04-13 05:03:42 【问题描述】:

我有这些代码,它们基本上使用 ListView 来显示联系人列表中的姓名,我想在单击每个姓名时获取他们的电话号码:

final ContentResolver cr = getContentResolver();

final Cursor c = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
myCursorAdapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] ContactsContract.Contacts.DISPLAY_NAME, new int[]R.id.TVRow, 0);
myPhoneList.setAdapter(myCursorAdapter);

myPhoneList.setOnItemClickListener(new AdapterView.OnItemClickListener()
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
        c.moveToPosition(position);
        Toast.makeText(getApplicationContext(), c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)), Toast.LENGTH_SHORT).show();
    
);

onItemClick方法中

    GetColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)

返回 -1,因此我无法使用此方法获取电话号码。

我还尝试打印出光标 c 的所有列,它返回 34 列,但似乎与电话号码相关的唯一列是 HasPhoneNumber

那么问题出在哪里,我该如何解决?谢谢!


更新版本,其中 String 数组传递给构造 myCursorAdapter 发生变化:

final ContentResolver cr = getContentResolver();

    final Cursor c = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    myCursorAdapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] ContactsContract.CommonDataKinds.Phone.NUMBER, new int[]R.id.TVRow, 0);
    myPhoneList.setAdapter(myCursorAdapter);

    myPhoneList.setOnItemClickListener(new AdapterView.OnItemClickListener()
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            c.moveToPosition(position);
            Toast.makeText(getApplicationContext(), c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)), Toast.LENGTH_SHORT).show();
        
    );

我想更新后的代码将在 ListView 中显示电话号码,但我收到一条错误消息“列 'data1' 不存在”。

【问题讨论】:

【参考方案1】:

首先在 androidManifest.xml 中添加这一行以获得用户的许可。

<uses-permission android:name="android.permission.READ_CONTACTS"/>

实现联系按钮

        phoneContactsButtton.setOnClickListener(new OnClickListener() 
            @Override
            public void onClick(View view) 
            // The below two line is needed to open the contact list of  mobile
                Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
                startActivityForResult(contactPickerIntent,1);

            
        );

你必须重写 onActivityResult() 它将被写入 onCreate() 方法的外部 类似这个

    @Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
   


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode)
        case 1 :
            if (resultCode == Activity.RESULT_OK) 
                Uri contactData = data.getData();

                Cursor cur =  getContentResolver().query(contactData, null, null, null, null);
                if (cur.getCount() > 0) // thats mean some resutl has been found
                    if(cur.moveToNext()) 
                        String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                        String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                        Log.e("Names", name);

                        if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
                        

                            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ id,null, null);
                            while (phones.moveToNext()) 
                                String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                                Log.e("Number", phoneNumber);
                            
                            phones.close();
                        

                    
                
                cur.close();
            
            break;
    


【讨论】:

【参考方案2】:

您可以使用以下代码在 Recyclerview 中获取联系人列表;

  List<ContactVO> contactVOList = new ArrayList();

  String[] projection = new String[]ContactsContract.Contacts._ID, ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.PHOTO_URI;
    Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null,
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
    List<ContactVO> userList = new ArrayList<>();

    String lastPhoneName = " ";
    if (phones.getCount() > 0) 
        while (phones.moveToNext()) 
            String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            String contactId = phones.getString(phones.getColumnIndex(ContactsContract.Contacts._ID));
            String photoUri = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
            if (!name.equalsIgnoreCase(lastPhoneName)) 
                lastPhoneName = name;
                ContactVO user = new ContactVO();
                user.setContactName(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
                user.setContactNumber(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
                userList.add(user);
                Log.d("getContactsList", name + "---" + phoneNumber + " -- " + contactId + " -- " + photoUri);
            
        
    
    phones.close();

    AllContactsAdapter contactAdapter = new AllContactsAdapter(userList, getApplicationContext());
    rvContacts.setLayoutManager(new LinearLayoutManager(PhoneDirectoryActivity.this));
    rvContacts.setAdapter(contactAdapter);

ContactVO类文件下面;

public class ContactVO

private String ContactImage;
private String ContactName;
private String ContactNumber;

public String getContactImage() 
    return ContactImage;


public void setContactImage(String contactImage) 
    this.ContactImage = ContactImage;


public String getContactName() 
    return ContactName;


public void setContactName(String contactName) 
    ContactName = contactName;


public String getContactNumber() 
    return ContactNumber;


public void setContactNumber(String contactNumber) 
    ContactNumber = contactNumber;


以下是AllContactsAdapter文件

    public class AllContactsAdapter extends RecyclerView.Adapter<AllContactsAdapter.ContactViewHolder> 

    private List<ContactVO> contactVOList;
    private Context mContext;
    private SparseBooleanArray itemStateArray = new SparseBooleanArray();

    public AllContactsAdapter(List<ContactVO> contactVOList, Context mContext) 
        this.contactVOList = contactVOList;
        this.mContext = mContext;
    

    @Override
    public ContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        View view = LayoutInflater.from(mContext).inflate(R.layout.single_contact_view, null);
        ContactViewHolder contactViewHolder = new ContactViewHolder(view);
        return contactViewHolder;
    

    @Override
    public void onBindViewHolder(ContactViewHolder holder, int position) 
        ContactVO contactVO = contactVOList.get(position);
        holder.tvContactName.setText(contactVO.getContactName());
        holder.tvPhoneNumber.setText(contactVO.getContactNumber());

        holder.bind(position);

        holder.cbContact.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                int adapterPosition = position;
                if (!itemStateArray.get(adapterPosition, false)) 
                    holder.cbContact.setChecked(true);
                    contactsList.add(holder.tvPhoneNumber.getText().toString());
                    itemStateArray.put(adapterPosition, true);
                 else 
                    holder.cbContact.setChecked(false);
                    itemStateArray.put(adapterPosition, false);
                    contactsList.remove(holder.tvPhoneNumber.getText().toString());
                
            
        );
    

    @Override
    public int getItemCount() 
        return contactVOList.size();
    

    public class ContactViewHolder extends RecyclerView.ViewHolder 

        ImageView ivContactImage;
        TextView tvContactName;
        TextView tvPhoneNumber;
        CheckBox cbContact;

        public ContactViewHolder(View itemView) 
            super(itemView);
            ivContactImage = itemView.findViewById(R.id.ivContactImage);
            tvContactName = itemView.findViewById(R.id.tvContactName);
            tvPhoneNumber = itemView.findViewById(R.id.tvPhoneNumber);
            cbContact = itemView.findViewById(R.id.cbContact);
        
        void bind(int arg1) 
            // use the sparse boolean array to check
            if (!itemStateArray.get(arg1, false)) 
                cbContact.setChecked(false);
             else 
                cbContact.setChecked(true);
            
        
    

【讨论】:

【参考方案3】:

ContactsContract Android API 将联系人数据(例如电话号码)存储在Data 表中,而不是Contacts 表中。

仔细阅读:https://developer.android.com/reference/android/provider/ContactsContract.html

更新 - 这是您的代码的固定版本(未经测试):

final ContentResolver cr = getContentResolver();
String[] projection = new String[] Contacts.DISPLAY_NAME, Phone.NUMBER;
final Cursor c = cr.query(Data.CONTENT_URI, projection, null, null, null);
myCursorAdapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] Phone.NUMBER, new int[]R.id.TVRow, 0);
myPhoneList.setAdapter(myCursorAdapter);

myPhoneList.setOnItemClickListener(new AdapterView.OnItemClickListener()
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
        c.moveToPosition(position);
        Toast.makeText(getApplicationContext(), c.getString(1), Toast.LENGTH_SHORT).show();
    
);

【讨论】:

【参考方案4】:

它返回 -1 因为您没有从 DB 请求列 ContactsContract.CommonDataKinds.Phone.NUMBER

new String[] ContactsContract.Contacts.DISPLAY_NAME

ContactsContract.Contacts.DISPLAY_NAME 是您请求的唯一字段。

为了能够获取电话号码,您首先需要将其包含在要从 DB 获取的列列表中:

新字符串[] ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER

现在您必须覆盖适配器的getView,以便将名称设置到列表行的 textView 中。之后,您的 onItemClick 将按预期工作

【讨论】:

我只尝试了 String[] 中的 ContactsContract.CommonDataKinds.Phone.NUMBER 并得到错误:列 'data1' 不存在。我想既然我已经在查询中包含了所有字段,那么光标应该包含关于电话号码的字段,适配器应该不是原因? @T.Yu,我不明白你改变了什么,现在有什么问题 我将 new String[] ContactsContract.Contacts.DISPLAY_NAME 更改为 new String[] ContactsContract.CommonDataKinds.Phone.NUMBER 我想它会在 ListView 中显示电话号码,但我得到了错误提示“列 'data1' 不存在”。 @T.Yu,好的,ContactsContract.CommonDataKinds.Phone.NUMBER 可能是错误的列名。让我检查一下 应该是。到目前为止,我访问过的几乎所有互联网上的相关帖子都使用了这个专栏。【参考方案5】:

此答案只是上述答案的一个小更新。它可能对某人有所帮助。

StarActivityForResult 已弃用。所以我们可以在 Kotlin 中使用下面的模型。

在清单中:

<uses-permission android:name="android.permission.READ_CONTACTS" />

请同时实现运行时权限。我的代码中还没有完成。

用于处理结果的以下行:

    private val openContacts = registerForActivityResult(ActivityResultContracts.PickContact()) 

    val contactData: Uri = it
    val phone: Cursor? = contentResolver.query(contactData!!, null, null, null, null)
    if (phone!!.moveToFirst()) 
        val contactName: String = phone.getString(phone.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))

        // To get number - runtime permission is mandatory.
        val id: String = phone.getString(phone.getColumnIndex(ContactsContract.Contacts._ID))
        if (phone.getString(phone.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)).toInt() > 0) 
            val phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null)
            while (phones!!.moveToNext()) 
                val phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                Log.d("## Number", phoneNumber)
            
            phones!!.close()
        

        Log.d("## Contact Name", contactName)
    


打开联系人:

button.setOnClickListener 
        openContacts.launch(null)
    

【讨论】:

以上是关于Android从联系人列表中获取电话号码的主要内容,如果未能解决你的问题,请参考以下文章

使用 ContentProvider 从联系人获取电话号码 - Android

如何使用 android studio 从联系人列表中选择联系人号码?

获取android联系人电话号码列表

Android - 无法获取某些联系人的电话号码

获取 Android 联系人光标异常

使用 android 2.1 在我自己的列表视图中显示姓名和联系电话