Эта статья является продолжением первой части (Работаем со списком контактов, #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)!
Как выглядит результат:
Удачной разработки.

