本文介绍如何利用 contactscontract.contacts.contact_last_updated_timestamp 字段精准筛选出最近被修改(如姓名、电话等字段变更)的联系人,避免全量遍历,提升性能与响应效率。
本文介绍如何利用 contactscontract.contacts.contact_last_updated_timestamp 字段精准筛选出最近被修改(如姓名、电话等字段变更)的联系人,避免全量遍历,提升性能与响应效率。
在 Android 联系人开发中,仅监听变更事件(如通过 ContentObserver)并不足以满足业务需求——关键在于识别哪些联系人真正发生了更新。原代码中直接查询 Phone.CONTENT_URI 会返回所有带号码的联系人记录,无法区分“新增”“修改”或“未变”,且存在重复(同一联系人可能有多个号码)。正确做法是:以联系人实体(ContactsContract.Contacts)为单位,按最后更新时间戳筛选。
ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP 是系统维护的时间戳(毫秒级 Unix 时间),每次联系人任意字段(包括姓名、号码、邮箱、头像等)被修改时自动更新。因此,只需按该字段排序并限定范围即可高效获取增量变更:
public void contactChanged() { ContentResolver resolver = getContentResolver(); String[] projection = { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP }; // 按更新时间倒序,最新修改的排在最前 String sortOrder = ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " DESC"; try (Cursor cursor = resolver.query( ContactsContract.Contacks.CONTENT_URI, projection, null, null, sortOrder)) { if (cursor == null || cursor.getCount() == 0) return; JSONArray updatedContacts = new JSONArray(); while (cursor.moveToNext()) { String id = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID)); String name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)); long lastUpdated = cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP)); // ⚠️ 关键建议:添加时间过滤(例如仅过去5分钟内更新) // long cutoff = System.currentTimeMillis() - 5 * 60 * 1000; // if (lastUpdated < cutoff) break; JSONObject contact = new JSONObject(); contact.put("id", id); contact.put("name", name); contact.put("last_updated_ms", lastUpdated); updatedContacts.put(contact); } getUpdatedContacts(updatedContacts.toString(), pointer); } catch (Exception e) { Log.e("ContactSync", "Failed to query updated contacts", e); }}
通过上述方式,你将获得真正意义上“被编辑过”的联系人列表,为同步、备份或实时 UI 更新提供精准、轻量的数据源。