检索Android OS上的联系人

时间:2014-04-02 20:48:55

标签: android contacts

我尝试使用此代码段来检索一个接一个的联系人。 信息:我已设置权限<uses-permission android:name="android.permission.READ_CONTACTS"/>

    Context context = getActivity();
    Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, new String[]{Phone.NUMBER}, null, null, null);

    while (cursor.moveToNext()) {
        String number = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
        Log.i("Number: ", number);
    }
    cursor.close();

这就是我的StackTrace发布的内容,我真的不明白它的内容:

Pick [Android Application]  
<terminated>Pick [Android Application]  
<disconnected>DalvikVM [localhost:8600] 
Pick [Android Application]  
DalvikVM [localhost:8600]   
    Thread [<1> main] (Suspended (exception IllegalArgumentException))  
        <VM does not provide monitor information>   
        ContextImpl$ApplicationContentResolver(ContentResolver).query(Uri, String[], String, String[], String, CancellationSignal) line: 458    
        ContextImpl$ApplicationContentResolver(ContentResolver).query(Uri, String[], String, String[], String) line: 360    
        FragmentContacts.onCreateView(LayoutInflater, ViewGroup, Bundle) line: 21   
        FragmentContacts(Fragment).performCreateView(LayoutInflater, ViewGroup, Bundle) line: 1500  
        FragmentManagerImpl.moveToState(Fragment, int, int, int, boolean) line: 927 
        FragmentManagerImpl.moveToState(int, int, int, boolean) line: 1104  
        BackStackRecord.run() line: 682 
        FragmentManagerImpl.execPendingActions() line: 1467 
        FragmentManagerImpl$1.run() line: 440   
        Handler.handleCallback(Message) line: 730   
        FragmentActivity$1(Handler).dispatchMessage(Message) line: 92   
        Looper.loop() line: 137 
        ActivityThread.main(String[]) line: 5419    
        Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]  
        Method.invoke(Object, Object...) line: 525  
        ZygoteInit$MethodAndArgsCaller.run() line: 1187 
        ZygoteInit.main(String[]) line: 1003    
        NativeStart.main(String[]) line: not available [native method]  
    Thread [<10> Binder_2] (Running)    
    Thread [<9> Binder_1] (Running) 
    Daemon Thread [<11> RefQueueWorker@org.apache.http.impl.conn.tsccm.ConnPoolByRoute@42a6b128] (Running)  
    Thread [<14> pool-3-thread-1] (Running) 
    Thread [<15> ParseCommandCache.runLoop()] (Running) 

1 个答案:

答案 0 :(得分:2)

这是因为您正在尝试获取查询时未请求的列数据。将您的查询行更改为:

Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, new String[]{Phone.NUMBER}, null, null, null);

对于要从中读取数据的每一列,请确保您还将其包含在投影数组中。 query()方法的第二个参数是一个String数组,其中包含您感兴趣的列。

更好的方法是:

// columns we're interested in reading data from
String[] projection = {Phone.NUMBER, OTHER_COLUMNS};

Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null);

阅读本教程以获取更多信息:http://developer.android.com/training/load-data-background/index.html

更新:您无法直接从联系人表格中获取电话号码。它们存储在不同的表中,因为联系人可以有多个号码。

为此,我们必须使用嵌套的游标查询。以下是它的工作方式:

  1. ContactsContract.Contacts._ID添加到投影数组中。此ID字段包含每个联系人的联系人ID。

  2. 迭代光标和每个联系人ID,获取他的号码。

  3. 以下是详细解决方案:

        // uri for the contacts data
        Uri contactsUri = ContactsContract.Contacts.CONTENT_URI;
    
        // columns we're interested in
        String[] projection = new String[] {
                ContactsContract.Contacts._ID,
                ContactsContract.Contacts.DISPLAY_NAME,
        };
    
        // we do not want contacts who do not have phone numbers
        // so we'll only query contacts whose phone numbers count is > 0
        String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " >? ";
        String[] selectionArgs = new String[] {"0"};
    
        // query all contacts
        Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, projection, selection, selectionArgs, null);
    
        // this list will hold lists of phone numbers of all contacts
        ArrayList<ArrayList<String>> allContactNumbers = new ArrayList<ArrayList<String>>();
    
        if(cursor != null){
            try{
    
                // for each contact Id, we'll fetch his numbers
                while(cursor.moveToNext()){
    
                      // get his contactId
                      String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
    
                      // ArrayList that will hold his phone numbers
                      ArrayList<String> phoneNumbers = new ArrayList<String>();
    
                      Cursor numberCursor = contResv.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{ contactId }, null);
    
                      try{
    
                              // add each phone number to phoneNumbers
                              while (numberCursor.moveToNext()){
                                     String contactNumber = numberCursor.getString(numberCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                                     phoneNumbers.add(contactNumber);
                              }
    
                      }finally{
                              numberCursor.close();
                      }  
    
                      // and add each contact's phone numbers to our master list
                      allContactNumbers.add(phoneNumbers);
    
            }finally{
    
             // close the cursor when we're done using it to avoid any database leaks
             cursor.close();
            }
        }
    
        // now do whatever you want with allContactNumbers.