Esta unidad nos muestra cómo se accede a nuestros contactos del móvil Android. Inicialmente en la "Contact list" nos muestra el nombre y pulsando sobre cualquiera de ellos veremos la información de detalle en la caja inferior. Probado en Rad Studio XE10. Tener en cuenta que en vuestra app tendréis que activar el permiso "Read contacts" para que funcione correctamente.
unit ContactsManager;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Helpers.Android,Androidapi.JNI.provider, Androidapi.JNI.JavaTypes,
Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Net, Androidapi.Jni.App,
Androidapi.JNIBridge, Androidapi.Helpers;
Type
// Record for contact data
TContactData = Record
LookupID : string;
Display_Name : String; // Display name : in almost smartphone it's last name + space + First name
FamilyName : String;
FirstName : String;
Email : String;
Phone : string;
End;
PContactData = ^TContactData; // Pointer to record
// This class manage contact data
TContactsManager = class
private
fContactsList : TList; // List of contacts
procedure ClearList; // procedure to clear contacts list
function GetContactsCount : integer; // Retrieveing contacts number
function GetContact(AIndex : Integer) : PContactData; //Access a contact record
procedure GetContactExtendedData(AContact : PContactData); // Retrieve extended data for a contact (Email, Phone, ....)
public
constructor Create;
Destructor Destroy;override;
procedure ExtractContactsList; //Retrieve all contacts
property Contacts[AIndex : Integer] : PContactData read GetContact;
property ContactsCount : Integer read GetContactsCount;
end;
implementation
{ TContactManager }
{-------------------------------------------------------------------------------
Procedure: TContactsManager.ClearList : Clear contacts list
DateTime: 2014.01.02
Arguments: None
Result: None
-------------------------------------------------------------------------------}
procedure TContactsManager.ClearList;
var i : integer;
wContact : PContactData;
begin
for i := fContactsList.Count -1 downto 0 do // for all contacts
begin
wContact := fContactsList[i];
Dispose(wContact); // free contact memory
fContactsList.Delete(i); // Delete contact entry
end;
end;
{-------------------------------------------------------------------------------
Procedure: TContactsManager.Create
DateTime: 2014.01.02
Arguments: None
Result: None
-------------------------------------------------------------------------------}
constructor TContactsManager.Create;
begin
fContactsList := TList.Create; // Create contact ilst object
end;
{-------------------------------------------------------------------------------
Procedure: TContactsManager.Destroy
DateTime: 2014.01.02
Arguments: None
Result: None
-------------------------------------------------------------------------------}
destructor TContactsManager.Destroy;
begin
ClearList; // clear contacts list
fContactsList.Free; // destroy contacts list
inherited;
end;
{-------------------------------------------------------------------------------
Procedure: TContactsManager.GetContact
DateTime: 2014.01.02
Arguments: AIndex: Integer
Result: PContactData
-------------------------------------------------------------------------------}
function TContactsManager.GetContact(AIndex: Integer): PContactData;
begin
try
if AIndex > fContactsList.Count -1 then
raise Exception.Create('Index out of bounds');
Result := fContactsList[AIndex] // return contact data from index
except
On E:Exception do
Raise Exception.create('[TContactManager.GetContact] : '+E.message);
end;
end;
{-------------------------------------------------------------------------------
Procedure: TContactsManager.ExtractContactsList : Retrieve all contacts
DateTime: 2014.01.02
Arguments: None
Result: None
-------------------------------------------------------------------------------}
procedure TContactsManager.ExtractContactsList;
var
wUri : JNet_URI;
wCursor : JCursor;
wLookup_Idx : Integer;
wDisplayNameIdx : integer;
wContact : PContactData;
begin
try
ClearList;
wUri := TJContactsContract_Contacts.JavaClass.CONTENT_URI; // Contact URI
with SharedActivity.getContentResolver do
wCursor :=query(wUri,nil, nil,nil, StringToJString('display_name ASC')); // Query to get all contact sorted by displayname
try
wLookup_Idx := wCursor.getColumnIndex(StringToJString('lookup')); //Getting id column index
wDisplayNameIdx := wCursor.getColumnIndex(StringToJString('display_name')); // getting displayname column index
while (wCursor.moveToNext) do // for each row
begin
New(wContact); // Create a new contact record
wContact.LookupID := JStringToString(wCursor.getString(wLookup_Idx)); // Set contact ID
wContact.Display_Name := JStringToString(wCursor.getString(wDisplayNameIdx)); //Set contact displayname
GetContactExtendedData(wContact); // Extract extended data (to get first name, last name, Email, Phone..)
fContactsList.Add(wContact); // Add contact to list
end;
finally
wCursor.close; // Close table cursor
wCursor := nil;
end;
except
On E:Exception do
Raise Exception.create('[GetContactsList] : '+E.message);
end;
end;
{-------------------------------------------------------------------------------
Procedure: TContactsManager.GetContactExtendedData : get additional data for a contact
DateTime: 2014.01.02
Arguments: AContact : PContactData
Result: None
-------------------------------------------------------------------------------}
procedure TContactsManager.GetContactExtendedData(AContact : PContactData);
var
wSubCursor : JCursor;
wfilter : TJavaObjectArray;
wJQueryParams : TJavaObjectArray;
wDataUri : JNet_URI;
begin
try
// Filter to extract only familyname, first name1 and first name 2 (http://developer.android.com/reference/android/provider/ContactsContract.DataColumns.html)
wfilter := TJavaObjectArray.Create(3);
wfilter[0] := TJCommonDataKinds_StructuredName.JavaClass.FAMILY_NAME;
wfilter[1] := TJCommonDataKinds_StructuredName.JavaClass.GIVEN_NAME;
wfilter[2] := TJCommonDataKinds_StructuredName.JavaClass.MIDDLE_NAME;
// Qurey condition (Exrtact only data for specific ID)
wJQueryParams := TJavaObjectArray.Create(2);
wJQueryParams[0] := TJCommonDataKinds_StructuredName.JavaClass.CONTENT_ITEM_TYPE;
wJQueryParams[1] := StringToJString(AContact.LookupID);
wDataUri := TJContactsContract_Data.JavaClass.CONTENT_URI; // Contacts data uri
with SharedActivity.getContentResolver do
wSubCursor := Query(wDataUri,wfilter,StringToJString('mimetype = ? AND lookup = ?') , wJQueryParams,nil); // Exec query
Try
if wSubCursor.getCount > 0 then // if query return some data
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
wSubCursor.moveToNext;
AContact.FamilyName := JStringToString(wSubCursor.getString(0));
AContact.FirstName := JStringToString(wSubCursor.getString(1)) + ' ' + JStringToString(wSubCursor.getString(2));
end;
Finally
wSubCursor.close;
wSubCursor := nil;
End;
// ------------- EMAIL -----------------------------
// Filter to extract Email only
wfilter := TJavaObjectArray.Create(1);
wfilter[0] := TJCommonDataKinds_Email.JavaClass.ADDRESS;
// Qurey condition (Exrtact only data for specific ID)
wJQueryParams := TJavaObjectArray.Create(2);
wJQueryParams[0] := TJCommonDataKinds_Email.JavaClass.CONTENT_ITEM_TYPE;
wJQueryParams[1] := StringToJString(AContact.LookupID);
wDataUri := TJContactsContract_Data.JavaClass.CONTENT_URI; // Contacts data uri
with SharedActivity.getContentResolver do
wSubCursor := Query(wDataUri,wfilter,StringToJString('mimetype = ? AND lookup = ?') , wJQueryParams,nil); // Exec query
Try
if wSubCursor.getCount > 0 then // if query return some data
begin
// Getting only first email , a contact can have many emails, so if needed,
// we need to loop on each row (while (wSubCursor.moveToNext) do)
wSubCursor.moveToNext;
AContact.Email := JStringToString(wSubCursor.getString(0));
end;
Finally
wSubCursor.close;
wSubCursor := nil;
End;
// ------------- PHONE -----------------------------
// Filter to extract Email only
wfilter := TJavaObjectArray.Create(1);
wfilter[0] := TJCommonDataKinds_Phone.JavaClass.NUMBER;
// Qurey condition (Exrtact only data for specific ID)
wJQueryParams := TJavaObjectArray.Create(2);
wJQueryParams[0] := TJCommonDataKinds_Phone.JavaClass.CONTENT_ITEM_TYPE;
wJQueryParams[1] := StringToJString(AContact.LookupID);
wDataUri := TJContactsContract_Data.JavaClass.CONTENT_URI; // Contacts data uri
with SharedActivity.getContentResolver do
wSubCursor := Query(wDataUri,wfilter,StringToJString('mimetype = ? AND lookup = ?') , wJQueryParams,nil); // Exec query
Try
if wSubCursor.getCount > 0 then // if query return some data
begin
// Getting only first phone number , a contact can have multiple phone numbers, so if needed,
// we need to loop on each row (while (wSubCursor.moveToNext) do)
wSubCursor.moveToNext;
AContact.Phone := JStringToString(wSubCursor.getString(0));
end;
Finally
wSubCursor.close;
wSubCursor := nil;
End;
except
On E:Exception do
Raise Exception.create('[TContactsManager.GetContactExtendedData] : '+E.message);
end;
end;
{-------------------------------------------------------------------------------
Procedure: TContactsManager.GetContactsCount
DateTime: 2014.01.02
Arguments: None
Result: integer
-------------------------------------------------------------------------------}
function TContactsManager.GetContactsCount: integer;
begin
Result := fContactsList.Count;
end;
end.
Para ver los contactos tendríamos que poner un ListBox (para mostrar la lista de nuestros contactos) y un tMemo para ver la información de cada uno de ellos.
En el evento OnClic del ListBox tendríamos:
const
wCRLF = #13#10;
begin
if LstContacts.ItemIndex <> -1 then
begin
with fContactsManager do
begin
lbcontactDetails.Text := wCRLF+
'ID : ' + Contacts[LstContacts.ItemIndex].LookupID + wCRLF+
'Family Name : ' + Contacts[LstContacts.ItemIndex].FamilyName + wCRLF+
'First Name : ' + Contacts[LstContacts.ItemIndex].FirstName + wCRLF+
'Email : ' + Contacts[LstContacts.ItemIndex].Email + wCRLF+
'Phone : ' + Contacts[LstContacts.ItemIndex].Phone;
end;
end;
end;
Y en el OnCreate del Form lo siguiente:
procedure TForm2.FormCreate(Sender: TObject);
var i : integer;
begin
fContactsManager := TContactsManager.Create;
fContactsManager.ExtractContactsList;
lbContactsList.Text := Format('Contacts list (%d)',[fContactsManager.ContactsCount]);
LstContacts.BeginUpdate;
try
for i := 0 to fContactsManager.ContactsCount -1 do
begin
LstContacts.Items.Add(fContactsManager.Contacts[i].Display_Name);
end;
finally
LstContacts.EndUpdate;
end;
end;
Link de descarga
Fuente: http://www.fmxexpress.com/access-android-contacts-manager-with-firemonkey-in-delphi-xe5/
No hay comentarios:
Publicar un comentario