Перейти к содержанию
  • Регистрация
  • 0
ENERGY

Поиск контакта по номеру

Вопрос

Никак не могу сделать поиск контакта по номеру.

 

Есть пример на Java, я все пытаюсь научиться переводить с java на Delphi, но не всегда получается. Вот пример (там же есть полный пример.): 

 

Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...

 

В нем используется Uri.withAppendedPath  (это Jnet_UriClass из Androidapi.JNI.Net) Я нигде не нашел пример работы с ним.

Попытался сделать сам : 

  vUriClass: Jnet_UriClass;
  vfilter : TJavaObjectArray<JString>;

wUri := vUriClass.withAppendedPath( TJContactsContract_PhoneLookup.JavaClass.CONTENT_FILTER_URI,
        vUriClass.encode( StringToJString('+11111111') ) );

   vfilter := TJavaObjectArray<JString>.Create(1);
   vfilter[0] := TJCommonDataKinds_StructuredName.JavaClass.DISPLAY_NAME;
                                                 

    with  SharedActivity.getContentResolver do
      wCursor :=query(wUri, vfilter, nil,nil, nil); // Query to get all contact sorted by displayname

Но ничего не получилось, вылетает ошибка сегментации в withAppendedPath.

 

Помогите пожалуйста, одна на вас надежда. Второй день пошел уже. Как этот ContactsContract.PhoneLookup provider использовать?

Вот полный код на Java :

