如何调用Android联系人列表?

133

我正在制作一个Android应用程序,需要调用手机的联系人列表。我需要调用联系人列表函数,选择一个联系人,然后返回我的应用程序并显示选定的联系人的名称。这里是我从互联网上找到的代码,但它不起作用。

import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.Contacts.People;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

public class Contacts extends ListActivity {

    private ListAdapter mAdapter;
    public TextView pbContact;
    public static String PBCONTACT;
    public static final int ACTIVITY_EDIT=1;
    private static final int ACTIVITY_CREATE=0;

    // Called when the activity is first created. 
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        Cursor C = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
        startManagingCursor(C);

        String[] columns = new String[] {People.NAME};
        int[] names = new int[] {R.id.row_entry};

        mAdapter = new SimpleCursorAdapter(this, R.layout.mycontacts, C, columns, names);
        setListAdapter(mAdapter);
    } // end onCreate()
    // Called when contact is pressed
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        Cursor C = (Cursor) mAdapter.getItem(position);
        PBCONTACT = C.getString(C.getColumnIndex(People.NAME));

        // RHS 05/06
        //pbContact = (TextView) findViewById(R.id.myContact);
        //pbContact.setText(new StringBuilder().append("b"));

        Intent i = new Intent(this, NoteEdit.class);
        startActivityForResult(i, ACTIVITY_CREATE);
    }
}

你能修复代码部分,包括代码的第一部分吗: import android.app.ListActivity... - David Glass
1.6和2.2的例子:http://www.coderanch.com/t/512048/Android/Mobile/Contact-API - Blundell
尝试使用 android contact extractor。这是一个小巧简单易用的库。 - Nitesh Tiwari
13个回答

251

我不完全确定你的示例代码的用途,但以下片段应该可以帮助你“调用联系人列表功能,选择一个联系人,然后返回到您的应用程序并显示联系人姓名”。

这个过程有三个步骤。

1. 权限

在您的应用程序清单中添加读取联系人数据的权限。

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

2. 调用联系人选择器

在您的Activity中,创建一个意图(Intent),请求系统从联系人URI中的项目中查找可以执行"Pick"动作的Activity。

Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);

调用startActivityForResult,传入此意图(以及请求代码整数,在此示例中为PICK_CONTACT)。这将导致Android启动一个已注册支持ACTION_PICK的活动,并在选择完成(或取消)后返回到此活动。

startActivityForResult(intent, PICK_CONTACT);

3. 监听结果

在你的Activity中,覆盖onActivityResult方法以便监听步骤2中启动的“选择联系人”活动的返回结果。你应该检查返回的请求码是否与你期望的值相匹配,并且结果码为RESULT_OK

你可以通过调用getData()方法来获取所选联系人的URI,该方法需要使用Intent参数。要获取所选联系人的姓名,您需要使用该URI创建一个新的查询并从返回的游标中提取名称。

@Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
  super.onActivityResult(reqCode, resultCode, data);

  switch (reqCode) {
    case (PICK_CONTACT) :
      if (resultCode == Activity.RESULT_OK) {
        Uri contactData = data.getData();
        Cursor c =  getContentResolver().query(contactData, null, null, null, null);
        if (c.moveToFirst()) {
          String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
          // TODO Whatever you want to do with the selected contact name.
        }
      }
      break;
  }
}

完整源代码: tutorials-android.blogspot.com(如何调用Android联系人列表).


41
看起来最近的Android API已经弃用了很多这个代码。有人有更新版吗? - yamspog
6
这里没有问题……您不需要READ联系人权限,因为用户在这里有控制权。应用程序本身不会内部读取联系人,而是弹出联系人列表。只有当用户选择联系人(手动操作)时,应用程序才能检索与该联系人信息相关联的一组有限数据。 - ddewaele
1
我能够在我的4.0+安卓手机上让用户选择联系人而不需要READ权限,但在1.6上无法做到。有人知道这个功能是在哪个版本中实现的吗? - amit
@RetoMeier onActivityResult会立即被调用,而我还没有选择联系人。http://stackoverflow.com/questions/32644502/why-is-onactivityresult-is-called-before-a-contact-is-chosen 我做错了什么? - fadedbee
1
PICK_CONTACT 对我来说无法正常工作。你是如何初始化它的? - user3104760
显示剩余6条评论

