如何在地址簿中收听插入/更新/删除的联系人

时间:2014-02-08 19:13:41

标签: android sync android-contacts contentobserver

有很多与之相关的问题,但没有一个能帮助我找到解决方案。

我正在尝试将所有联系人从设备同步到远程服务器并且能够轻松完成,但是当更新/删除/插入(新联系人)等联系人发生更改时无法找到解决方案。

尝试使用ContentObserver,但onChange()被多次调用。很难找到联系人更改数据。

    public class ContactService extends Service {

    private int mContactCount;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mContactCount = getContactCount();

        Log.d("Contact Service", mContactCount + "");

        this.getContentResolver().registerContentObserver(
                ContactsContract.Contacts.CONTENT_URI, true, mObserver);
    }

    private int getContactCount() {
        Cursor cursor = null;
        try {
            cursor = getContentResolver().query(
                    ContactsContract.Contacts.CONTENT_URI, null, null, null,
                    null);
            if (cursor != null) {
                return cursor.getCount();
            } else {
                return 0;
            }
        } catch (Exception ignore) {
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return 0;
    }

    private ContentObserver mObserver = new ContentObserver(new Handler()) {

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);

            final int currentCount = getContactCount();
            if (currentCount < mContactCount) {
                // CONTACT DELETED.

                Log.d("Contact Service", currentCount + "");

            } else if (currentCount == mContactCount) {
                // CONTACT UPDATED.
            og.d("Contact Service", currentCount+"");

            } else {
                // NEW CONTACT.
                Log.d("Contact Service", currentCount + "");

            }
            mContactCount = currentCount;
        }

    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        getContentResolver().unregisterContentObserver(mObserver);
    }
}

但是当地址簿中有更新/插入时,onChange()会被多次调用。

任何人都能为我提供更好的解决方案吗?

非常感谢。

由于

4 个答案:

答案 0 :(得分:18)

关于onChange的问题是,它被调用以进行删除/添加/更新,因此您不能只计算联系人的数量,因为一个人可能已被删除,一个已添加,然后您有一个更改的联系人簿,但同样重要。但是,查看 column 版本,您应该能够评估哪些联系人已更新(在您已经获得联系簿的完整副本之后)。只需检查版本是否大于您已经存在的版本(对于当前联系人)。

答案 1 :(得分:1)

按照Magnus&#39;回答,使用此列检索版本代码

ContactsContract.RawContacts.VERSION

答案 2 :(得分:0)

这对我来说很好。

1 - 注册服务

this.getApplicationContext()
                .getContentResolver()
                .registerContentObserver(
                        ContactsContract.Contacts.CONTENT_URI, true,
                        new ContactsListner(new Handler(),this,getContactCount()));

2 - getContactCount() 的定义

private int getContactCount() {
        Cursor cursor = null;
        try {
            cursor = activity.getContentResolver().query(
                    ContactsContract.Contacts.CONTENT_URI, null, null, null,
                    null);
            if (cursor != null) {
                return cursor.getCount();
            } else {
                return 0;
            }
        } catch (Exception ignore) {
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return 0;
    }

3 - 联系人监听类

import android.app.Activity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.provider.ContactsContract;
import android.widget.Toast;

import androidx.annotation.Nullable;

public class ContactsListner extends ContentObserver {
    /**
     * Creates a content observer.
     *
     * @param handler The handler to run {@link #onChange} on, or null if none.
     *
     *
     */

    Activity activity;
    int contactsCount;

    public ContactsListner(Handler handler, Activity activity, int contactsCount) {
        super(handler);
        this.activity = activity;
        this.contactsCount = contactsCount;
    }




    @Override
    public void onChange(boolean selfChange, @Nullable Uri uri) {
        super.onChange(selfChange, uri);



            int currentContacts = getContactCount();
            Toast.makeText(activity, "Current num is "+currentContacts+"     and recent : "+contactsCount, Toast.LENGTH_SHORT).show();

            if (currentContacts<contactsCount){
                Toast.makeText(activity, "Deleted", Toast.LENGTH_SHORT).show();
            }else if (currentContacts == contactsCount){
                Toast.makeText(activity, "Update occurred", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(activity, "New contact added", Toast.LENGTH_SHORT).show();
            }

            contactsCount = currentContacts;

    }





    private int getContactCount() {
        Cursor cursor = null;
        try {
            cursor = activity.getContentResolver().query(
                    ContactsContract.Contacts.CONTENT_URI, null, null, null,
                    null);
            if (cursor != null) {
                return cursor.getCount();
            } else {
                return 0;
            }
        } catch (Exception ignore) {
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return 0;
    }
}

答案 3 :(得分:-2)

我这样做了,它对我有用,可以调用Log和ContactNumber Change。

  <DataGridTemplateColumn Visibility="Visible"  Header="Reason Id"  Width="250">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <ComboBox x:Name="" SelectedValue="{Binding TypeId}" SelectedValuePath="TypeId" DisplayMemberPath="Type"  
                                                  ItemsSource="{Binding TypeItems}" ></ComboBox>
                                </StackPanel>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>