【问题标题】:How can I get a phone's contact list in a Firemonkey mobile application?如何在 Firemonkey 移动应用程序中获取手机的联系人列表?
【发布时间】:2013-11-08 18:17:27
【问题描述】:

如何在 FireMonkey 移动应用程序中获取手机的联系人列表?

【问题讨论】:

  • 您是否尝试阅读androidiOS 关于此主题的文档?
  • 我不是用 java 或 object c 编写的,我使用的是 Rad Studio XE5。

标签: android ios delphi firemonkey delphi-xe5


【解决方案1】:

给你 .. 它还没有完成,因为它读取了一个人的所有数字,如果有两个数字,你将在列表中列出这个人的两倍 .. 但是从这里我认为你可以工作并调整它以适应你的需要:))

function GetContact: TStringList;
var
cursorContacts, cursorContactsPhone: JCursor;
hasPhoneNumber: Integer;
id: Int64;
displayName, phoneNumber, contactID: string;
begin
Result := TStringList.Create;
cursorContacts := SharedActivity.getContentResolver.query(TJContactsContract_Contacts.JavaClass.CONTENT_URI, nil, nil, nil, nil);
if (cursorContacts.getCount > 0) then
begin
while (cursorContacts.moveToNext) do
begin
id := cursorContacts.getLong(cursorContacts.getColumnIndex(StringToJString('_ID')));
displayName := JStringToString(cursorContacts.getString(cursorContacts.getColumnIndex(StringToJString('DISPLAY_NAME'))));
hasPhoneNumber := cursorContacts.getInt(cursorContacts.getColumnIndex(StringToJString('HAS_PHONE_NUMBER')));
if (hasPhoneNumber > 0) then
begin
cursorContactsPhone := SharedActivity.getContentResolver.query(TJCommonDataKinds_Phone.JavaClass.CONTENT_URI, nil,StringToJString('CONTACT_ID = ' + IntToStr(id)),nil, nil);
while (cursorContactsPhone.moveToNext) do
begin
phoneNumber := JStringToString(cursorContactsPhone.getString(cursorContactsPhone.getColumnIndex(StringToJString('DATA1'))));
contactID := JStringToString(cursorContactsPhone.getString(cursorContactsPhone.getColumnIndex(StringToJString('CONTACT_ID'))));
Result.Add(displayName + ': ' + phoneNumber);
end;
cursorContactsPhone.close;
end;
end;
end;
cursorContacts.close;
end;

最好的问候, 克鲁诺

【讨论】:

  • 嘿,我在使用此代码时遇到问题。我得到 TJContactsContract_Contacts.JavaClass.CONTENT_URI 和 TJCommonDataKinds_Phone.JavaClass.CONTENT_URI 的未声明标识符。你碰巧知道为什么,以及如何解决这个问题吗?谢谢!
  • 您需要 Androidapi.Jni.Provider 用于此用途并投入使用:Androidapi.JNIBridge、Androidapi.Jni.GraphicsContentViewText、Androidapi.Jni.Net、Androidapi.Jni.JavaTypes、FMX。 Helpers.Android ...
  • 哈哈! .Provider 不见了! :O 我已经拥有了所有其他人,谢谢。试图包括其他几个,但没有像看起来那样到达提供者:/谢谢!!! Ps:您是否碰巧有此代码的更新/更新版本,它也删除了人的外观等的重复,或者没有在这方面做任何进一步的进展? :)
  • 抱歉重播晚了 :) ...我将在此处发布过滤解决方案,但我在此发帖的站点上没有它...会尽快完成,但你也可以这样做:首先将所有名称和 ID 放入一个列表中,然后在基于名称的第二个列表中获取与名称和 PhoneID 相关的数字 :)
  • 我实际上已经开始工作了。 :) 不管怎么说,还是要谢谢你!!我对它进行了排序,所以我没有重复,我还通过名称使用“LIKE”属性查询它来使用 tEdit.OnChange 事件进行自动搜索,虽然它工作得非常慢,如果我只用一个字母做的话,所以我现在至少使用 2 个字符,而且它完美无瑕 :)
【解决方案2】:

这是我的代码(灵感来自 @mali kruno,最初由 @mali kruno 创建,我只是根据自己的需要更改它!)根据 TEdit OnChange 事件搜索所有联系人:

我在 commonfunctions.pas 单元中使用了这个函数:

