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

Filippo

Expert
Licensed User
This is a log-file created by "printCursor(crsr)"
B4X:
name: Fili 1
number: 123456789
emails: null
_id: 0
***************
name: Fili 2
number: 987654321
emails: null
_id: 1
***************
name: Fili 1
number: 123456789
emails: null
_id: 0
***************
name: Fili 2
number: 987654321
emails: null
_id: 1
***************
 

Filippo

Expert
Licensed User
I have started my new smartphone and now everything works, thank you. :)
 

Filippo

Expert
Licensed User
Hi Erel,

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

B4X:
        values.Initialize
        values.PutLong("_id", rawContactId)
        values.PutString("tag", kontakt1.DisplayName)
        values.PutString("number", kontakt1.Number)
        cr.Insert(simUri, values)
How to modify a SIM contact?

I tried with this code so far but it does not work.
B4X:
        values.Initialize
        values.PutString("number", kontakt1.Number)
        'SetData("vnd.android.cursor.item/phone_v2", values, rawContactId, True)
        cr.Update(simUri, values, "mimetype = ? AND _id = ?", Array As String("vnd.android.cursor.item/phone", rawContactId))
       
        values.Initialize
        values.PutString("tag", kontakt1.DisplayName)
        'SetData("vnd.android.cursor.item/name", values, rawContactId, True)
        cr.Update(simUri, values, "mimetype = ? AND _id = ?", Array As String("vnd.android.cursor.item/name", rawContactId))
 

DKCERT

Member
Licensed User
It will set the current notes field. You can modify the code in ContactsUtils to add a new note (if multiple notes are supported).
Erel; Could you please throw an AddNote sub together. Mine eighter updates all Notes or only leaves the first one (deletes all others).

Btw: This a version of GetNote(s) that steps through all Notes and returns them as a List:

B4X:
Public Sub GetNotes(id As Long) As List
    Dim nl As List
    nl.Initialize
    For Each obj() As Object In GetData("vnd.android.cursor.item/note", Array As String("data1"), id, Null)
        If obj(0) <> "" Then nl.Add(obj(0))
    Next
    Return nl
End Sub
 

DKCERT

Member
Licensed User
@DKCERT, have you tried to set the last parameter in SetNote sub to False?
Yes I have. It results in an exception (this is the Sub):

B4X:
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
...
...
Sub lstContacts_ItemLongClick (Position As Int, Value As Object)
    Dim c As cuContact = Value
    cu.AddNote(c.Id, "New Note")
    'update the text
    lstContacts_ItemClick(Position, Value)
End Sub
B4X:
contactsutils_setdata (java line: 685)
java.lang.IllegalArgumentException: Invalid column name_raw_contact_id
  at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:144)
  at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:114)
  at android.content.ContentProviderProxy.bulkQueryInternal(ContentProviderNative.java:398)
  at android.content.ContentProviderProxy.query(ContentProviderNative.java:439)
  at android.content.ContentResolver.query(ContentResolver.java:264)
  at anywheresoftware.b4a.objects.ContentResolverWrapper.Query(ContentResolverWrapper.java:43)
  at testapp.contactsutils._setdata(contactutils.java:685)
  at testapp.contactsutils._addnote(contactutils.java:96)
  at testapp.contactsutils.main._lstcontacts_itemlongclick(main.java:384)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:507)
  at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
  at anywheresoftware.b4a.BA$2.run(BA.java:272)
  at android.os.Handler.handleCallback(Handler.java:587)
  at android.os.Handler.dispatchMessage(Handler.java:92)
  at android.os.Looper.loop(Looper.java:150)
  at android.app.ActivityThread.main(ActivityThread.java:4385)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:507)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
  at dalvik.system.NativeStart.main(Native Method)
java.lang.IllegalArgumentException: Invalid column name_raw_contact_id
I hope this helps?
 

Filippo

Expert
Licensed User
I tried it that way, but unfortunately it does not work. :(
B4X:
        values.Initialize
        values.PutString("number", kontakt1.Number)
        Log(cr.Update(simUri, values, "_id = ?", Array As String(rawContactId)) )
       
        values.Initialize
        values.PutString("tag", kontakt1.DisplayName)
        Log(cr.Update(simUri, values, "_id = ?", Array As String(rawContactId)) )
Maybe you have an idea again?
 

Erel

Administrator
Staff member
Licensed User
@DKCERT, I tried this code and it worked fine:
B4X:
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
Maybe there is a problem somewhere else in your code.

Sorry Filippo. Not sure why it doesn't work. Try to find a Java solution. It should be simple to convert it.
 

DKCERT

Member
Licensed User
@DKCERT, I tried this code and it worked fine:
B4X:
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
Maybe there is a problem somewhere else in your code.
Hi Erel, I'm actually using your demo code for ContactsUtils as my test platform :)
How do you test the code and on what device(s)? It fails on my test device: HTC Desire S (v/2.3.5 - API 10).
Reason for asking is I stumbled on these ones: https://code.google.com/p/android/issues/detail?id=11619 from http://stackoverflow.com/questions/...ntract-contact-missing-constants-from-the-api
Anyway, the Desire allows adding Notes to the given Contact - so it is of course possible. Any ideas?
 

thedesolatesoul

Expert
Licensed User
@DKCERT from your logs its seems you made some modifications to your class?
It cannot find name_raw_contact_id in contactUri. See here: http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html
It should be there, I dont understand how you get that exception unless your device doesnt have that feature or you changed the uri. Try testing on the emulator as well with a different android version.

@Filippo are you sure you need to pass the raw contact id rather than the contact_id when doing a modify? Do you have documentation for the simUri and its fields?
 

Filippo

Expert
Licensed User

DKCERT

Member
Licensed User
@DKCERT from your logs its seems you made some modifications to your class?
It cannot find name_raw_contact_id in contactUri. See here: http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html
It should be there, I dont understand how you get that exception unless your device doesnt have that feature or you changed the uri. Try testing on the emulator as well with a different android version.
Well... modifications... I added AddNote (Update As Boolean -> False) and GetNotes (loops through all notes) and AddPhoto2 to the class. The "name_raw_contact_id" param is from the SetData sub in ContactsUtils v/1.05:

B4X:
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
The emulator fails as well (using API level 8 -> Android v/2.2). So does the physical HTC Desire S (API level 10 -> Android 2.3.5).
 

Filippo

Expert
Licensed User
I have found the solution.

With this code you can change a SIM-contact:

B4X:
    Dim cr As ContentResolver
    Dim values As ContentValues

    values.Initialize
    values.PutString("tag", old_DisplayName)
    values.PutString("number", old_Number)
    values.PutString("newTag", new_DisplayName)
    values.PutString("newNumber", new_Number)
   
    cr.Update(simUri, values, Null, Null)
 

DKCERT

Member
Licensed User
@DKCERT I tested it with Nexus 4. Seems like your device misses this column.

The purpose of this column is to find the primary raw_contact_id from the aggregated contact. If you like you can check which other columns are available and see whether there is an alternative way to find the raw_contact_id.
The emulator fails as well (using API level 8 -> Android v/2.2). So does the physical HTC Desire S (API level 10 -> Android 2.3.5).
Well... I somehow hoped you could help me there ;) As the SDK also fails you properly have the right tools to pin down this issue!?
 

shaffnert03

Member
Licensed User
Is it possible for me to add birthday to what this library can pull? And if so, any advice on where I'd start?
 
Top