Mobility

Use SQLite to create a contacts browser in Android

William J. Francis walks Android developers through a SQLite tutorial on how to implement a no-frills contacts browser.

Google's Android has strong database support. By default, Android ships with SQLite, a powerful, full-featured, small footprint technology. SQLite is not specific to Android; it's an open source technology that's been around since 2000, and has enjoyed adoption on a number of embedded platforms.

On Android, SQLite provides not just a solid database layer, but also a means of Inter Process Communication (IPC). While processes on Android are generally isolated for security reasons, SQLite, combined with the platform's content provider model, allows applications to share some data in a controlled fashion.

Probably the most straightforward example of using a content provider can be demonstrated using the Contacts list on your device. This tutorial implements a no-frills contacts browser. You can follow along with the step-by-step instructions below or download the entire project and import it into Eclipse.

1. Start a new Android project in Eclipse. Because we are using the later version of the contacts API, you will need to target a minimum of Android 2.0. Be sure you change the name of your startup class to Main.java.

2. To read the contacts list on the device the application will have to get permission at the time of installation. We accomplish this by adding a permission to the AndroidManifest.XML file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.authorwjf.content_provider_browser"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".Main"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

3. Our layout is straightforward; we will need two buttons and a text view nested within a horizontal linear layout. Open /res/layout/main.xml and make the following modifications:

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Contacts API"
android:padding="8dip"
android:gravity="center" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dip"
android:gravity="center" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&lt;="
android:id="@+id/previous" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="contact name"
android:id="@+id/name" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="=&gt;"
android:id="@+id/next" />
</LinearLayout>
</LinearLayout>

4. Move on to our Main.java file. We will start by defining a class level cursor and some supporting functions.

Main.java
package com.authorwjf.content_provider_browser;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Main extends Activity implements OnClickListener {
private Cursor mCursor;
private static final int NEXT = 1;
private static final int PREVIOUS = 2;
private String getContact(int which) {
String result = null;
if (which == NEXT) {
if (mCursor.moveToNext()) {
result = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
} else {
mCursor.moveToLast();
}
} else {
if (mCursor.moveToPrevious()) {
result = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
} else {
mCursor.moveToFirst();
}
}
return result;
}
private void populateField(String name) {
if (name!=null)
((TextView) findViewById(R.id.name)).setText(name);
}

5. Let's add our on create override. This is where we will initialize our global cursor and wire up our buttons.

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ContentResolver cr = getContentResolver();
mCursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (mCursor.moveToFirst()) {
String name = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
populateField(name);
}
((Button) findViewById(R.id.next)).setOnClickListener(this);
((Button) findViewById(R.id.previous)).setOnClickListener(this);
}

6. And speaking of our buttons, we still need a handler.

@Override
public void onClick(View v) {
if (v.getId() == R.id.next) {
populateField(getContact(NEXT));
} else {
populateField(getContact(PREVIOUS));
}
}

7. We need to override the on destroy method so we can clean up our open cursor.

@Override
protected void onDestroy() {
try {
mCursor.close();
} catch (Exception e) {
// ignore
}
super.onDestroy();
}
Now our application is ready. However, if you are running on an emulator, you still need to do one more thing before downloading the app: start the emulator, open the default contacts application, and add the names of a few of your closest friends (Figure A). Figure A

Once you populate a few contacts, launch the demo code and click until your heart is content (Figure B). Figure B

While our sample code is engineered to be as simple as possible, the implications are wide reaching. If this post generates adequate interest, perhaps we can pick up here in a future article and implement our own content provider. Live long and prosper!

About

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

0 comments

Editor's Picks