function GetContact (Name: string; Number: string; const tip: integer) : TStringList;
var
cursorContactsPhone: JCursor;
Typo1, Typo2: string;
FindBy: JString;
ToFind: TJavaObjectArray<JString>;
CurRec: integer;
begin
Result:=TStringList.Create;
CurRec:=0;
ToFind:= TJavaObjectArray<JString>.Create(2);
if Name <> '' then
  begin
    ToFind.Items[0] := StringToJString('data1');
    ToFind.Items[1] := StringToJString('display_name');
    FindBy := StringToJString('display_name LIKE "%' + Name + '%"');
    Typo1:='data1';
    Typo2:='display_name';
  end
else if Number <> '' then
  begin
    ToFind.Items[0] := StringToJString('display_name');
    ToFind.Items[1] := StringToJString('data1');
    FindBy := StringToJString('data1 LIKE "%' + Number + '%"');
    Typo1:='display_name';
    Typo2:='data1';
  end;
cursorContactsPhone := SharedActivity.getContentResolver.query(TJCommonDataKinds_Phone.JavaClass.CONTENT_URI, ToFind, FindBy, nil, nil);
while (cursorContactsPhone.moveToNext) do
begin
Result.Add
(JStringToString(cursorContactsPhone.getString(cursorContactsPhone.getColumnIndex(StringToJString(Typo2)))) + ' - ' +
JStringToString(cursorContactsPhone.getString(cursorContactsPhone.getColumnIndex(StringToJString(Typo1)))));
CurRec:=CurRec+1;
end;
cursorContactsPhone.close;
end;

我从 ContactSearch.Change 事件(它是 TEdit 组件)中调用它,如下所示:

procedure TMainF.ContactsSearch.Change(Sender: TObject);
var ResultNo: integer; SearchContacts: string; Results: TStringList;
begin                   // begin main procedure
if ContactsSearch.Text.Length > 1 then
begin                 //begin search and memo update
SearchContacts:=ContactsSearch.Text;
Results:=GetContact(SearchContacts, '', 0);
ResultNo:=0;
Memo1.Lines.Clear;
for ResultNo := 0 to Results.Count-1
do
begin
Memo1.Lines.Add(Results.Strings[ResultNo]);
end;

Results.Free;
end;
end;

请注意,ResultTStringList 在函数中创建在备忘录更新后在一个过程中释放。 另请注意,我只搜索 TEdit 长度为 2 或更多,否则在 tedit 中仅输入“a”将显示所有具有字母“a”的联系人以他们的名义,因此每次搜索,使用退格等时它都会冻结一点...... 解决方法是在应用程序启动时将电话簿加载到 TStringList 中,然后仅搜索字符串列表,但这不会带来其他麻烦: a) 不会检测到电话簿更新,或者您必须实现“更新”按钮,这根本没有任何意义来解决这个问题.. b)应用程序启动需要更长的时间 c) 没有尝试过,并且不确定它实际上会加速搜索多少,因为 Memo.Lines.Add 比查询本身花费更多的时间,所以......

至于重复,您可以看到这里没有处理,因为目前我不需要这样做,但是您可以使用备忘录中的“排序”轻松处理,或者,如果您更好不想丢失否则会显示为重复的条目,在 TStringList 本身内部管理它们,以便您在同一行中合并数字,或为每个名称创建子字符串列表(当然,只有在出现名称时不止一次,如果您不想最终获得两倍于实际需要的字符串列表)。

希望这会有所帮助。

【讨论】:

  • 这个例子不会在 100% 下工作,因为项目 'data1' 用于在显示屏上显示电话号码(在某些型号的设备上用于显示号码,例如空格或破折号)。最好使用“data4”项,因为它使用原始数据。
【解决方案3】:

考虑到 Delphi 没有为这个问题提供统一/封装的解决方案,您的操作方式与使用本机编程 API 的程序员大致相同。

您需要研究 Android SDK 如何显示联系人列表以及 iOS SDK 如何显示其联系人列表,然后使用原生 API 来访问它。

这两个平台之间会有很大的不同,但是一旦您在 2 个不同的操作系统上建立了实现并查看了提供的内容以及跨平台可访问的内容,编写一些独立于操作系统的接口是可行的两个实现。这就是 FMX 在两个平台上实现的类似功能的其他实例中所做的。

如果所需的 API 尚未导入 Delphi 的 RTL(这很有可能),那么您还需要为您需要的那些 API 编写导入,以便能够首先调用它们。

执行摘要:

  1. 卷起袖子
  2. 陷入困境
  3. 自己编写代码
  4. 享受一些很酷的 API 工作带来的乐趣

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 2018-05-31
    相关资源
    最近更新 更多