Android 中的联系人选择器
Contact Picker 是 android 中的一项功能,开发人员可以使用它来要求用户选择特定的联系人。然后,开发人员可以查询与所选联系人相关的详细信息并执行所需的操作。下面给出了一个示例视频,以了解我们将在本文中做什么。请注意,我们将使用Java语言来实现这个项目。
要让用户选择一个联系人并为您的应用程序提供对所有联系人信息的访问权限,我们可以使用ACTION_PICK操作并将ContactsContract.Contacts.CONTENT_URI传递给将用于创建应用程序的 Intent。这是 Intent 的构造函数——
Intent(String action, Uri uri)
结果 Intent 被传递给您的onActivityResult(int requestCode, int resultCode, Intent data)回调包含内容:指向所选联系人的 URI。即使您的应用程序不包含READ_CONTACTS权限,响应也会授予您的应用程序使用 Contacts Provider API 读取该联系人的临时权限。我们可以使用返回的 URI 查询显示名称、电话号码、id 以及与 android 的联系人表相关的许多其他详细信息。
Notes:
- Contact phone number or email address cannot be obtained using Contacts table since contact number is not stored in this table.
- Even though the documentation states that we do not require READ_CONTACTS permission when using ACTION_PICK. There has been a bug reported by few developers who state that in few versions of android, READ_CONTACTS permission is required when using ACTION_PICK. Check issue.
示例项目
在 Android Studio 中创建一个新项目。选择手机和平板电脑,然后从模板中选择空活动。在下一个屏幕中,您将被要求提供与您的项目相关的详细信息。您可以命名应用程序并打包您想要的任何内容。在这里,我们命名了应用程序ContactPicker和包com.geekforgeeks.android.contactpicker。选择语言为Java并选择API 21的最小 SDK。点击完成。
安卓清单
我们将需要READ_CONTACTS权限。我们需要在main/AndroidManifest.xml中声明这个权限
AndroidManifest.xml
XML
XML
ContactPicker
Pick Contact
Contact Name
XML
Java
public class ContactPickerActivity extends AppCompatActivity
{
private static final int REQUEST_READ_CONTACTS_PERMISSION = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
...
}
private boolean hasContactsPermission()
{
return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) ==
PackageManager.PERMISSION_GRANTED;
}
// Request contact permission if it
// has not been granted already
private void requestContactsPermission()
{
if (!hasContactsPermission())
{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS_PERMISSION);
}
}
}
Java
public class ContactPickerActivity extends AppCompatActivity
{
...
private static final int REQUEST_CONTACT = 1;
private Button mContactPick;
private Button mContactName;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_picker);
// Intent to pick contacts
final Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
mContactPick = findViewById(R.id.contact_pick);
mContactName = findViewById(R.id.contact_name);
mContactPick.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
startActivityForResult(pickContact, REQUEST_CONTACT);
}
});
requestContactsPermission();
}
...
}
Java
public class ContactPickerActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
...
updateButton(hasContactsPermission());
}
public void updateButton(boolean enable)
{
mContactPick.setEnabled(enable);
mContactName.setEnabled(enable);
}
...
}
Java
public class ContactPickerActivity extends AppCompatActivity
{
...
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_READ_CONTACTS_PERMISSION && grantResults.length > 0)
{
updateButton(grantResults[0] == PackageManager.PERMISSION_GRANTED);
}
}
...
}
Java
public class ContactPickerActivity extends AppCompatActivity
{
...
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) return;
if (requestCode == REQUEST_CONTACT && data != null)
{
Uri contactUri = data.getData();
// Specify which fields you want
// your query to return values for
String[] queryFields = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
// Perform your query - the contactUri
// is like a "where" clause here
Cursor cursor = this.getContentResolver()
.query(contactUri, queryFields, null, null, null);
try
{
// Double-check that you
// actually got results
if (cursor.getCount() == 0) return;
// Pull out the first column of
// the first row of data
// that is your contact's name
cursor.moveToFirst();
String name = cursor.getString(0);
mContactName.setText(name);
}
finally
{
cursor.close();
}
}
}
...
}
Java
package com.geekforgeeks.android.contactpicker;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class ContactPickerActivity extends AppCompatActivity
{
private static final int REQUEST_READ_CONTACTS_PERMISSION = 0;
private static final int REQUEST_CONTACT = 1;
private Button mContactPick;
private Button mContactName;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_READ_CONTACTS_PERMISSION && grantResults.length > 0)
{
updateButton(grantResults[0] == PackageManager.PERMISSION_GRANTED);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) return;
if (requestCode == REQUEST_CONTACT && data != null)
{
Uri contactUri = data.getData();
// Specify which fields you want your
// query to return values for
String[] queryFields = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
// Perform your query - the contactUri
// is like a "where" clause here
Cursor cursor = this.getContentResolver()
.query(contactUri, queryFields, null, null, null);
try
{
// Double-check that you
// actually got results
if (cursor.getCount() == 0) return;
// Pull out the first column
// of the first row of data
// that is your contact's name
cursor.moveToFirst();
String name = cursor.getString(0);
mContactName.setText(name);
}
finally
{
cursor.close();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_picker);
// Intent to pick contacts
final Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
mContactPick = findViewById(R.id.contact_pick);
mContactName = findViewById(R.id.contact_name);
mContactPick.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
startActivityForResult(pickContact, REQUEST_CONTACT);
}
});
requestContactsPermission();
updateButton(hasContactsPermission());
}
public void updateButton(boolean enable)
{
mContactPick.setEnabled(enable);
mContactName.setEnabled(enable);
}
private boolean hasContactsPermission()
{
return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) ==
PackageManager.PERMISSION_GRANTED;
}
// Request contact permission if it
// has not been granted already
private void requestContactsPermission()
{
if (!hasContactsPermission())
{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS_PERMISSION);
}
}
}
布局
布局将包含两个按钮。第一个按钮将打开联系人应用程序,第二个按钮将显示所选联系人的姓名。以下是最终布局的图片。
字符串.xml
在创建布局之前,在res/values/ 字符串 .xml中添加以下字符串。
XML
ContactPicker
Pick Contact
Contact Name
activity_contact_picker.xml
现在从res/layout/activity_contact_picker.xml中删除所有内容并添加它。
XML
活动
我们首先需要请求READ_CONTACTS权限。在Java/com/geekforgeeks/android/contactpicker/ContactPickerActivity中添加方法hasContactsPermission()和requestContactsPermission() 。Java有关如何请求许可的更多详细信息,请访问此处。
Java
public class ContactPickerActivity extends AppCompatActivity
{
private static final int REQUEST_READ_CONTACTS_PERMISSION = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
...
}
private boolean hasContactsPermission()
{
return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) ==
PackageManager.PERMISSION_GRANTED;
}
// Request contact permission if it
// has not been granted already
private void requestContactsPermission()
{
if (!hasContactsPermission())
{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS_PERMISSION);
}
}
}
在onCreate(Bundle savedInstanceState)方法中,我们需要做 4 件事:
- 通过 id 检索两个按钮。
- 创建 Intent 以打开联系人应用程序。
- 将侦听器添加到启动联系人应用程序的mPickContact按钮。
- 调用requestContactsPermission()方法。
Java
public class ContactPickerActivity extends AppCompatActivity
{
...
private static final int REQUEST_CONTACT = 1;
private Button mContactPick;
private Button mContactName;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_picker);
// Intent to pick contacts
final Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
mContactPick = findViewById(R.id.contact_pick);
mContactName = findViewById(R.id.contact_name);
mContactPick.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
startActivityForResult(pickContact, REQUEST_CONTACT);
}
});
requestContactsPermission();
}
...
}
添加另一个方法updateButton(boolean enable) ,这将根据应用程序是否具有读取联系人权限来启用或禁用这两个按钮。这将防止应用程序中的任何崩溃。
Java
public class ContactPickerActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
...
updateButton(hasContactsPermission());
}
public void updateButton(boolean enable)
{
mContactPick.setEnabled(enable);
mContactName.setEnabled(enable);
}
...
}
覆盖onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)当我们的用户接受或拒绝应用程序读取联系人的权限时,android 将自动调用它。这样做是必要的,因为根据结果,我们需要启用和禁用这两个按钮。
Java
public class ContactPickerActivity extends AppCompatActivity
{
...
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_READ_CONTACTS_PERMISSION && grantResults.length > 0)
{
updateButton(grantResults[0] == PackageManager.PERMISSION_GRANTED);
}
}
...
}
对于最后一步,覆盖onActivityResult(int requestCode, int resultCode, Intent data)将由 android 自动调用。我们检查是否为我们传递给意图的REQUEST_CONTACT常量调用了该方法。我们还检查返回的数据是否不为空。我们检索数据并查询我们想要检索的字段。结果以游标的形式获得。我们从光标中提取所需的数据并退出。
Java
public class ContactPickerActivity extends AppCompatActivity
{
...
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) return;
if (requestCode == REQUEST_CONTACT && data != null)
{
Uri contactUri = data.getData();
// Specify which fields you want
// your query to return values for
String[] queryFields = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
// Perform your query - the contactUri
// is like a "where" clause here
Cursor cursor = this.getContentResolver()
.query(contactUri, queryFields, null, null, null);
try
{
// Double-check that you
// actually got results
if (cursor.getCount() == 0) return;
// Pull out the first column of
// the first row of data
// that is your contact's name
cursor.moveToFirst();
String name = cursor.getString(0);
mContactName.setText(name);
}
finally
{
cursor.close();
}
}
}
...
}
ContactPickerActivity
这是完整的ContactPickerActivity。Java
Java
package com.geekforgeeks.android.contactpicker;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class ContactPickerActivity extends AppCompatActivity
{
private static final int REQUEST_READ_CONTACTS_PERMISSION = 0;
private static final int REQUEST_CONTACT = 1;
private Button mContactPick;
private Button mContactName;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_READ_CONTACTS_PERMISSION && grantResults.length > 0)
{
updateButton(grantResults[0] == PackageManager.PERMISSION_GRANTED);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) return;
if (requestCode == REQUEST_CONTACT && data != null)
{
Uri contactUri = data.getData();
// Specify which fields you want your
// query to return values for
String[] queryFields = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
// Perform your query - the contactUri
// is like a "where" clause here
Cursor cursor = this.getContentResolver()
.query(contactUri, queryFields, null, null, null);
try
{
// Double-check that you
// actually got results
if (cursor.getCount() == 0) return;
// Pull out the first column
// of the first row of data
// that is your contact's name
cursor.moveToFirst();
String name = cursor.getString(0);
mContactName.setText(name);
}
finally
{
cursor.close();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_picker);
// Intent to pick contacts
final Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
mContactPick = findViewById(R.id.contact_pick);
mContactName = findViewById(R.id.contact_name);
mContactPick.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
startActivityForResult(pickContact, REQUEST_CONTACT);
}
});
requestContactsPermission();
updateButton(hasContactsPermission());
}
public void updateButton(boolean enable)
{
mContactPick.setEnabled(enable);
mContactName.setEnabled(enable);
}
private boolean hasContactsPermission()
{
return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) ==
PackageManager.PERMISSION_GRANTED;
}
// Request contact permission if it
// has not been granted already
private void requestContactsPermission()
{
if (!hasContactsPermission())
{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS_PERMISSION);
}
}
}
输出: