Accediendo a la lista de contactos Android



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