67

我为Android 2.2 Froyo版本这样做:

基本上使用eclipse创建一个类,例如:

public class SomePickContactName extends Activity

然后插入以下代码。记得添加我版本代码中引用的私有类变量和常量:

protected void onCreate(Bundle savedInstanceState) 
{
  super.onCreate(savedInstanceState);       
  Intent intentContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); 
  startActivityForResult(intentContact, PICK_CONTACT);
}//onCreate

public void onActivityResult(int requestCode, int resultCode, Intent intent) 
{

  if (requestCode == PICK_CONTACT)
  {         
    getContactInfo(intent);         
    // Your class variables now have the data, so do something with it. 
  }
}//onActivityResult

protected void getContactInfo(Intent intent)
{

   Cursor cursor =  managedQuery(intent.getData(), null, null, null, null);      
   while (cursor.moveToNext()) 
   {           
       String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
       name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)); 

       String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));

       if ( hasPhone.equalsIgnoreCase("1"))
           hasPhone = "true";
       else
           hasPhone = "false" ;

       if (Boolean.parseBoolean(hasPhone)) 
       {
        Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId,null, null);
        while (phones.moveToNext()) 
        {
          phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        }
        phones.close();
       }

       // Find Email Addresses
       Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,null,ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId,null, null);
       while (emails.moveToNext()) 
       {
        emailAddress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
       }
       emails.close();

    Cursor address = getContentResolver().query(
                ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI,
                null,
                ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + " = " + contactId,
                null, null);
    while (address.moveToNext()) 
    { 
      // These are all private class variables, don't forget to create them.
      poBox      = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
      street     = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
      city       = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
      state      = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
      postalCode = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
      country    = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
      type       = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE));
    }  //address.moveToNext()   
  }  //while (cursor.moveToNext())        
   cursor.close();
}//getContactInfo

应用程序在尝试第二次获取电子邮件时崩溃。编辑:如果其他人遇到相同的错误,请删除“cursor.close();”https://dev59.com/Umkw5IYBdhLWcg3ws873 - alicanbatur

14

在查找使用ContactsContract API的API Level 5解决方案时,您可以通过以下方式稍微修改上面的代码:

  Intent intent = new Intent(Intent.ACTION_PICK);
  intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
  startActivityForResult(intent, PICK_CONTACT);

然后在onActivityResult中使用列名:

  ContactsContract.Contacts.DISPLAY_NAME

1
显示联系电话号码需要什么? - Usman Masood
在Android 1.6中没有这样的类。我在Contacts.ContactMethods中找到了类似的名称,但是我只得到了异常(找不到这样的活动)。但是Reto的代码很好用。 - davs

8

以下是获取联系人的代码片段:

package com.contact;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class GetContactDemoActivity extends Activity implements OnClickListener {

private Button btn = null;
private TextView txt = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    btn = (Button) findViewById(R.id.button1);
    txt = (TextView) findViewById(R.id.textView1);

    btn.setOnClickListener(this);
}

@Override
public void onClick(View arg0) {
    if (arg0 == btn) {
        try {
            Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
            startActivityForResult(intent, 1);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Error in intent : ", e.toString());
        }
    }
}

@Override
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());
    }
}

}


6
        Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
        while (phones.moveToNext())
        {
        String Name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
        String Number=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        }

