B4A Library [class] ContactsUtils - Provides read / write access to the stored contacts

Status
Not open for further replies.
ContactsUtils is a class based on ContentResolver library.

ContactsUtils allows you to read all kinds of information from the device stored contacts and also to modify the information, add new contacts and delete existing contacts.

Most of the methods expect a contact id. You can get this id by calling one of the Find methods. All the Find methods return a List that holds cuContact items.

The cuContact object holds the contact name and id. With that id you can get more information, add or modify existing fields and delete the contact.

Types:
B4X:
Type cuContact (Id As Long, DisplayName As String)
Type cuEmail (Email As String, EmailType As String)
Type cuPhone (Number As String, PhoneType As String)
Type cuEvent (DateString As String, EventType As String)

Public subs:
B4X:
'Returns a List with cuContact items based on the given name.
'Name - Name to look for.
'Exact - Whether to search for the exact name or to search for names that contain the given value.
'VisibleOnly - Whether to return only visible contacts. In most cases there are many invisible contacts.
Public Sub FindContactsByName(Name As String, Exact As Boolean, VisibleOnly As Boolean) As List

'Similar to FindContactsByName. Finds contacts based on the mail address.
Public Sub FindContactsByMail(Mail As String, Exact As Boolean, VisibleOnly As Boolean) As List

'Similar to FindContactsByName. Finds contacts based on the notes field.
Public Sub FindContactsByNotes(Note As String, Exact As Boolean, VisibleOnly As Boolean) As List

'Similar to FindContactsByName. Finds contacts based on the phone number.
Public Sub FindContactsByPhone(PhoneNumber As String, Exact As Boolean, VisibleOnly As Boolean) As List

'Returns the starred contacts.
Public Sub FindContactsByStarred(Starred As Boolean) As List

'Returns all contacts.
Public Sub FindAllContacts(VisibleOnly As Boolean) As List

'Returns all contacts with a photo.
Public Sub FindContactsWithPhotos As List

'Returns a List with cuEmail items.
Public Sub GetEmails(Id As Long) As List

'Returns a List with cuEvents items.
Public Sub GetEvents(Id As Long) As List

'Returns a List with cuPhone items.
Public Sub GetPhones(id As Long) As List

'Returns the note field.
Public Sub GetNote(id As Long) As String

'Returns the thumbnail photo of the given contact. Returns an uninitialized bitmap if no photo is available.
Public Sub GetPhoto(Id As Long) As Bitmap

'Gets whether the contact is "starred".
Public Sub GetStarred(Id As Long) As Boolean

'Sets the note field of the given id.
Public Sub SetNote(Id As Long, Note As String)

'Adds an email field to the given contact id.
'EmailType - One of the email types strings (see Initialize method).
Public Sub AddEmail(Id As Long, Email As String, EmailType As String)

'Adds a phone field to the given contact id.
'PhoneType - One of the phone types strings (see Initialize method).
Public Sub AddPhone(Id As Long, PhoneNumber As String, PhoneType As String)

'Deletes the given phone number.
Public Sub DeletePhone(Id As Long, PhoneNumber As String)

'Deletes the given email address.
Public Sub DeleteEmail(Id As Long,Email As String)

'Sets the starred state of the given id.
Public Sub SetStarred (Id As Long, Starred As Boolean)

'Deletes the contact with the given Id.
Public Sub DeleteContact(Id As Long)

'Inserts a new contact and returns the cuContact object of this contact.
Public Sub InsertContact(Name As String, Phone As String) As cuContact

To use this class you need to add a reference to the ContentResolver and SQL libraries.

The following permissions should be added in the manifest editor:
B4X:
AddPermission("android.permission.READ_CONTACTS")
AddPermission("android.permission.WRITE_CONTACTS") 'if write access is required

It should be pretty simple to extend this class and retrieve or modify other fields based on the existing code.

The attached project, which includes the ContactsUtils class shows a list with the visible contacts. Pressing on a contact will show some details about the contact and its photo. Long pressing on a contact will change its starred state.

V1.20 - Adds GetGroups and GetAccounts methods.
V1.10 - Adds GetEvents method.
V1.05 - Fixes an issue with InsertContact on HTC devices.
 

Attachments

  • ContactsUtils.zip
    11.6 KB · Views: 1,625
Last edited:

bsnqt

Active Member
Licensed User
Longtime User
Dear Erel,

Just a newbie / stupid question, in your example how can i sort by using cu.sort(true)... it does not work as it does not contains string but contacts...
The contacts displayed in the listview (in your example) seems not being in alphabet order... I know that I can add all displaynames (cachedname) to another list and sort it. But can I do it directly with cu (ContactsUtil)?

Thanks a lot.

Best regards,
bsnqt
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can use SortType:
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      cu.Initialize
   End If
   Activity.LoadLayout("1")
   Dim allContacts As List = cu.FindAllContacts(True)
   allContacts.SortType("DisplayName", True)
   For Each c As cuContact In allContacts
      lstContacts.AddSingleLine2(c.DisplayName, c)
   Next
End Sub
 

bsnqt

Active Member
Licensed User
Longtime User
You can use SortType:
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      cu.Initialize
   End If
   Activity.LoadLayout("1")
   Dim allContacts As List = cu.FindAllContacts(True)
   allContacts.SortType("DisplayName", True)
   For Each c As cuContact In allContacts
      lstContacts.AddSingleLine2(c.DisplayName, c)
   Next
End Sub

Oh, ok, I got it, thank you very much. I totally forgot the method "SortType".

Best regards,
bsnqt
 

bsnqt

Active Member
Licensed User
Longtime User
Dear Erel,

Using the ContactUtils it is much and much faster to find & load all Contacts from phone than using Phone and Contacts2 library. Earlier, I did that task with more than 12 sec. (as also reported by other members), now this task is done very quickly, almost immediately or < 1 sec.

However, I still have a problem.

If I want to find a stored Contact name by using the phone number and "FindContactsByPhone", I have to know exactly the phone number that I stored earlier. Let say in the past I stored "003311223344" now if my searching number is "0033-1122-3344", then I cannot find out this Contact.

I am doing anything wrong? How can we eliminate the "phone number format" factor when doing search, as the user can enter (store) every kind of format they want, let say 0033-1122-3344 or (00) 33 1122- 3344 and so on...

B4X:
Sub Button2_Click
    Dim phoneList As List
    phoneList.Initialize
    phoneList = cu.FindContactsByPhone("0033-1122-3344", False, False)
    For i = 0 To phoneList.Size - 1
        ToastMessageShow(phoneList.Get(i), False)
    Next
End Sub
 

bsnqt

Active Member
Licensed User
Longtime User
I thought it is related to ContactUtils but anyway I will start a new thread... Thanks in advance.
 

CapReed

Member
Licensed User
Longtime User
I have noticed that sometimes some contacts do not recover your photos with GetPhoto correctly.

I made this minimal modification in ContactUtils Module to get the picture when this circumstance occurs:

B4X:
'Returns the thumbnail photo of the given contact. Returns an uninitialized bitmap if no photo is available.
Public Sub GetPhoto(Id As Long) As Bitmap
    Dim raw As List = GetData("vnd.android.cursor.item/photo", Array As String("data15"), Id, Array As Boolean(True))
    Dim bmp As Bitmap
    Log("Numero de posibles fotos : " & raw.Size)
    If raw.Size > 0 Then
        For ra =0 To raw.Size-1
            Dim obj() As Object = raw.Get(ra)
            Dim bytes() As Byte = obj(0)
            If bytes <> Null Then
                Dim In As InputStream
                In.InitializeFromBytesArray(bytes, 0, bytes.Length)
                bmp.Initialize2(In)
                In.Close
            End If
        Next
    End If
    Return bmp
End Sub

Hope this helps to some other user with the same situation.
 

peacemaker

Expert
Licensed User
Longtime User
No possibility to update an existing contact (notes field) ?
 

bsnqt

Active Member
Licensed User
Longtime User
I think it is completely possible.

Code from Erel's example project:
B4X:
Sub UpdateNote(Name As String, Note As String)
  Dim u As Uri
  u.Parse("content://com.android.contacts/contacts")
  Dim crsr As Cursor = cr.Query(u, Array As String("_id"), "display_name = ?", Array As String(Name), "")
  If crsr.RowCount = 0 Then
      Log("No match found: " & Name)
  Else
      crsr.Position = 0
      Dim id As Long = crsr.GetLong("_id")
      Dim cv As ContentValues
      cv.Initialize
      cv.PutString("data1", Note)
      Dim dataUri As Uri
      dataUri.Parse("content://com.android.contacts/data")
      Log(cr.Update(dataUri, cv, "mimetype = 'vnd.android.cursor.item/note' AND contact_id = ?", _
        Array As String(id)))
  End If
  crsr.Close
End Sub
 

peacemaker

Expert
Licensed User
Longtime User
Wow ! Great.
But will it update the current Notes, or add ?
I remember in some Android version there were several records for Notes.
 
D

Deleted member 103

Guest
Hi Erel,

with this code I can add address.
B4X:
            values.Initialize
            values.PutLong("raw_contact_id", rawContactId)
            values.PutString("mimetype", "vnd.android.cursor.item/postal-address_v2")
            values.PutInteger("data2", Address.TYP) 'Address type
            values.PutString("data5", Address.POBOX)
            values.PutString("data4", Address.STREET)
            values.PutString("data7", Address.CITY)
            values.PutString("data8", Address.REGION)
            values.PutString("data9", Address.POSTCODE)
            values.PutString("data10", Address.COUNTRY)
            cr.Insert(dataUri, values)

How can I delete an address?
 
D

Deleted member 103

Guest
Hi Erel,

maybe you can help me.
With this code I can read the SIM contacts.

B4X:
Dim simUri As Uri
simUri.Parse("content://icc/adn")

Public Sub FindSIMContacts As List
   Return FindSIMContactsIdFromData("vnd.android.cursor.item/name", "data1", "null", "<>", True, False)
End Sub

Private Sub FindSIMContactsIdFromData (Mime As String, DataColumn As String, Value As String, Operator As String, _
    Exact As Boolean, VisibleOnly As Boolean) As List
    If Not(Exact) Then
        Operator = "LIKE"
        Value = "%" & Value & "%"
    End If
    Dim selection As String = "mimetype = ? AND " & DataColumn & " " & Operator & " ? "
    If VisibleOnly Then selection = selection & " AND in_visible_group = 1"
'    Dim crsr As Cursor = cr.Query(simUri, Array As String("_id", "name"), selection, _
'        Array As String(Mime, Value), "")
    Dim crsr As Cursor = cr.Query(simUri, Null, Null, Null,"")
    Dim res As List
    res.Initialize
    Dim m As Map
    m.Initialize
    For i = 0 To crsr.RowCount - 1
        printCursor(crsr)
        crsr.Position = i
        Dim cu As cuContact
        cu.Initialize
        cu.id = crsr.GetLong("_id")
        cu.DisplayName = crsr.GetString("name")

        If m.ContainsKey(cu.id) Then Continue
       
        Dim p As cuPhone
        Dim lst As List
        lst.Initialize
        p.Number=crsr.GetString("number")
        p.PhoneType=phoneTypes.Get(2)
        lst.Add(p)
        cu.Phonenumber = lst

        m.Put(cu.id, Null)
        res.Add(cu)
    Next
    crsr.Close
    Return res
End Sub

I have on my SIM card exactly 4 contacts(see Appendix), can you tell me why I see only two contacts with my code?
 

Attachments

  • Phone4all_01.png
    Phone4all_01.png
    91.2 KB · Views: 808
  • Phone4all_02.png
    Phone4all_02.png
    96.2 KB · Views: 836
Status
Not open for further replies.
Top