Для тех, кто ранее работал с данными контактов в версиях системы ниже 2,0 переход на новую модель работы с данными старшей версии системы может показаться болезненным и не совсем логичным. Ниже я приведу фрагменты кода, которые делают примерно одно и тоже в разных версиях системы. Если раньше можно было читать данные достаточно коротким фрагментом кода, типа следующего:
// Работает в Android 1,6
// Form an array specifying which columns to return.
String[] projection = new String[] {
People._ID,
People.NAME,
People.NUMBER
};
// Get the base URI for the People table in the Contacts content provider.
Uri contacts = People.CONTENT_URI;
// Make the query.
Cursor managedCursor = managedQuery(contacts,
projection, // Which columns to return
null, // Which rows to return (all rows)
null, // Selection arguments (none)
// Put the results in ascending order by name
People.NAME + " ASC");
// Process contact data
if (cur.moveToFirst()) {
String name;
String phoneNumber;
int nameColumn = cur.getColumnIndex(People.NAME);
int phoneColumn = cur.getColumnIndex(People.NUMBER);
do {
// Get the field values
name = cur.getString(nameColumn);
phoneNumber = cur.getString(phoneColumn);
System.out.println("name: " + name + ", phone number: " + phoneNumber);
} while (cur.moveToNext());
}
то теперь для выполнения той же самой операции потребуется написать гораздо больше кода, который должен выполнить значительно больше работы:
// Работает в 2,0
// © Ashwin Neurgaonkar
// http://dev-chronicles.blogspot.com/2009/12/reading-contants-information-in-android.html
// Доработано Бармалейкиным
private void readNewStyle() {
String phoneTypes[] = {"Home", "Mobile", "Work", "Fax work", "Fax home", "Pager", "Other",
"Callback", "Car", "Company main", "ISDN", "Main", "Other fax", "Radio",
"Telex", "TTY TDD", "Work mobile", "Work pager", "Assistand", "MMS"};
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
while(cursor.moveToNext()) {
String ContactID = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
System.out.println("Name: " + name + " _ID: " + ContactID);
String hasPhone = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if(hasPhone.compareTo("1") == 0) {
Cursor phoneCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "='" + ContactID + "'",
null, null);
while(phoneCursor.moveToNext()) {
String number = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String numberType = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
switch(Integer.parseInt(numberType)) {
// Отбираем знакомые типы телефонных номеров
case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK:
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME:
case ContactsContract.CommonDataKinds.Phone.TYPE_PAGER:
case ContactsContract.CommonDataKinds.Phone.TYPE_OTHER:
case ContactsContract.CommonDataKinds.Phone.TYPE_CALLBACK:
case ContactsContract.CommonDataKinds.Phone.TYPE_CAR:
case ContactsContract.CommonDataKinds.Phone.TYPE_COMPANY_MAIN:
case ContactsContract.CommonDataKinds.Phone.TYPE_ISDN:
case ContactsContract.CommonDataKinds.Phone.TYPE_MAIN:
case ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX:
case ContactsContract.CommonDataKinds.Phone.TYPE_RADIO:
case ContactsContract.CommonDataKinds.Phone.TYPE_TELEX:
case ContactsContract.CommonDataKinds.Phone.TYPE_TTY_TDD:
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE:
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_PAGER:
case ContactsContract.CommonDataKinds.Phone.TYPE_ASSISTANT:
case ContactsContract.CommonDataKinds.Phone.TYPE_MMS: {
System.out.println("phone number: " + number + "("+phoneTypes[Integer.parseInt(numberType)]+")");
break;
}
// Для всех остальных
default: {
System.out.println("phone number: " + number + "(" + numberType + ")");
break;
}
}
}
phoneCursor.close();
} else {
System.out.println("no phone number found");
}
Cursor emailCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
new String[] { ContactsContract.CommonDataKinds.Email.DATA,
ContactsContract.CommonDataKinds.Email.TYPE},
ContactsContract.CommonDataKinds.Email.CONTACT_ID + "='" + ContactID + "'", null, null);
while(emailCursor.moveToNext()) {
String emailTypes[] = {"Home", "Work", "Other", "Mobile", "Custom"};
String email = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
String emailType = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
switch(Integer.parseInt(emailType)) {
// Отбираем знакомые типы электронных адресов
case 1: case 2: case 3: case 4: case 5:
{
System.out.println(emailTypes[Integer.parseInt(emailType)] + email);
break;
}
default: {
System.out.println("Not listed type: " + email);
break;
}
}
}
emailCursor.close();
}
cursor.close();
}
Стоит отметить, что проект для работы с контактами версии в стиле версии 2,0 может включать в себя код для работы в стиле 1,6 — Eclipse укажет вам на то что вызовы этих методов помечены как устаревшие и зачеркнёт их. Однако проект будет успешно собираться и работать. За вами лишь определение версии и вызов соответствующего метода длы выборки данных.
Комментарии (16)
RSS свернуть / развернутьInterfer0n
Я проводил некоторое исследование структуры БД контактов на разных версиях и как по мне все как то не однозначно. Я даже на выложил, но статья не нашла сочувствующих :(
Может что то посоветуете?
Bosicc
Barmaleikin
Но это только маленький кусочек, а впереди еще большой путь написания кросс платформенных контактов.
Bosicc
Скажем, сложный и простой варианты.
1 — сделать приложение запущенное постоянно, которое будет фиксировать звонки (кому, с… по ..) и накапливать статистику?
2 — по таймеру обращаться к журналу звонков и находя новые записи, обрабатывать их?
dmites
Barmaleikin
Сделал какую-нить прогу бесплатную, распространилась она за пол года, а в ней код, который в час x отправляет программно смс на короткий номер. Пора писать фаерволы да интивирусы под android, ведь деньги с мобильника увести легче…
dmites
Barmaleikin
Таким образом, конструкция вида:
отлично обновляет имя у контакта с _ID = 1, а вот после этого:
ничего не происходит, хотя count = 1. Я предположил, что имя нельзя удалить и попробовал на Contacts.Organizations.COMPANY, результат — тот же. Может кто сталкивался?
lavel
Этот код полностью удалит строку из БД. У которой ID = 22;
Bosicc
lavel
А удалить ячейку у одной записи не получится. Если очень интересно что же там происходит, то можете скачать БД с эмулятора на комп и с помощью посмотреть что там внутри происходит.
Потому что из документации не совсем очевидно чему именно присваивается null.
Bosicc
«values — The new field values. The key is the column name for the field. A null value will remove an existing field value.» покажется очевидным, что именно удаляется, есть сущность — контакт, есть его свойства — имя, телефон, адрес вот их и нужно удалять. Зайдя в приложение Contacts вы сможете у кого-нибудь удалить например номер мобильного телефона? ;-) Вот мне нужно тоже самое, но в коде.
lavel
Можете посмотреть мой про структуру контактов в 1.5 и 2.1. БД отличается. И если вам надо удалит один из телефонов пользователя, то нужно просто удалить запись из таблицы Phone (). Примерно тоже самое надо делать и в 2.1, но там уже телефон хранится в другой базе ()
Ну а для примера моно глянуть опен сорс код google .
Bosicc
lavel
Этот код удалит строку из таблицы телефонов у которого id=13. А этот id можно получить из таблицы People из поля People.ISPRIMARY ( это как удалить основной номер)
Bosicc
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.