Android(Java)如何仅查询已更新姓名/手机号的联系人?
仅查询姓名或手机号更新的Android联系人方案
要实现仅获取姓名或手机号字段更新的联系人,核心思路是通过记录上次同步时间戳过滤更新数据,并利用ContentObserver的精准回调缩小查询范围,具体实现如下:
核心逻辑
- 利用
ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP字段判断联系人最后更新时间 - 通过重载ContentObserver的
onChange(boolean selfChange, Uri uri)方法,获取变动联系人的精准URI,避免全量查询 - 用SharedPreferences存储上次同步时间,过滤出时间戳晚于该值的联系人
代码实现
1. 同步时间戳的存储与读取
// 获取上次同步时间,初始值为应用启动时间 private long getLastSyncTime() { SharedPreferences sp = getSharedPreferences("ContactSync", MODE_PRIVATE); return sp.getLong("last_sync_time", System.currentTimeMillis()); } // 更新同步时间为当前时间 private void updateLastSyncTime() { SharedPreferences sp = getSharedPreferences("ContactSync", MODE_PRIVATE); sp.edit().putLong("last_sync_time", System.currentTimeMillis()).apply(); }
2. 优化ContentObserver回调
class ContactObserver extends ContentObserver { public ContactObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); contactChanged(null); // 无具体URI时执行时间过滤查询 } @Override public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); contactChanged(uri); // 传入变动URI,精准查询单个联系人 } }
3. 修改查询逻辑,实现精准过滤
public void contactChanged(Uri changedUri) { ContentResolver contentResolver = getContentResolver(); long lastSyncTime = getLastSyncTime(); String[] PROJECTION = new String[]{ ContactsContract.CommonDataKinds.Phone.CONTACT_ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP // 新增更新时间字段 }; Cursor cursor = null; try { if (changedUri != null) { // 有变动URI时,直接查询该联系人 cursor = contentResolver.query(changedUri, PROJECTION, null, null, null); } else { // 无URI时,过滤出上次同步后更新的联系人 String selection = ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " > ?"; String[] selectionArgs = new String[]{String.valueOf(lastSyncTime)}; cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, selection, selectionArgs, null); } JSONArray contactsArray = new JSONArray(); if (cursor != null && cursor.moveToFirst()) { do { String id = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)); String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); JSONObject contact = new JSONObject(); contact.put("id", id); contact.put("name", name); contact.put("number", number); contactsArray.put(contact); } while (cursor.moveToNext()); } getUpdatedContacts(contactsArray.toString(), pointer); updateLastSyncTime(); // 更新同步时间戳 } catch (JSONException e) { e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } }
4. 注册ContentObserver
getContentResolver().registerContentObserver( ContactsContract.Contacts.CONTENT_URI, true, // 监听子表变动(如手机号表) new ContactObserver(new Handler(Looper.getMainLooper())) );
额外说明
如果需要严格仅过滤姓名或手机号的变动(排除头像、备注等其他字段更新),还需在本地存储每个联系人的历史姓名和手机号,查询到更新的联系人后,对比这两个字段是否真的发生变化,再纳入结果集。
内容的提问来源于stack exchange,提问作者yeri123
相关产品推荐
相关产品推荐