public String getContactDisplayNameByNumber(String number) {
    Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
    String name = "?";

    ContentResolver contentResolver = getContentResolver();
    Cursor contactLookup = contentResolver.query(uri, new String[] {BaseColumns._ID,
            ContactsContract.PhoneLookup.DISPLAY_NAME }, null, null, null);

    try {
        if (contactLookup != null && contactLookup.getCount() > 0) {
            contactLookup.moveToNext();
            name = contactLookup.getString(contactLookup.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
            //String contactId = contactLookup.getString(contactLookup.getColumnIndex(BaseColumns._ID));
        }
    } finally {
        if (contactLookup != null) {
            contactLookup.close();
        }
    }

    return name;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендуемые сообщения

  • 0

Есть компонент TAddressBook, он не подходит?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Большое Вам спасибо Ярослав, за то что вносите большой вклад в развитие Mobile Delphi. Очень мало примеров  и документации (причем на любом языке) по этому поводу, ваш сайт очень выручает.

Я попробовал демку c:\Program Files (x86)\Embarcadero\Studio\18.0\Samples\Object Pascal\Multi-Device Samples\Device Sensors and Services\Address Book\Contacts\Contacts_Delphi.dproj с  TAddressBook .

Delphi 10 upd 1

Запускал на телефоне HTC - ни один контакт не загрузился - просто пустой список.

UPD: Вместо  AddressBook1.AllContacts(Source, Contacts);

Нужно  AddressBook1.AllContacts(nil, Contacts);  тогда загружает все контакты.

Вся проблема в том, что он считывает сразу все контакты. А мне это не нужно.

Лучше использовать код для поиска конкретного номера, прекрасно находит работает (также работает и вставка нового контакта, здесь описал http://stackoverflow.com/questions/29782398/insert-contacts-in-android-with-delphi/41294891#41294891): 

function TCore.IsNumberInAddressBook(const aNumber: string): boolean;
var
  vCursor: JCursor;
  vQueryStr: string;
begin
  Result := false;
  // will be: data1 LIKE '%+380501960000%'   (with quotes)
  vQueryStr := JStringToString( TJCommonDataKinds_Phone.JavaClass.NORMALIZED_NUMBER) + ' LIKE ''%' + aNumber + '%''';

  vCursor := TAndroidHelper.Activity.getContentResolver.query(
    TJCommonDataKinds_Phone.JavaClass.CONTENT_URI,
    nil,   //projection String: A list of which columns to return. Passing null will return all columns, which is inefficient.
    StringToJString(vQueryStr), // String: A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given URI.
    nil, nil);
   // Query help: https://developer.android.com/reference/android/content/ContentResolver.html#query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String)

  if vCursor <> nil then
  try
    Result := vCursor.getCount > 0;
   finally
    vCursor.close;
  end;
end;

// а это может пригодится
 while (cursor.moveToNext) do  
 begin

   lbContactsList.Text := JStringToString(cursor.getString(
      cursor.getColumnIndex(StringToJString('DISPLAY_NAME'))));
   lbContactsList.Tag := cursor.getInt(cursor.getColumnIndex(StringToJString('_ID')));
   //  ListBox1.AddObject(ListBoxItem);
end;

 

Цитата

У меня вопрос к Вам. Вы не в курсе где находится исходный код процедуры

procedure AllContacts(const ASource: TAddressBookSource; var AContacts: TAddressBookContacts); (unit FMX.AddressBook)?

UPD: AllContacts находится в \source\fmx\FMX.AddressBook.Android.pas

 

 

А вообще для самообразования хотелось бы узнать как вызвать  ContactsContract.PhoneLookup.CONTENT_FILTER_URI

И что это за конструкция такая Uri.withAppendedPath, ведь в будущем наверняка с ней придется сталкиваться. Если вы в курсе, расскажите пожалуйста.

Изменено пользователем ENRGY

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 24.12.2016 в 01:35, Brovin Yaroslav сказал:

Есть компонент TAddressBook, он не подходит?

 

А как быть со службой? Если в USES есть FMX.AddressBook, то в службах это работать не будет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Всё-таки есть у кого-нибудь рабочий пример поиска имени по номеру телефона?

Буду премного благодарен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Есть такой пример поиска имени контакта по номеру телефона. Он компилируется, работает, но номер телефона не находит.

 

function TDMSrv.GetContactByPhoneNumber(const sTel: string): string;
var
  wJDislpayName,
  wJFirstName,
  wJLastName,
  wJQueryStr: JString;
  wJQueryParams: TJavaObjectArray<JString>;

  wSubCursor: JCursor;
  wfilter: TJavaObjectArray<JString>;
  wDataUri: JNet_URI;
begin
  if sTel.IsEmpty then
  begin
    log('GetContactByPhoneNumber. Phone number is empty!');
    exit;
  end;

  wDataUri := TJContactsContract_Data.JavaClass.CONTENT_URI;

  wfilter := TJavaObjectArray<JString>.Create(3);
  wfilter[0] := TJCommonDataKinds_StructuredName.JavaClass.DISPLAY_NAME;
  wfilter[1] := TJCommonDataKinds_StructuredName.JavaClass.FAMILY_NAME;
  wfilter[2] := TJCommonDataKinds_StructuredName.JavaClass.GIVEN_NAME;

  wJQueryStr := StringToJString('mimetype = ? AND lookup = ?');

  wJQueryParams := TJavaObjectArray<JString>.Create(2);
  wJQueryParams[0] := TJCommonDataKinds_Phone.JavaClass.NUMBER;
  wJQueryParams[1] := StringToJString(sTel);

  wSubCursor := TAndroidHelper.Context.getContentResolver.Query(wDataUri, wfilter, wJQueryStr, wJQueryParams, nil);

  try
    if wSubCursor.getCount > 0 then
    begin
      // Getting only first row, as we retrieving only names, a contact can have only one first name, one familyname,
      // for phone number for example, we need to loop on each row (while (wSubCursor.moveToNext) do) because a contact can have many phone number
      log('wSubCursor.getCount = ' + wSubCursor.getCount.ToString);
      wSubCursor.moveToNext;
      wJDislpayName := wSubCursor.getString(0);
      wJLastName    := wSubCursor.getString(1);
      wJFirstName   := wSubCursor.getString(2);
    end
    else
      log('wSubCursor.getCount = 0');

    Result := JStringToString(wJDislpayName);
  finally
    wSubCursor.close;
    FreeAndNil(wSubCursor);// := nil;
  end;
end;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
21 час назад, x11 сказал:

Всё-таки есть у кого-нибудь рабочий пример поиска имени по номеру телефона?

Буду премного благодарен.

Возьмите сорцы FMX.AddressBook.Android и заиспользуйте тот код. Единственная причина по которой адресная книга тянет за собой всю платформу в сервисах - это работа с TBitmapSurface. В теории, если уберете всю работу с BitmapSurface (он нужен только для загрузки фоток), то уберете зависимость от платформы. и в этом случае можно использовать эту реализацию напрямую в сервисах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Спасибо, конечно... но...

 

51 минуту назад, Brovin Yaroslav сказал:

В теории, если уберете всю работу с BitmapSurface (он нужен только для загрузки фоток), то уберете зависимость от платформы. и в этом случае можно использовать эту реализацию напрямую в сервисах.

 

На сколько я знаю, то FMX.AddressBook тянет за собой всю адресную книгу себе... зачем?

Ну и я не настолько в этом разбираюсь, чтобы правильно что-то "убрать".

Изменено пользователем x11

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Взял файл, удалил из uses все упоминания, начинающиеся с FMX, "прикрепил" к проекту, при попытке скомпилировать - 70+ ошибок.

Screenshot_1.png

Изменено пользователем x11

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
18 часов назад, x11 сказал:

Взял файл, удалил из uses все упоминания, начинающиеся с FMX, "прикрепил" к проекту, при попытке скомпилировать - 70+ ошибок.

Screenshot_1.png

Ну и правильно, удалить то удалили, а зависимости не разрешили. 

Из исходника в свой юнит или куда еще, надо перенести именно те методы, дергающие api, которые нужны для решения задачи.

Завтра конкретнее посмотрю

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Для решения задачи, по идее, мне нужна только одна маленькая процедура.

Т.е. получается за многолетнюю историю FMX я сейчас пока что единственный, кому понадобилось выполнить поиск контакта по номеру в сервисе? Ну или другой поиск в адресной книге Андроида.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

смотрите код на джава, примеров уйма на стаке.

сравните что в вашем коде выше не так, вот ссылочка для примера 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

В том-то и дело, что не получается. Вот пример (см там, где 79 оценок)

https://stackoverflow.com/questions/3712112/search-contact-by-phone-number

как его перевести в Delphi?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Вот мне подсказали на sql.ru рабочий пример, который и у меня получилось использовать в службе.

Я так понимаю, что приходится в этом случае получать полностью всю адресную книгу и потом перебирать её у себя в коде циклом, что не совсем правильно.

Пример компилируется и работает на Delphi Tokyo:

function GetContactByNumbers(const aPhoneNumbers: TList<String>): string;
var
  wUri: JNet_URI;
  lookupID: String;
  wCursor,
  wSubCursor: JCursor;
  wLookup_Idx: Integer;
  wDisplayNameIdx: integer;
  wfilter,
  wJQueryParams: TJavaObjectArray<JString>;
  wDataUri: JNet_URI;
begin
  wUri :=  TJContactsContract_Contacts.JavaClass.CONTENT_URI;
  wCursor := TAndroidHelper.Context.getContentResolver.query(wUri, nil, nil, nil, StringToJString('display_name ASC'));
   try
     wLookup_Idx := wCursor.getColumnIndex(StringToJString('lookup'));
     wDisplayNameIdx := wCursor.getColumnIndex(StringToJString('display_name'));

     while wCursor.moveToNext do
     begin
       lookupID := JStringToString(wCursor.getString(wLookup_Idx));
       wfilter := TJavaObjectArray<JString>.Create(1);
       wfilter[0] := TJCommonDataKinds_Phone.JavaClass.NUMBER;

       // Qurey condition (Exrtact only data for specific ID)
       wJQueryParams := TJavaObjectArray<JString>.Create(2);
       wJQueryParams[0] := TJCommonDataKinds_Phone.JavaClass.CONTENT_ITEM_TYPE;
       wJQueryParams[1] := StringToJString(lookupID);

       wDataUri := TJContactsContract_Data.JavaClass.CONTENT_URI;  // Contacts data uri

       wSubCursor := TAndroidHelper.Context.getContentResolver.
         Query(wDataUri,wfilter,StringToJString('mimetype = ? AND lookup = ?') , wJQueryParams,nil); // Exec query

       try
         if wSubCursor.getCount > 0 then
         begin
           while (wSubCursor.moveToNext) do
           begin
             if aPhoneNumbers.Contains(JStringToString(wSubCursor.getString(0))) then
             begin
               Result := JStringToString(wCursor.getString(wDisplayNameIdx));
               Break;
             end;
           end;
         end;
       finally
         wSubCursor.close;
         wSubCursor := nil;
       end;
     end;
   finally
     wCursor.Close;
     wCursor := nil;
   end;
end;

 

 

К сожалению, в справке по Delphi нет описания TJContactsContract_Contacts, TJCommonDataKinds_Phone и TAndroidHelper.Context.getContentResolver.query. И примеров нет.

 

И пример использования:

// В USES нужно добавить System.Generics.Collections для TList.

VAR
 ListNumbers: TList<string>;
begin

  ListNumbers := TList<string>.Create;
  try
    ListNumbers.Add(sTel);// передаем полный номер: +380681234567
    ListNumbers.Add(RightStr(sTel, 10));// если в адресной книге записан номер без кода оператора - 0681234567
    ContactName := GetContactByNumbers(ListNumbers);
  finally
    FreeAndNil(ListNumbers);
  end;

 

Изменено пользователем x11

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

И ещё не понятно, как работает код, когда у контакта в адресной книге есть 2 номера телефона. Я проверил - оба функция находит, но где это, в каком месте кода, я не понял.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 23.12.2016 в 22:09, ENERGY сказал:

Есть пример на Java, я все пытаюсь научиться переводить с java на Delphi, но не всегда получается. Вот пример (там же есть полный пример.): 

 

function TContactsManager.GetContactByNumber(
  const aPhoneNumber: string): string;
var
  wUri: JNet_URI;
  wCursor: JCursor;
  wfilter,
  wJQueryParams: TJavaObjectArray<JString>;
begin
  Result := '';
  wUri := TJNet_URI.JavaClass.withAppendedPath
    (
     TJContactsContract_PhoneLookup.JavaClass.CONTENT_FILTER_URI,
     StringToJString(aPhoneNumber)
    );

  wfilter := TJavaObjectArray<JString>.Create(2);
  wfilter[0] := StringToJString('lookup');
  wfilter[1] := StringToJString('display_name');

  with SharedActivity.getContentResolver do
    wCursor := query(wUri, wfilter, nil, nil, nil);

  try
    if Assigned(wCursor) and
       (wCursor.getCount > 0) then
    begin
      wCursor.moveToNext;
      Result := JStringToString(wCursor.getString(
        wCursor.getColumnIndex(StringToJString('display_name'))));
    end;
  finally
    wCursor.Close;
    wCursor := nil;
  end;
end;

http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1183758&msg=21183983

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...