当且仅当 ContactsContract.Contacts.CONTENT_URI 更改时,ContentObserver 才应调用

问题描述 投票:0回答:3

因为我的应用程序使用来自

android.provider.ContactsContract.Data
(API > 11)和
ContactsContract.Contacts.CONTENT_URI
(API < 11) to populate
Contacts

)的内容

我已尝试

registerContentObserver()
反对这些提供商。但即使我一拨打电话就尝试从设备上呼叫某人,它也会呼叫我的
ContentObserver
。它确实触发了我的
ContentObserver
,这对我来说没有用,因为
Contacts Provider
中没有内容更改。

根本原因:

当从由

LAST_TIME_CONTACTED
合法唤醒的设备发出呼叫时,
ContactsContract.Contacts.CONTENT_URI
ContentObserver
中的某些内容似乎会发生变化。

尝试过:

private class ContactsContentObserver extends ContentObserver {
    public ContactsContentObserver() {
        super(null);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Zname.getPreferences().setRefreshContact(true);
    }
}

已在

ContentObserver
OnCreate()
 中注册 
Activity

ContactsContentObserver contactsContentObserver = new ContactsContentObserver();
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, false, contactsContentObserver);

尝试将

notifyForDescendents
用作
false
上的
registerContentObserver
。还是会触发
ContentObserver

问题:

如何注册

ContentObserver
并触发当且仅当联系人信息处于CRUD(创建、更新、删除)状态(除了
Last_Time_Contacted
或其后代之外)?

android android-contentprovider contentobserver
3个回答
5
投票

这里的根本问题是注册

ContactsContract.Contacts.CONTENT_URI
并不像您合理想象的那样有效。

即使

notifyForDescendents
false
,您也会收到更新的原因是,触发更新的
Uri
是...
ContactsContract.Contacts.CONTENT_URI
而不是正在拨打的联系人行。

联系人应用程序中的违规代码可以在

GrepCode 中找到,并且在 Google Code 上为此提交了一个错误。

因此,要回答您的问题,

您无法注册将触发联系人上特定字段的ContentObserver

您的应用程序中需要有一些东西,以便在onChange
触发时跟踪计算差异.


0
投票
由于

android.provider.ContactsContract

 内容提供商有其自身的复杂性,这使得 
ContentObserver
 很难仅通知 
contacts
 内容更改,除非它是 
LAST_TIME_CONTACTED
 字段,因为每个遇到的人都这么说,所以事实如此。 

需要开发自己的逻辑,当

contacts

通知时,
ContentObserver
数据是否更新。

无论

contacts

是否真的更新,都要考虑构建逻辑。

    根据上次检查的情况进行检查。取决于要求。
  • ContentObserver
     中添加 
    Service
    ,即 
    STICKY
    ,这样当联系人发生变化时它就可以在那里。

同步电话簿逻辑:-由于我使用 SQLite 维护联系人,因此检查其是否存在并构建逻辑。

ContentValues values; Cursor cursor = Zname.getApplication().getContentResolver().query(DBConstant.All_Contacts_Columns.CONTENT_URI,null,DBConstant.All_Contacts_Columns.COLUMN_CONTACT_NUMBER+ "=?",new String[] { _contact.getContactNumber() },null); if (cursor.getCount() <= 0) { cursor.moveToFirst(); Zname.getApplication().getContentResolver().delete(DBConstant.All_Contacts_Columns.CONTENT_URI,DBConstant.All_Contacts_Columns.COLUMN_CONTACT_NUMBER+ "?=",new String[] { _contact.getContactNumber() }); Log.i(TAG, "Updating zname phonebook"); values = new ContentValues(); values.put(DBConstant.All_Contacts_Columns.COLUMN_CONTACT_ID,_contact.getContactId()); values.put(DBConstant.All_Contacts_Columns.COLUMN_CONTACT_NUMBER,_contact.getContactNumber()); values.put(DBConstant.All_Contacts_Columns.COLUMN_DISPLAY_NAME,_contact.getContactName()); values.put(DBConstant.All_Contacts_Columns.COLUMN_ZNAME_DP_URL_SMALL,_contact.getContactPhotoUri().toString()); Zname.getApplication().getContentResolver().insert(DBConstant.All_Contacts_Columns.CONTENT_URI,values); if (cursor != null) cursor.close(); }
    

0
投票
关于 LAST_TIME_CONTACTED 正如您所提到的,它已被弃用,并且将始终从 API 29 返回 0,因此您不应该使用它...

https://developer.android.com/reference/android/provider/ContactsContract.ContactOptionsColumns#LAST_TIME_CONTACTED

如果您想监控整个地址簿甚至一个联系人,您确实可以使用:

applicationContext.contentResolver.registerContentObserver(ContactsContract.Contacts.CONTENT_URI, false, observer)
然后你查询整个通讯录:

applicationContext.contentResolver.query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null )?.use { cursor -> while (cursor.moveToNext()) { Log.d("AppLog", "" + DatabaseUtils.dumpCurrentRowToString(cursor)) } }
您可以将其更改为专注于您想要监控的特定联系人。

您可以使用每个联系人的 CONTACT_LAST_UPDATED_TIMESTAMP 查看是否有任何更改。然后,您还可以为自己保存所有您希望在检查中排除和包含的内容。这非常适合您自己的需求。

您可能需要使用一些去抖动技术,特别是当您监视整个地址簿时。操作方法如下:

Kotlin Android 反跳

© www.soinside.com 2019 - 2024. All rights reserved.