Эта статья является продолжением первой части (Работаем со списком контактов, #1). В этой статье вы узнаете, как определять тип контакта и как определить/вывести тип номера в виде строки.
Для определения типа контакта (или тип аккаунта, которому принадлежит контакт), нам понадобится таблица «raw_contacts», а конкретно столбец «ACCOUNT_TYPE».
В этом столбце хранится тип аккаунта, к которому принадлежит контакт и в паре со столбцом «ACCOUNT_NAME» идентифицирует конкретный аккаунт.
К сожалению, единственный тип аккаунта одинаковый на всех устройствах это аккаунт Google, его значение «com.google». Остальные типы (SIM и Телефон), на всех устройствах пишутся по-разному. В этом виноваты производители Android устройств!
Я провёл немало тестов и пытался найти универсальное решение для всех устройств, но так и не нашёл его. Единственный вариант, добавить условие проверки для всех возможных типов. Если вы знаете, как решить данную проблему, то обязательно напишите мне.
Вот информация (ACCOUNT_TYPE) по устройствам, которые мне удалось заполучить:
Аккаунт Google:
- Все устройства - «com.google»
SIM-карта:
- Samsung Galaxy S Plus, Samsung Galaxy S2 - «vnd.sec.contact.sim»
- HTC Sensation Z710e, HTC Rhyme – «com.anddroid.contacts.sim»
- Sony Xperia go – «нет информации»
Контакты телефона:
- Samsung Galaxy S Plus, Samsung Galaxy S2 - «vnd.sec.contact.phone»
- HTC Sensation Z710e, HTC Rhyme – «com.htc.android.pcsc»
- Sony Xperia go – «com.sonyericsson.localcontacts»
Теперь необходимо составить условие для выборки контактов.
Например, нам нужны контакты, сохранённые в телефоне: " AND (ACCOUNT_TYPE = 'vnd.sec.contact.phone' OR ACCOUNT_TYPE = 'com.htc.android.pcsc' OR ACCOUNT_TYPE = 'com.sonyericsson.localcontacts')".
Как будет выглядеть результат:
Код для кнопки:
procedure TForm1.Button1Click(Sender: TObject); var cursor, cursor2: JCursor; id: integer; ListBoxItem: TListBoxItem; begin cursor := SharedActivity.getContentResolver.query( TJContactsContract_Contacts.JavaClass.CONTENT_URI, nil, StringToJString('HAS_PHONE_NUMBER = 1'), nil, StringToJString('DISPLAY_NAME ASC')); ListBox1.Clear; ListBox1.BeginUpdate; if (cursor.getCount > 0) then begin while (cursor.moveToNext) do begin id := cursor.getInt(cursor.getColumnIndex(StringToJString('_ID'))); cursor2 := SharedActivity.getContentResolver.query( TJContactsContract_RawContacts.JavaClass.CONTENT_URI, nil, StringToJString('CONTACT_ID = ' + IntToStr(id) + ' AND ' + '(ACCOUNT_TYPE = ' + '''vnd.sec.contact.phone''' + ' OR ACCOUNT_TYPE = ' + '''com.htc.android.pcsc''' + ' OR ACCOUNT_TYPE = ' + '''com.sonyericsson.localcontacts'')'), nil, nil); while (cursor2.moveToNext) do begin ListBoxItem := TListBoxItem.Create(ListBox1); ListBoxItem.ItemData.Text := JStringToString(cursor.getString( cursor.getColumnIndex(StringToJString('DISPLAY_NAME')))); ListBoxItem.ItemData.Detail := JStringToString(cursor2.getString( cursor2.getColumnIndex(StringToJString('ACCOUNT_TYPE')))); ListBoxItem.Tag := id; ListBox1.AddObject(ListBoxItem); end; cursor2.close; Label1.Text := 'Всего: ' + IntToStr(ListBox1.Count); end; end; cursor.close; ListBox1.EndUpdate; end;
Далее, научим наше приложение выводить тип для всех номеров отдельно взятого контакта.
В предыдущей статье, мы с вами уже научились выводить идентификатор типа, а значит половина дела сделано. Нам остаётся только найти текстовое значение для каждого идентификатор типа.
Для этого пишем вот такую строчку кода:
ListBoxItem.ItemData.Detail := JStringToString(SharedActivity.getString( TJCommonDataKinds_Phone.JavaClass.getTypeLabelResource(NumberType)));
Также следует не забывать, что пользователь может создать свой собственный тип номера. Этот тип будет храниться в столбце «DATA3», а значение идентификатора будет равно «0». Значит, нужно написать условие проверяющее значение идентификатора на ноль.
Код для события «OnItemClick»:
procedure TForm1.ListBox1ItemClick(const Sender: TCustomListBox; const Item: TListBoxItem); var id, NumberType: integer; FIO: string; cursor: JCursor; ListBoxItem : TListBoxItem; begin TabControl1.ActiveTab := TabItem2; id := Item.Tag; FIO := Item.Text; Label2.Text := FIO; cursor := SharedActivity.getContentResolver.query( TJCommonDataKinds_Phone.JavaClass.CONTENT_URI, nil, StringToJString('CONTACT_ID = ' + IntToStr(id)), nil, nil); ListBox2.Clear; ListBox2.BeginUpdate; if(cursor.getCount > 0) then begin while (cursor.moveToNext) do begin ListBoxItem := TListBoxItem.Create(ListBox2); ListBoxItem.ItemData.Text := JStringToString(cursor.getString( cursor.getColumnIndex(TJCommonDataKinds_Phone.JavaClass.NUMBER))); NumberType := cursor.getInt(cursor.getColumnIndex(StringToJString('DATA2'))); if NumberType = 0 then begin ListBoxItem.ItemData.Detail := JStringToString(cursor.getString( cursor.getColumnIndex(StringToJString('DATA3')))); end else begin ListBoxItem.ItemData.Detail := JStringToString(SharedActivity.getString( TJCommonDataKinds_Phone.JavaClass.getTypeLabelResource(NumberType))); end; ListBox2.AddObject(ListBoxItem); end; end; cursor.close; ListBox2.EndUpdate; end;
UPDATE (20.04.14):
Чтобы код заработал в Delphi XE6, необходимо:
в "uses" заменить модуль "Androidapi.JNI.JavaTypes" на "Androidapi.Helpers".
Архив обновлён (Добавил комментарий для Delphi XE6)!
Как выглядит результат:
Удачной разработки.