Как заставить Android ContentObserver для ContactsContract обнаруживать добавленный, обновленный или удаленный контакт?
Я могу получить общее уведомление "о том, что произошла смена базы данных контактов", но я хочу знать конкретную запись, которая была вставлена, обновлена или удалена. Ниже приведен код, который регистрируется и получает уведомление 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);
Ответы
Ответ 1
У меня этот код в базовом классе Application.
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);
}
}
}
Относительно того, что вы можете поставить в проекции, проверьте здесь
Unfortunately, it is not specific which makes my processing exhaustive and inefficient.
Было бы здорово, если в следующие выпуски Android также будет отправлен идентификатор контакта, который был только что изменен.
Надеюсь, что это поможет
Ответ 2
Наконец, по крайней мере, я могу обнаружить это Обновить/Удалить/Вставить посмотреть на мой метод 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);
}
}
Когда произошло Обновление, я обновляю все контакты
Когда произошел Вставить, я вставляю новую добавленную строку, после проверки isExist в существующей базе данных
Когда Удалить еще не найдено решение
Ответ 3
Прежде всего, вы должны зарегистрировать свой контентный сервер, чтобы получать уведомление об изменении.
Сделайте это, позвонив:
registerContentObserver();
Здесь спецификации: registerContetObserver
После того, как вы захотите уведомить всех слушателей, когда произойдет изменение:
contentResolver.notifyChange();
Здесь спецификации для этого: notifyChange
Надеюсь, что это поможет;)
Приветствия!
Ответ 4
Используйте Loaders для запроса и отображения списка контактов на вашем устройстве Android на вашем эмуляторе.
Они автоматически обнаруживают изменения в базовых данных и отражают их в пользовательском интерфейсе.