【问题标题】:How do I make my Android ContentObserver for ContactsContract detect a added, updated or deleted contact?如何让我的 Android ContentObserver for ContactsContract 检测到添加、更新或删除的联系人?
【发布时间】:2011-08-25 05:05:05
【问题描述】:

我能够收到“联系人数据库发生更改”的一般通知,但我想知道插入、更新或删除的特定记录。以下是注册并获取 onChange 通知的代码。不幸的是,这不是具体的,这使我的处理详尽且效率低下。

这里是代码存根:

            if ((mNativeContactsObserver == null) && (mHandler == null)) {
            mHandler = new Handler(this.getMainLooper()) {
            };
            mNativeContactsObserver = new ContentObserver(mHandler) {
                @Override
                public void onChange(boolean selfChange) {
                    super.onChange(selfChange);

                    Bundle data = null;
                    Message message = mHandler.obtainMessage();
                    if (message != null) {
                        data = message.getData();
                        if (data != null) {
                            Logs.d(TAG, "Message = [" + message.toString() + "] data=[" + data.toString() + "]");
                            Logs.d(TAG, "Contents = [" + message.describeContents() + "]");
                        }
                    }

                    if (!selfChange) {
                        final Account accountListen = MySyncAdapter.lookupAccount(TAG, getApplicationContext(), getUserProfile().getAccountId(), AUTHORITY_MY_SYNC);
                        Logs.d(TAG, "onChange!? account: " + accountListen.name);
                        if (!ContentResolver.isSyncPending(account, ContactsContract.AUTHORITY) 
                                && (!ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY))) {
                            Bundle extras = new Bundle();
                            extras.putInt(MySyncAdapter.EXTRA_SYNC_TYPE, MySyncAdapter.REQUEST_SYNC_NATIVE_CHANGED);
                            ContentResolver.requestSync(accountListen, ContactsContract.AUTHORITY, extras);
                        } else {
                            Logs.w(TAG, "There is a pending sync.  This request is ignored.");
                        }
                    }
                }
            };
        }
        Uri uriContactsListen = ContactsContract.Contacts.CONTENT_URI.buildUpon().appendEncodedPath("#").build();
        Logs.i(TAG, "Register listening for native contacts changes. [" + uriContactsListen + "]");
        cr.registerContentObserver(uriContactsListen, true, mNativeContactsObserver);

【问题讨论】:

  • 您是否了解如何检测 ContactsContract 添加或删除或何时显式更新?即使我希望仅在删除记录时通知我的 ContentObserver。不是每次
  • 很遗憾没有,但是自从 Eclair 之后我就没有再追求了。
  • 嗨,你有解决办法吗?我希望在我的项目中获得相同的结果。
  • @BhoomiZalavadiya 不幸的是,没有。我只是把如果关闭作为一个限制,然后再也不回头了。

标签: android crud contactscontract contentobserver


【解决方案1】:

最后至少我能够检测到这个更新/删除/插入看看我的OnChange方法如下

 @Override
       public void onChange(boolean selfChange) {
           super.onChange(selfChange);
           Log.e("ContactChangeObserver", "onChange");

           // 0 Update , 1 Delete , 2 Added
 // Get count from phone contacts
           final int currentCount = contactDBOperaion.getContactsCountFromPhone();

 // Get count from your sqlite database
           int mContactCount= DbContacts.getInstance().getContactsCount();

           if (currentCount < mContactCount) {
               // DELETE HAPPEN.
               Log.e("Status", "Deletion");
               contactDBOperaion.SyncContacts(1);
           } else if (currentCount == mContactCount) {
               // UPDATE HAPPEN.
               contactDBOperaion.SyncContacts(0);
           } else {
               // INSERT HAPPEN.
               Log.e("Status", "Insertion");
               contactDBOperaion.SyncContacts(2);
           }
       }

当发生更新时,我会更新所有联系人

Insert 发生时,我正在插入新添加的行,检查后 isExist 在现有数据库中

删除发生时还没有找到解决办法

【讨论】:

    【解决方案2】:

    我的应用程序基类中有这段代码。

    private ContentObserver contactObserver = new ContactObserver();
    
    private class ContactObserver extends ContentObserver {
    
        public ContactObserver() {
            super(null);
        }
    
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
    
            // Since onChange do not sent which user have been changed, you 
            // have to figure out how to match it with your data.
            // Note: Contact is  one of my classes.
            for (Contact contact : getContacts()) {
                if (!contact.isLinked())
                    continue;
    
                String selection = ContactsContract.Data._ID + " = ?";
                String[] selectionArgs = new String[] { contact.getSystemId() };
                String[] projection = new String[] { ContactsContract.Data.DISPLAY_NAME };
                Cursor cursor = getContentResolver().query(
                        ContactsContract.Contacts.CONTENT_URI, projection,
                        selection, selectionArgs, null);
    
                if (!cursor.moveToFirst())
                    return;
    
                String name = cursor.getString(0);
    
                if (contact.getUsername().equalsIgnoreCase(name))
                    continue;
    
                contact.setUserName(name);
    
            }
        }
    }
    

    关于你可以在投影检查中添加什么here

    Unfortunately, it is not specific which makes my processing exhaustive and inefficient.
    

    如果在下一个 Android 版本中也能发送刚刚更改的联系人 ID,那就太好了。

    希望对你有帮助

    【讨论】:

    • 当电话簿中添加任何新联系人时,您能帮我做些什么吗?然后我会收到通知并将新联系人发送到服务器上的网络服务...@
    • 要从整个社区获得更多帮助,请创建一个关于您的阻止者、问题、关注等的新问题。
    【解决方案3】:

    首先,您必须注册您的 contentObserver 以接收更改通知。

    通过调用来做到这一点:

    registerContentObserver();
    

    这是规格:registerContetObserver

    之后,您会希望在发生修改时通知所有侦听器:

    contentResolver.notifyChange();
    

    这是那个的规格:notifyChange

    希望对你有帮助;)

    干杯!

    【讨论】:

    • 哎呀!我没有提到我正在注册并收到通知(即,来自使用 Android 通讯录 - 联系人应用程序的人)。我想要得到的是联系人的记录,这样我就可以在我的数据结构中捕获一个引用——相反,我要做的是搜索整个通讯录以查找任何更改。我的想法是我可能需要提供更具体的 URI 来观察,或者有一种方法可以从通知中提取密钥。 Oooorrrrr ...完全不同的东西:)
    • 好的。我这里没有你的完整代码结构,所以很难弄清楚所有这些......但是,你不能让每个记录都注册到观察者,以便在发生变化时直接通过记录得到通知吗? )
    • 其实所有的代码都在描述中。至于为每条记录注册是不切实际的。可能有 500 多个聚合联系人,这将是要注册的两倍(或更多)原始联系人。这就是为什么我希望可以指定 URI 以包含子查询。例如,您可以看到我尝试了 ContactsContract.Contacts.CONTENT_URI.buildUpon().appendEncodedPath("#").build(); -- 没有达到我希望的效果。
    • 好的,我明白了....那么也许您可以覆盖 URI 对象....定义您自己的自定义对象并自己嵌入所需的子查询信息... ;)
    • 如何覆盖 URI?我必须对 URI 的内容提供者进行子类化。
    【解决方案4】:

    使用加载器在您的模拟器上查询和显示您的安卓设备上的联系人列表。 它们会自动检测基础数据的变化并将其反映在您的 UI 上。

    【讨论】:

      猜你喜欢
      • 2011-11-27
      • 1970-01-01
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多