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 : TJavaObjectArrayPara 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.; 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.
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/