首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 讀取聯系人 Email 報 CursorIndexOutOfBoundsException:列索引錯誤與正確查詢姿勢

     編輯:程式設計綜合問答

錯誤現象


Cursor email_crsr = getContentResolver().query(
    CommonDataKinds.Email.CONTENT_URI, 
    null, 
    CommonDataKinds.Phone.CONTACT_ID + " = ?", // 錯誤:用 Phone 的 CONTACT_ID
    new String[]{id}, 
    null);
if (email_crsr != null) 
    email = phone_crsr.getString(phone_crsr.getColumnIndex(CommonDataKinds.Email.DATA)); // 多處錯誤

拋出:CursorIndexOutOfBoundsException: Index -1 requested, with a size of 4

多重錯誤分析

  1. 選擇條件列錯誤:CommonDataKinds.Phone.CONTACT_ID 用於電話表,Email 表應用 CommonDataKinds.Email.CONTACT_ID
  2. 游標變量混用:查詢返回 email_crsr,但讀取用 phone_crsr (未定義/舊變量)
  3. 未移動游標:query 返回游標在 beforeFirst 位置,必須 moveToFirst() 或 moveToNext() 才能讀取
  4. 列索引 -1:getColumnIndex 返回 -1 表示列名不存在,導致 getString(-1) 拋出異常

正確完整代碼


public ArrayList getContactEmails() {
    ArrayList emails = new ArrayList<>();
    ContentResolver cr = getContentResolver();
    
    // 1. 查詢所有聯系人 ID
    Cursor contactCursor = cr.query(
        ContactsContract.Contacts.CONTENT_URI,
        new String[]{ContactsContract.Contacts._ID},
        null, null, null);
    
    if (contactCursor != null) {
        while (contactCursor.moveToNext()) {
            String contactId = contactCursor.getString(
                contactCursor.getColumnIndex(ContactsContract.Contacts._ID));
            
            // 2. 根據聯系人 ID 查詢 Email
            Cursor emailCursor = cr.query(
                ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                new String[]{ContactsContract.CommonDataKinds.Email.DATA}, // 只取需要的列
                ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", // 正確列
                new String[]{contactId},
                null);
            
            if (emailCursor != null) {
                while (emailCursor.moveToNext()) { // 關鍵:移動游標
                    String email = emailCursor.getString(
                        emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                    if (!TextUtils.isEmpty(email)) {
                        emails.add(email);
                    }
                }
                emailCursor.close();
            }
        }
        contactCursor.close();
    }
    return emails;
}

關鍵最佳實踐

實踐代碼體現
投影列new String[]{Email.DATA} 避免全表掃描
正確選擇列Email.CONTACT_ID 而非 Phone.CONTACT_ID
游標移動while (cursor.moveToNext())
列索引檢查int idx = cursor.getColumnIndex(col); if (idx >= 0) ...
資源關閉cursor.close() 在 finally 或 try-with-resources
異步執行聯系人查詢較慢,必須在 IO 線程 (RxJava/協程/AsyncTask)

現代替代:Contacts Jetpack Library (AndroidX)


// 依賴: implementation "androidx.contacts:contacts:1.0.0-alpha1" (或更新版)
val cursor = contentResolver.query(
    Email.CONTENT_URI,
    arrayOf(Email.DATA),
    "${Email.CONTACT_ID} = ?",
    arrayOf(contactId),
    null
)
// 使用 Kotlin 擴展函數安全遍歷
cursor?.use { 
    it.mapNotNull { it.getString(it.getColumnIndex(Email.DATA)) }
       .filter { it.isNotBlank() }
       .forEach { emails.add(it) }
}

權限聲明




  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved