B4A=true Group=Default Group ModulesStructureVersion=1 Type=Class Version=6 @EndOfDesignText@ 'version: 1.20 'Class module Sub Class_Globals Type cuContact (Id As Long, DisplayName As String, FirstName As String, LastName As String) Type cuEmail (Id As Long, Email As String, EmailType As String) Type cuNote (Id As Long, Note As String) Type cuPhone (Id As Long, Number As String, PhoneType As String) Type cuPhoto (Id As Long, Photo As String) Type cuAddress (Street As String, Neighborhood As String, City As String, PostCode As String, AddressType As String, RawAddress As String) Type cuEvent (DateString As String, EventType As String) Type cuOrganization (Company As String, Title As String) Private mailTypes, phoneTypes, eventTypes, addressTypes As Map Private cr As ContentResolver Private dataUri, contactUri, rawContactUri As Uri Private GroupSources, GroupSourcesByName, GroupRows, GroupRowsByName As Map End Sub Public Sub Initialize dataUri.Parse("content://com.android.contacts/data") contactUri.Parse("content://com.android.contacts/contacts") rawContactUri.Parse("content://com.android.contacts/raw_contacts") cr.Initialize("cr") mailTypes.Initialize mailTypes.Put("1", "home") mailTypes.Put("2", "work") mailTypes.Put("3", "other") mailTypes.Put("4", "mobile") phoneTypes.Initialize phoneTypes.Put("1", "home") phoneTypes.Put("2", "mobile") phoneTypes.Put("3", "work") phoneTypes.Put("4", "fax_work") phoneTypes.Put("5", "fax_home") phoneTypes.Put("6", "pager") phoneTypes.Put("7", "other") phoneTypes.Put("8", "callback") phoneTypes.Put("9", "car") phoneTypes.Put("10", "company_main") phoneTypes.Put("11", "isdn") phoneTypes.Put("12", "main") phoneTypes.Put("13", "other_fax") phoneTypes.Put("14", "radio") phoneTypes.Put("15", "telex") phoneTypes.Put("16", "tty_tdd") phoneTypes.Put("17", "work_mobile") phoneTypes.Put("18", "work_pager") phoneTypes.Put("19", "assistant") phoneTypes.Put("20", "mms") addressTypes.Initialize addressTypes.Put("1", "home") addressTypes.Put("2", "work") addressTypes.Put("3", "other") addressTypes.Put("4", "custom") eventTypes.Initialize eventTypes.Put("1", "anniversary") eventTypes.Put("2", "other") eventTypes.Put("3", "birthday") End Sub '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. Public Sub FindContactsByName(Name As String, Exact As Boolean, VisibleOnly As Boolean) As List Return FindContactsIdFromData("name", "data1", Name, "=", Exact, VisibleOnly,"") End Sub 'Similar to FindContactsByName. Finds contacts based on the mail address. Public Sub FindContactsByMail(Mail As String, Exact As Boolean, VisibleOnly As Boolean) As List Return FindContactsIdFromData("email_v2", "data1", Mail, "=", Exact, VisibleOnly,"") End Sub 'Similar to FindContactsByName. Finds contacts based on the notes field. Public Sub FindContactsByNotes(Note As String, Exact As Boolean, VisibleOnly As Boolean) As List Return FindContactsIdFromData("note", "data1", Note, "=", Exact, VisibleOnly,"") End Sub 'Similar to FindContactsByName. Finds contacts based on the phone number. Public Sub FindContactsByPhone(PhoneNumber As String, Exact As Boolean, VisibleOnly As Boolean) As List Return FindContactsIdFromData("phone_v2", "data1", PhoneNumber, "=", Exact, VisibleOnly,"") End Sub 'Returns the starred contacts. Public Sub FindContactsByStarred(Starred As Boolean) As List Dim value As String = IIf(Starred,"1","0") Return FindContactsIdFromData("name", "starred", value,"=", True, True,"") End Sub 'Returns all contacts. Public Sub FindAllContacts(VisibleOnly As Boolean, Sort As String) As List Return FindContactsIdFromData("name", "data1", "null", "<>", True, VisibleOnly,Sort) End Sub 'Returns all contacts with a photo. Public Sub FindContactsWithPhotos As List Return FindContactsIdFromData("photo", "data15", "null", "<>", True, False,"") End Sub 'Returns all contacts that are member of the specified group ID. Public Sub FindContactsByGroupRowId(gid As Int, VisibleOnly As Boolean) As List Dim projCols() As String = Array As String("contact_id", "display_name") Return FindContactsIdFromData2("vnd.android.cursor.item/group_membership", "data1", gid, "=", True, VisibleOnly, projCols) End Sub 'Returns all contacts that are member of a specified group name (part) Public Sub FindContactsByGroupName(gname As String, VisibleOnly As Boolean) As List Dim l As List l.Initialize FillGroupSources gname = gname.ToLowerCase For Each k As String In GroupRowsByName.Keys ' Search of the group as part of the key If k.ToLowerCase.Contains(gname) Then gname = k Next If Not(GroupRowsByName.ContainsKey(gname)) Then Return l ' Return an empty list Dim i As Int If IsNumber(GroupRowsByName.Get(gname)) Then i = GroupRowsByName.Get(gname) Else Try i = Bit.ParseInt(GroupRowsByName.Get(gname), 16) Catch Return l End Try End If Return FindContactsByGroupRowId(i, VisibleOnly) End Sub Private Sub FindContactsIdFromData (Mime As String, DataColumn As String, Value As String, Operator As String, _ Exact As Boolean, VisibleOnly As Boolean, SortColumn As String) 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(dataUri, Array As String("contact_id", "data1","data2","data3"), selection, _ Array As String("vnd.android.cursor.item/"&Mime, Value), SortColumn) Dim res As List res.Initialize Dim m As Map m.Initialize For i = 0 To crsr.RowCount - 1 crsr.Position = i Dim Id As Long = crsr.GetLong("contact_id") If m.ContainsKey(Id) Then Continue ' It returns first mail or phone for a contact m.Put(Id, Null) Select Mime Case "email_v2" Dim mail As cuEmail mail.Initialize mail.Id = Id mail.Email = crsr.GetString2(1) mail.EmailType = mailTypes.Get(crsr.GetString2(2)) res.Add(mail) Case "note" Dim note As cuNote note.Initialize note.Id = Id note.Note = crsr.GetString2(1) res.Add(note) Case "phone_v2" Dim phon As cuPhone phon.Initialize phon.Id = Id phon.Number = crsr.GetString2(1) phon.PhoneType = phoneTypes.Get(crsr.GetString2(2)) res.Add(phon) Case "photo" Dim phot As cuPhoto phot.Initialize phot.Id = Id phot.Photo = crsr.GetString2(1) res.Add(phot) Case Else Dim c As cuContact c.Initialize c.Id = Id c.DisplayName = crsr.GetString2(1) c.FirstName = IIf(crsr.GetString2(2)<>Null,crsr.GetString2(2),"") c.LastName = IIf(crsr.GetString2(3)<>Null,crsr.GetString2(3),"") res.Add(c) End Select Next crsr.Close Return res End Sub ' Like FindContactsIdFromData, but the 'projection' columns are specified by the caller Private Sub FindContactsIdFromData2(Mime As String, DataColumn As String, Value As String, Operator As String, _ Exact As Boolean, VisibleOnly As Boolean, projectionColumns() As String) 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(dataUri, projectionColumns, selection, Array As String(Mime, Value), "display_name") Dim res As List res.Initialize Dim m As Map m.Initialize For i = 0 To crsr.RowCount - 1 crsr.Position = i Dim Id As Long = crsr.GetLong("contact_id") If m.ContainsKey(Id) Then Continue Dim cu As cuContact = GetNames(Id) m.Put(cu.Id, Null) res.Add(cu) Next crsr.Close Return res End Sub Private Sub FillGroupSources ' WM - added processing for GroupSourcesByName, GroupRows, GroupRowsByName If GroupSources.IsInitialized = False Then GroupSources.Initialize GroupSourcesByName.Initialize GroupRows.Initialize GroupRowsByName.Initialize Dim gu As Uri gu.Parse("content://com.android.contacts/groups") Dim c As Cursor = cr.Query(gu, Array As String("_id", "sourceid", "title"), "", Null, "") For i = 0 To c.RowCount - 1 c.Position = i GroupSources.Put(c.GetString("sourceid"), c.GetString("title")) GroupSourcesByName.Put(c.GetString("title").ToLowerCase, c.GetString("sourceid")) ' Note: title is downshifted to make it easier to look up values in the map GroupRows.Put(c.GetString("_id"), c.GetString("title")) GroupRowsByName.Put(c.GetString("title").ToLowerCase, c.GetString("_id")) ' Note: title is downshifted to make it easier to look up values in the map Next End If End Sub '************************************************************************************************************************************************* ' GET Functions '************************************************************************************************************************************************* Private Sub GetData(Mime As String, DataColumns() As String, Id As Long, Blobs() As Boolean) As List Dim crsr As Cursor = cr.Query(dataUri, DataColumns, "mimetype = ? AND contact_id = ?", Array As String(Mime, Id), "") Dim res As List res.Initialize For i = 0 To crsr.RowCount - 1 crsr.Position = i Dim row(DataColumns.Length) As Object For c = 0 To DataColumns.Length - 1 If Blobs <> Null And Blobs(c) = True Then row(c) = crsr.GetBlob2(c) Else row(c) = crsr.GetString2(c) End If Next res.Add(row) Next crsr.Close Return res End Sub 'Small utility to find the type integer value from the type name Private Sub GetKeyFromValue(m As Map, v As String, defaultValue As Int) As Int Dim t As Int = defaultValue For i = 0 To m.Size - 1 If m.GetValueAt(i) = v Then t = m.GetKeyAt(i) Exit End If Next Return t End Sub 'Returns a Map. The keys are the account names and the values are the account types. Public Sub GetAccounts(Id As Long) As Map Dim uri As Uri uri.Parse("content://com.android.contacts/contacts/" & Id & "/entities") Dim c As Cursor = cr.Query(uri, Array As String("account_name", "account_type"), "", Null, "") Dim m As Map m.Initialize For i = 0 To c.RowCount - 1 c.Position = i m.Put(c.GetString("account_name"), c.GetString("account_type")) Next c.Close Return m End Sub Public Sub GetAccount2(Id As Long) As String Dim crsr As Cursor = cr.Query(dataUri, Array As String("account_name", "account_type"), "_id = ?", Array As String(Id), ""), res As String = "" If crsr.RowCount > 0 Then crsr.Position = 0 res = crsr.GetString("account_name") & ":" & crsr.GetString("account_type") End If crsr.Close Return res End Sub 'Returns a List with cuAddress items. Public Sub GetAddresses(Id As Long) As List Dim res As List res.Initialize For Each obj() As Object In GetData("vnd.android.cursor.item/postal-address_v2", Array As String("data1", "data2", "data4","data6","data7","data9"), Id, Null) Dim a As cuAddress a.Initialize a.RawAddress = obj(0) a.AddressType = addressTypes.Get(obj(1)) a.Street = IIf(obj(2)<>Null,obj(2),"") a.Neighborhood = IIf(obj(3)<>Null,obj(3),"") a.City = IIf(obj(4)<>Null,obj(4),"") a.PostCode = IIf(obj(5)<>Null,obj(5),"") res.Add(a) Next Return res End Sub 'Returns a List with cuEmail items. Public Sub GetEmails(Id As Long) As List Dim res As List res.Initialize For Each obj() As Object In GetData("vnd.android.cursor.item/email_v2", Array As String("data1", "data2"), Id, Null) Dim e As cuEmail e.Initialize e.Id = Id e.Email = obj(0) e.EmailType = mailTypes.Get(obj(1)) res.Add(e) Next Return res End Sub 'Returns a List with cuEvents items. Public Sub GetEvents(Id As Long) As List Dim res As List res.Initialize For Each obj() As Object In GetData("vnd.android.cursor.item/contact_event", Array As String("data1", "data2"), Id, Null) Dim e As cuEvent e.Initialize e.DateString = obj(0) e.EventType = eventTypes.Get(obj(1)) res.Add(e) Next Return res End Sub 'Returns a List of groups Public Sub GetGroups(Id As Long) As List FillGroupSources Dim uri As Uri uri.Parse("content://com.android.contacts/contacts/" & Id & "/entities") Dim c As Cursor = cr.Query(uri, Array As String("group_sourceid"), "", Null, "") Dim groups As List groups.Initialize For i = 0 To c.RowCount - 1 c.Position = i If c.GetString("group_sourceid") <> Null Then Dim source As String = c.GetString("group_sourceid") If GroupSources.ContainsKey(source) Then groups.Add(GroupSources.Get(source)) End If Next c.Close Return groups End Sub 'Returns the names fields. Public Sub GetNames(id As Long) As cuContact Dim names As List = GetData("vnd.android.cursor.item/name", Array As String("data1", "data2","data3"), id, Null) Dim c As cuContact If names.Size > 0 Then c.Initialize Dim obj() As Object = names.Get(0) c.Id = id c.DisplayName = obj(0) c.Firstname = IIf(obj(1)<>Null,obj(1),"") c.LastName = IIf(obj(2)<>Null,obj(2),"") End If Return c End Sub 'Returns the note field. Public Sub GetNote(id As Long) As String Dim raw As List = GetData("vnd.android.cursor.item/note", Array As String("data1"), id, Null) If raw.Size = 0 Then Return "" Dim obj() As Object = raw.Get(0) Return IIf(obj(0)<>Null,obj(0),"") End Sub 'Returns the Organization fields (company and title) Public Sub GetOrganization(Id As Long) As cuOrganization Dim organizations As List = GetData("vnd.android.cursor.item/organization", Array As String("data1", "data4"), _ Id, Null) Dim o As cuOrganization If organizations.Size > 0 Then o.Initialize Dim obj() As Object = organizations.Get(0) o.Company = IIf(obj(0)<>Null,obj(0),"") o.Title = IIf(obj(1)<>Null,obj(1),"") End If Return o End Sub 'Returns a List with cuPhone items. Public Sub GetPhones(Id As Long) As List Dim r As List r.Initialize For Each obj() As Object In GetData("vnd.android.cursor.item/phone_v2", Array As String("data1", "data2"), Id, Null) Dim p As cuPhone p.Initialize p.Number = IIf(obj(0)<>Null,obj(0),"") p.PhoneType = phoneTypes.Get(obj(1)) r.Add(p) Next Return r End Sub '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 If raw.Size > 0 Then Dim obj() As Object = raw.Get(0) 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 End If Return bmp End Sub 'Gets whether the contact is "starred". Public Sub GetStarred(Id As Long) As Boolean Dim crsr As Cursor = cr.Query(contactUri, Array As String("starred"), "_id = ?", Array As String(Id), "") crsr.Position = 0 Dim starred As Boolean = crsr.GetInt("starred") = 1 crsr.Close Return starred End Sub '************************************************************************************************************************************************* ' SET Functions '************************************************************************************************************************************************* Private Sub SetData(Mime As String, Values As ContentValues, Id As Long, Update As Boolean) If Update Then cr.Update(dataUri, Values, "mimetype = ? AND contact_id = ?", Array As String(Mime, Id)) Else Dim crsr As Cursor = cr.Query(contactUri, Array As String("name_raw_contact_id"),"_id = ?", Array As String(Id), "") If crsr.RowCount = 0 Then Log("Error getting raw_contact_id") crsr.Close Return End If crsr.Position = 0 Values.PutString("raw_contact_id", crsr.GetString("name_raw_contact_id")) crsr.Close Values.PutString("mimetype", Mime) cr.Insert(dataUri, Values) End If End Sub Private Sub SetData2(Mime As String, Values As ContentValues, Data1 As String, Id As Long) cr.Update(dataUri, Values, "mimetype = ? AND contact_id = ? AND data1 = ?", Array As String(Mime, Id, Data1)) End Sub ' Sets an structured postal address for a contact. Public Sub SetAddress(Id As Long, Address As cuAddress, RawOld As String) Dim v As ContentValues v.Initialize v.PutInteger("data2", GetKeyFromValue(addressTypes, Address.AddressType, 2)) v.PutString("data4", Address.Street) v.PutString("data6", Address.Neighborhood) v.PutString("data7", Address.City) v.PutString("data9", Address.PostCode) SetData2("vnd.android.cursor.item/postal-address_v2", v, RawOld, Id) End Sub ' Sets an existing contact's DisplayName. Public Sub SetDisplayName(Id As Long, DisplayName As String) Dim cv As ContentValues cv.Initialize cv.PutString("data1", DisplayName) SetData("vnd.android.cursor.item/name", cv, Id, True) End Sub 'Sets an existing event field to the given contact id Public Sub SetEvent(Id As Long, DateString As String, EventType As String) Dim v As ContentValues If DateString.Contains("/") Then DateString = Regex.Replace("(..)/(..)/(....)",DateString,"$3-$2-$1") v.Initialize v.PutString("data1", DateString) v.PutInteger("data2", GetKeyFromValue(eventTypes, EventType, 2)) SetData("vnd.android.cursor.item/contact_event", v, Id, True) End Sub 'Sets firstname or lastname to the given contact id Public Sub SetName(Id As Long, Name As String, TypeName As String) Dim cv As ContentValues cv.Initialize cv.PutString("data"&IIf(TypeName.ToLowerCase="firstname","2","3"), Name) SetData("vnd.android.cursor.item/name", cv, Id, True) End Sub 'Sets firstname, lastname and display_name to the given contact id Public Sub SetNames(Id As Long, c As cuContact) Dim cv As ContentValues cv.Initialize cv.PutString("data2",c.FirstName) cv.PutString("data3",c.LastName) cv.PutString("data1",c.DisplayName) SetData("vnd.android.cursor.item/name", cv, Id, True) End Sub 'Sets the note field of the given id. Public Sub SetNote(Id As Long, Note As String) Dim v As ContentValues v.Initialize v.PutString("data1", Note) SetData("vnd.android.cursor.item/note", v, Id, True) End Sub 'Sets/Add/Delete the organization fields of the given id Public Sub SetOrganization(Id As Long, Organization As cuOrganization, Update As Boolean) Dim v As ContentValues, Mime As String = "vnd.android.cursor.item/organization" v.Initialize If (Organization.Company&Organization.Title).trim<>"" Then v.PutString("data1",Organization.Company) v.PutString("data4",Organization.Title) SetData(Mime,v,Id,Update) Else cr.Delete(dataUri, "mimetype = ? AND contact_id = ?", Array As String(Mime, Id)) End If End Sub 'Sets a phone field to the given contact id. Public Sub SetPhone(Id As Long, New As String, PhoneType As String, Old As String) Dim v As ContentValues, t As Int = GetKeyFromValue(phoneTypes, PhoneType, 2) v.Initialize v.PutString("data1", New) v.PutInteger("data2", t) 'Default=mobile SetData2("vnd.android.cursor.item/phone_v2", v, Old , Id) End Sub 'Sets the starred state of the given id. Public Sub SetStarred (Id As Long, Starred As Boolean) Dim cv As ContentValues cv.Initialize cv.PutBoolean("starred", Starred) cr.Update(contactUri, cv, "_id = ?", Array As String(Id)) End Sub '************************************************************************************************************************************************** ' DELETE Functions '************************************************************************************************************************************************** Private Sub DeleteData(Mime As String, Data1 As String, Id As Long) cr.Delete(dataUri, "mimetype = ? AND data1 = ? AND contact_id = ?", Array As String(Mime, Data1, Id)) End Sub Private Sub DeleteData2(Mime As String, Data2 As Int, Id As Long) cr.Delete(dataUri, "mimetype = ? AND data2 = ? AND contact_id = ?", Array As String(Mime, Data2, Id)) End Sub 'Delete the given address of the given type Public Sub DeleteAddress(Id As Long,RawAddress As String) DeleteData("vnd.android.cursor.item/postal-address_v2",RawAddress, Id) End Sub Public Sub DeleteAddressByType(Id As Long, AddressType As String) 'Log("2Del:"&RawAddress.Replace(CRLF,"|")&"<") 'Dim c As Cursor = cr.Query(dataUri, Array As String("data1"),"mimetype = ? AND contact_id = ?", Array As String("vnd.android.cursor.item/postal-address_v2" ,Id), "") 'For i = 0 To c.RowCount - 1 ' c.Position = i ' Log("Read:"&c.GetString("data1").Replace(CRLF,"|")&"<") 'Next Dim Data2 As Int = GetKeyFromValue(addressTypes, AddressType, 99) 'if not recognize, no deletion of default ! DeleteData2("vnd.android.cursor.item/postal-address_v2", Data2, Id) End Sub 'Deletes the contact with the given Id. Public Sub DeleteContact(Id As Long) cr.Delete(rawContactUri, "contact_id = ?", Array As String(Id)) End Sub 'Deletes the given email address. Public Sub DeleteEmail(Id As Long, Email As String) DeleteData("vnd.android.cursor.item/email_v2", Email, Id) End Sub 'Deletes the given email address. Public Sub DeleteEmailByType(Id As Long, EmailType As String) Dim Data2 As Int = GetKeyFromValue(mailTypes, EmailType, 99) 'if not recognize, no deletion of default ! DeleteData2("vnd.android.cursor.item/email_v2", Data2, Id) End Sub 'Deletes the given event Public Sub DeleteEvent(Id As Long, Event As String) If Event.Contains("/") Then Event = Regex.Replace("(..)/(..)/(....)",Event,"$3-$2-$1") DeleteData("vnd.android.cursor.item/contact_event", Event, Id) End Sub 'Deletes the given phone number. Public Sub DeletePhone(Id As Long, PhoneNumber As String) DeleteData("vnd.android.cursor.item/phone_v2", PhoneNumber, Id) End Sub Public Sub DeletePhoneByType(Id As Long, PhoneType As String) Dim Data2 As Int = GetKeyFromValue(phoneTypes, PhoneType, 99) 'if not recognize, no deletion of default ! DeleteData2("vnd.android.cursor.item/phone_v2", Data2, Id) End Sub '************************************************************************************************************************************************* ' ADD Functions '************************************************************************************************************************************************* ' Adds an structured postal address for a contact. Public Sub AddAddress(Id As Long, Address As cuAddress) Dim v As ContentValues, t As Int = GetKeyFromValue(addressTypes, Address.AddressType, 2) v.Initialize v.PutInteger("data2", t) v.PutString("data4", Address.Street) v.PutString("data6", Address.Neighborhood) v.PutString("data7", Address.City) v.PutString("data9", Address.PostCode) SetData("vnd.android.cursor.item/postal-address_v2", v, Id, False) End Sub 'Adds an email field to the given contact id. Public Sub AddEmail(Id As Long, Email As String, EmailType As String) Dim v As ContentValues v.Initialize v.PutString("data1", Email) v.PutInteger("data2", GetKeyFromValue(mailTypes, EmailType, 1)) ' Default=home SetData("vnd.android.cursor.item/email_v2", v, Id, False) End Sub 'Adds an event field to the given contact id Public Sub AddEvent(Id As Long, DateString As String, EventType As String) Dim v As ContentValues If DateString.Contains("/") Then DateString = Regex.Replace("(..)/(..)/(....)",DateString,"$3-$2-$1") v.Initialize v.PutString("data1", DateString) v.PutInteger("data2", GetKeyFromValue(eventTypes, EventType, 2)) SetData("vnd.android.cursor.item/contact_event", v, Id, False) End Sub 'Adds a group to the givien contact id Public Sub AddGroup(Id As Long, GroupId As String) Dim uri As Uri, v As ContentValues uri.Parse("content://com.android.contacts/contacts/" & Id & "/entities") v.initialize v.PutString("group_sourceid",GroupId) cr.Insert(uri,v) End Sub 'Adds a Note to the given contact id Public Sub AddNote(Id As Long, Note As String) Dim v As ContentValues v.Initialize v.PutString("data1", Note) SetData("vnd.android.cursor.item/note", v, Id, False) End Sub 'Adds a phone field to the given contact id. Public Sub AddPhone(Id As Long, PhoneNumber As String, PhoneType As String) Dim v As ContentValues, t As Int = GetKeyFromValue(phoneTypes, PhoneType, 2) v.Initialize v.PutString("data1", PhoneNumber) v.PutInteger("data2", t) 'Default=mobile SetData("vnd.android.cursor.item/phone_v2", v, Id, False) End Sub 'Inserts a new contact and returns the cuContact object of this contact. Public Sub CreateContact(Name As String, AccountName As String, AccountType As String) As cuContact Dim values As ContentValues values.Initialize If AccountName <> "" Then values.PutString("account_name",AccountName) Else values.PutNull("account_name") If AccountType <> "" Then values.PutString("account_type",AccountType) Else values.PutNull("account_type") Dim rawUri As Uri = cr.Insert(rawContactUri, values) Dim rawContactId As Long = rawUri.ParseId values.Initialize values.PutLong("raw_contact_id", rawContactId) values.PutString("mimetype", "vnd.android.cursor.item/name") values.PutString("data1", Name) cr.Insert(dataUri, values) Dim cu As cuContact cu.Initialize Dim crsr As Cursor = cr.Query(dataUri, Array As String("contact_id", "display_name"), "raw_contact_id = ?", Array As String(rawContactId), "") crsr.Position = 0 cu.DisplayName = crsr.GetString("display_name") cu.Id = crsr.GetLong("contact_id") Return cu End Sub 'useful for debugging Private Sub printCursor(c As Cursor) 'ignore For r = 0 To c.RowCount - 1 c.Position = r For col = 0 To c.ColumnCount - 1 Try Log(c.GetColumnName(col) & ": " & c.GetString2(col)) Catch Log(c.GetColumnName(col) & ": " & LastException) End Try Next Log("***************") Next End Sub