5
完整的代码如下:
    package com.testingContect;

    import android.app.Activity;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.ContactsContract;
    import android.provider.Contacts.People;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;

    public class testingContect extends Activity implements OnClickListener{
    /** Called when the activity is first created. */

    EditText ed;
    Button bt;
    int PICK_CONTACT;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        bt=(Button)findViewById(R.id.button1);
        ed =(EditText)findViewById(R.id.editText1);
        ed.setOnClickListener(this);
        bt.setOnClickListener(this);


    }

    @Override
    public void onClick(View v) {

        switch(v.getId())
        {
        case R.id.button1:

            break;
        case R.id.editText1:
             Intent intent = new Intent(Intent.ACTION_PICK);
              intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
              startActivityForResult(intent, PICK_CONTACT);


            break;

        }

    }
    public void onActivityResult(int requestCode, int resultCode, Intent intent) 
    {

      if (requestCode == PICK_CONTACT)
      {         
          Cursor cursor =  managedQuery(intent.getData(), null, null, null, null);
          cursor.moveToNext();
          String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
           String  name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)); 

          Toast.makeText(this, "Contect LIST  =  "+name, Toast.LENGTH_LONG).show(); 
      }
    }//onActivityResult
}//class ends

1
PICK_CONTACT 在哪里初始化? - Edward Falk
1
它应该在活动类的顶部声明:private static final int PICK_CONTACT = 1; - Omar

5
public void onActivityResult(int requestCode, int resultCode, Intent intent) 
{
  if (requestCode == PICK_CONTACT && intent != null) //here check whether intent is null R not
  {  
  }
}

因为如果不选择任何联系人,程序会出现异常。所以最好检查这个条件。


3

在使用Android联系人列表时要小心。

以上方法中读取联系人列表适用于大多数Android设备,但HTC One和Sony Xperia除外。我曾经浪费了六周的时间来弄清楚问题出在哪里!

在线上有很多类似的教程 - 首先读取“全部”联系人,然后使用ArrayAdapterListview中显示。这不是一个高效的解决方案。与其首先寻找其他网站上的解决方案,不如先看看developer.android.com。如果developer.android.com上没有任何解决方案,那么你应该去别的地方寻找。

解决方案是使用CursorAdapter而不是ArrayAdapter来检索联系人列表。虽然使用ArrayAdapter可以在大多数设备上正常工作,但它并不高效。当ListView被滚动时,CursorAdapter只会在运行时检索到联系人列表的一部分。

public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ...
    // Gets the ListView from the View list of the parent activity
    mContactsList =
        (ListView) getActivity().findViewById(R.layout.contact_list_view);
    // Gets a CursorAdapter
    mCursorAdapter = new SimpleCursorAdapter(
            getActivity(),
            R.layout.contact_list_item,
            null,
            FROM_COLUMNS, TO_IDS,
            0);
    // Sets the adapter for the ListView
    mContactsList.setAdapter(mCursorAdapter);
}

获取联系人列表:获取联系人列表


3
令我惊讶的是,您并不需要用户权限CONTACT_READ来读取姓名和一些基本信息(联系人是否加星标,最后通话时间等)。但是,您需要权限才能读取联系人的详细信息,例如电话号码。

1

我有一段代码,可以通过共享偏好设置将联系人保存到您的数据库中,以下是我的代码:

public class MainActivity extends AppCompatActivity {
    EditText nameInput,phoneInput;
    TextView LargeText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main22);
        nameInput = (EditText) findViewById(R.id.nameInput);
        phoneInput = (EditText) findViewById(R.id.phoneInput);

        LargeText = (TextView) findViewById(R.id.textView2);
    }

    public void saveInfo (View view){
        SharedPreferences sharedPref = getSharedPreferences("nameInfo" , Context.MODE_PRIVATE);
        SharedPreferences.Editor editor= sharedPref.edit();
        editor.putString("name", nameInput.getText().toString());
        editor.putString("phone", phoneInput.getText().toString());
        editor.apply();
        Toast.makeText(this, "Saved", Toast.LENGTH_LONG).show();
    }

    public void displayData(View view){
        SharedPreferences sharedPref = getSharedPreferences("nameInfo" , Context.MODE_PRIVATE);
        String name = sharedPref.getString("name", "");
        String ph = sharedPref.getString ("phone","");
        LargeText.setText(name + " " + ph);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接