Android 从联系人列表中获取 phone 号码
Android get phone number from contact list
我有这些代码,它们基本上使用 ListView 来显示联系人列表中的姓名,我想在单击每个姓名时获取他们的 phone 号码:
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)
returns -1 因此我无法用这种方法得到 phone 号码。
我还尝试打印出光标 c
的所有列,它 returns 34 列,但似乎与 phone 数字相关的唯一一列是 HasPhoneNumber
.
问题出在哪里,我该如何解决?谢谢!
更新版本,其中传递给构造 myCursorAdapter
的 String
数组已更改:
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 中显示 phone 个数字,但我收到一个错误提示 "column 'data1' does not exist"。
它 returns -1 因为您没有从数据库请求列 ContactsContract.CommonDataKinds.Phone.NUMBER
:
new String[] {ContactsContract.Contacts.DISPLAY_NAME}
ContactsContract.Contacts.DISPLAY_NAME
是您请求的唯一字段。
为了能够获得 phone 数字,您首先需要将其包含到要从数据库中获取的列列表中:
新字符串[] {ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}
现在您必须覆盖适配器的 getView
,以便它将名称设置到列表行的 textView 中。之后您的 onItemClick
将按预期工作
ContactsContract
Android API 存储联系人的数据,例如 phone 号码在 Data
table 中,而不是 Contacts
table.
仔细阅读: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();
}
});
首先在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;
}
}
您可以使用以下代码在 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
class 文件下方;
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);
}
}
}
}
这个答案只是对上述答案的一个小更新。它可能对某人有帮助。
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)
}
我有这些代码,它们基本上使用 ListView 来显示联系人列表中的姓名,我想在单击每个姓名时获取他们的 phone 号码:
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)
returns -1 因此我无法用这种方法得到 phone 号码。
我还尝试打印出光标 c
的所有列,它 returns 34 列,但似乎与 phone 数字相关的唯一一列是 HasPhoneNumber
.
问题出在哪里,我该如何解决?谢谢!
更新版本,其中传递给构造 myCursorAdapter
的 String
数组已更改:
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 中显示 phone 个数字,但我收到一个错误提示 "column 'data1' does not exist"。
它 returns -1 因为您没有从数据库请求列 ContactsContract.CommonDataKinds.Phone.NUMBER
:
new String[] {ContactsContract.Contacts.DISPLAY_NAME}
ContactsContract.Contacts.DISPLAY_NAME
是您请求的唯一字段。
为了能够获得 phone 数字,您首先需要将其包含到要从数据库中获取的列列表中:
新字符串[] {ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}
现在您必须覆盖适配器的 getView
,以便它将名称设置到列表行的 textView 中。之后您的 onItemClick
将按预期工作
ContactsContract
Android API 存储联系人的数据,例如 phone 号码在 Data
table 中,而不是 Contacts
table.
仔细阅读: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();
}
});
首先在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;
}
}
您可以使用以下代码在 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
class 文件下方;
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);
}
}
}
}
这个答案只是对上述答案的一个小更新。它可能对某人有帮助。
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)
}