Thursday, February 28, 2008

Android: Contact photos


Android: Contact photos

You may wonder how you can add photos to your contacts in Android SDK M5. There are at least two very different ways:

  • the correct way
  • the quick and dirty hack way

There's no need to say that the correct way, using Intents didn't work at first, and even we are in an “Open Source” platform, we don't have the sources to check how the Contacts application is shaping its intent to edit the contact's photo.

I've been trying to discover this intent, but no luck yet. More on this later.

So we are destined to the quick and dirty hack.

Contacts database

It's no news that contacts, by default, are stored in a sqlite3 database. I'm putting some emphasis in this because one of the most relevant features of the Android platform is the “All applications are equal” model. So, strictly speaking, Contacts application may have been replaced. However, we will restrict this to the Android default Contacts application, including its ContentProvider. To turn our quest easier, sqlite3 command is provided in the emulator image.

Get a shell to your running emulator using

 $ adb shell

once in the shell

 # sqlite3 /data/data/com.google.android.providers.contacts/databases/contacts.db

There are some tables in this database. We are interested in the people table. If we obtain the schema

CREATE TABLE people (
_id INTEGER PRIMARY KEY,
_sync_account TEXT,
_sync_id TEXT,
_sync_time TEXT,
_sync_version TEXT,
_sync_local_id INTEGER,
_sync_dirty INTEGER,
_sync_mark INTEGER,
name TEXT NOT NULL,
notes TEXT,
photo TEXT,
company TEXT,
title TEXT,
times_contacted INTEGER NOT NULL DEFAULT 0,
last_time_contacted INTEGER,
starred INTEGER NOT NULL DEFAULT 0,
preferred_phone INTEGER REFERENCES phones(_id),
preferred_email INTEGER REFERENCES contact_methods(_id)
);

Obviously, the photo holds the reference to the contact's photo. _id is the unique id of the cont

act.

Photos

We have to store the photos in the filesystem. Let's create a directory to store them.

 # mkdir /data/data/com.google.android.providers.contacts/photos

The push some photos using

 $ adb push <local> <remote>

You can use whatever name you like, but it will be easier if you use the contact unique id to name the photo. We have seen the _id column in the schema before. If you want to verify the ids

 # sqlite3 /data/data/com.google.android.providers.contacts/databases/contacts.db 'select _id,name from people;'

will show something like this

1|Donald Duck
2|Mickey Mouse
3|Pluto
4|Minnie Mouse
5|X


thus, our photos directory should look like this after we transfer the images

-rw-rw-rw-    1 0        0            4625 Feb 27 16:05 1.png
-rw-rw-rw- 1 0 0 4715 Feb 27 16:05 2.png
-rw-rw-rw- 1 0 0 4873 Feb 27 16:05 3.png
-rw-rw-rw- 1 0 0 3085 Feb 27 16:05 4.png

Update the people table

Using sqlite3

# sqlite3 /data/data/com.google.android.providers.contacts/databases/contacts.db
sqlite> UPDATE people SET photo = '/data/data/com.google.android.providers.contacts/photos/' || _id || '.png';

Conclusion

If everything went well, you are now seeing something similar to the previous screenshot. Definitely it's not the way to go, but if you want to provide some photos of your contacts in a quick and dirty way you can do it.

You may say “But wait, what is the correct way ?”

If you touch (or click) the photo while editing a contact you will receive this Unsupported action.

I've tried to receive this Intent to no avail using this intent filter

   <intent-filter>
<action android:name="android.intent.action.GET_CONTENT"/>
<data android:mimeType="image/*"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

but for some reason, it doesn't match. Do you have an idea ? We would like to know.

Post a Comment