Asynchronously populating listview from SQLite database using Content Providers

August 11, 2012
By

In this article, we will create a contact manager application which facilitates to add, update, delete and list contacts with their name and phone number.

We will make use content providers to access SQLite database in the application. Also the contacts in the listview is populated asynchronously using loaders.

This application is developed in Eclipse (3.7.2) with ADT plugin ( 20.0.2 ) and Android SDK (R20.0.1 )


1. Create a new Android application project titled “SqlSpinnerSmsDemo”

Create a new Android Application Project

Figure 1 : Create a new Android Application Project


2. Design application launcher icon

Design Application Launcher Icon

Figure 2 : Design Application Launcher Icon


3. Create a blank activity

Create a new blank activity

Figure 3 : Create a new blank activity


4. Enter MainActivity details

Enter MainActivity details

Figure 4 : Enter MainActivity details


5. Update the file res/values/strings.xml


<resources>

    <string name="app_name">SqlSpinnerSmsDemo</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">Contacts Manager</string>

    <string name="txt_btn_add">Add</string>
    <string name="txt_btn_edit">Edit</string>
    <string name="txt_btn_del">Delete</string>

    <string name="txt_btn_call">Call</string>
    <string name="txt_btn_sms">SMS</string>

    <string name="hnt_txt_name">Enter your name here </string>
    <string name="hnt_txt_phone">Enter your phone number here</string>

</resources>


6. Update the layout file of the MainActivity in the file res/layout/activity_main.xml


    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:id="@+id/rlayout"
        >
            <Button
                android:id="@+id/btn_add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/txt_btn_add"
            />

            <Button
                android:id="@+id/btn_edit"
                android:layout_toRightOf="@id/btn_add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/txt_btn_edit"
            />

            <Button
                android:id="@+id/btn_del"
                android:layout_toRightOf="@id/btn_edit"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/txt_btn_del"
            />

            <Button
                android:id="@+id/btn_call"
                android:layout_toRightOf="@id/btn_del"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/txt_btn_call"
            />

            <Button
                android:id="@+id/btn_sms"
                android:layout_toRightOf="@id/btn_call"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/txt_btn_sms"
            />
        </RelativeLayout>

        <ListView
            android:id="@+id/lst_contacts"
            android:layout_centerHorizontal="true"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/rlayout"

        />

    </RelativeLayout>

7. Create a layout file for the AlertDialogFragment ( Contact ) screen in the file res/layout/contact.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="match_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/txt_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textCapCharacters"
        android:hint="@string/hnt_txt_name"
    />

    <EditText
        android:id="@+id/txt_phone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="text|phone"
        android:hint="@string/hnt_txt_phone"
    />
</LinearLayout>


8. Create a database helper class to do the operations add, edit, delete and list operations on SQLite database. The path to this file is src/in/wptrafficanalyzer/sqlspinnersmsdemo/ContactsDB.java


package in.wptrafficanalyzer.sqlspinnersmsdemo;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class ContactsDB extends SQLiteOpenHelper{

    /** Database name */
    private static String DBNAME = "sqlspinnersmsdemo";

    /** Version number of the database */
    private static int VERSION = 1;

    /** Field 1 of the table contacts, which is the primary key */
    public static final String KEY_ROW_ID = "_id";

    /** Field 2 of the table contacts, stores the contact name */
    public static final String KEY_NAME = "name";

    /** Field 3 of the table contacts, stores the phone number of the contact */
    public static final String KEY_PHONE = "phone";

    /** A constant, stores the the table name */
    private static final String DATABASE_TABLE = "contacts";

    /** An instance variable for SQLiteDatabase */
    private SQLiteDatabase mDB;

    /** Constructor */
    public ContactsDB(Context context) {
        super(context, DBNAME, null, VERSION);
        this.mDB = getWritableDatabase();
    }

    /** This is a callback method, invoked when the method getReadableDatabase() / getWritableDatabase() is called
     * provided the database does not exists
    * */
    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql =     "create table contacts (_id integer primary key autoincrement , "
        + " name text not null , phone text not null ) " ;
        db.execSQL(sql);
    }

    /** Inserts a new contact to the table contacts */
    public long insert(ContentValues contentValues){
        long rowID = mDB.insert(DATABASE_TABLE, null, contentValues);
        return rowID;
    }

    /** Updates a contact */
    public int update(ContentValues contentValues,String contactID){
        int cnt = mDB.update(DATABASE_TABLE, contentValues, "_id=" + contactID, null);
        return cnt;
    }

    /** Deletes a contact from the table */
    public int del(String contactID){
        int cnt = mDB.delete(DATABASE_TABLE, "_id="+contactID, null);
        return cnt;
    }

    /** Returns all the contacts in the table */
    public Cursor getAllContacts(){
        return mDB.query(DATABASE_TABLE, new String[] { KEY_ROW_ID,  KEY_NAME , KEY_PHONE } , null, null, null, null, KEY_NAME + " asc ");
    }

    /** Returns a contact by passing its id */
    public Cursor getContactByID(String contactID){
        return mDB.query(DATABASE_TABLE, new String[] { KEY_ROW_ID,  KEY_NAME , KEY_PHONE } , "_ID="+contactID, null, null, null, KEY_NAME + " asc ");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}


9. Create a content provider class to do the database operations from the applications. The path to this class file is src/in/wptrafficanalyzer/sqlspinnersmsdemo/ContactsProvider.java


package in.wptrafficanalyzer.sqlspinnersmsdemo;

import java.sql.SQLException;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;

/** A custom Content Provider to do the database operations */
public class ContactsProvider extends ContentProvider{

    public static final String PROVIDER_NAME = "in.wptrafficanalyzer.sqlspinnersmsdemo.contacts";

    /** A uri to do operations on contacts table. A content provider is identified by its uri */
    public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/contacts" );

    /** Constants to identify the requested operation */
    private static final int CONTACTS = 1;
    private static final int CONTACT_ID = 2;

    private static final UriMatcher uriMatcher ;
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(PROVIDER_NAME, "contacts", CONTACTS);
        uriMatcher.addURI(PROVIDER_NAME, "contacts/#", CONTACT_ID);
    }

    /** This content provider does the database operations by this object */
    ContactsDB mContactsDB;

    /** A callback method which is invoked when the content provider is starting up */
    @Override
    public boolean onCreate() {
        mContactsDB = new ContactsDB(getContext());
        return true;
    }

    /** A callback method which is invoked when delete operation is requested on this content provider */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int cnt = 0;
        if(uriMatcher.match(uri)==CONTACT_ID){
            String contactID = uri.getPathSegments().get(1);
            cnt = mContactsDB.del(contactID);
        }
        return cnt;
    }

    @Override
    public String getType(Uri uri) {
         return null;
    }

    /** A callback method which is invoked when insert operation is requested on this content provider */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        long rowID = mContactsDB.insert(values);
        Uri _uri=null;
        if(rowID>0){
            _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
        }else {
            try {
                throw new SQLException("Failed to insert : " + uri);
            }catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return _uri;

    }

    /** A callback method which is by the default content uri */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        if(uriMatcher.match(uri)==CONTACTS){
            return mContactsDB.getAllContacts();
        }else{
            String contactID = uri.getPathSegments().get(1);
            return mContactsDB.getContactByID(contactID);
        }
    }

    /** A callback method which is invoked when update operation is requested on this content provider */
    @Override
    public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
        int cnt = 0;
        if(uriMatcher.match(uri)==CONTACT_ID){
            String contactID = uri.getPathSegments().get(1);
            cnt = mContactsDB.update(contentValues, contactID);
        }
        return cnt;
    }
}


10. Create an alert dialog fragment class namely Contact to provide interface for Add, Edit and Delete operations. The path to this class file is src/in/wptrafficanalyzer/sqlspinnersmsdemo/Contact.java


package in.wptrafficanalyzer.sqlspinnersmsdemo;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
import android.widget.EditText;

public class Contact extends DialogFragment implements LoaderCallbacks<Cursor>{

    /** A constant identifier for add operation */
    public static final int CONTACT_ADD =  1;

    /** A constant identifier for edit operation */
    public static final int CONTACT_EDIT = 2;

    /** A constant identifier for delete operation */
    public static final int CONTACT_DEL =  3;

    /** An adapter which holds contacts for the listview */
    SimpleCursorAdapter mAdapter;

    /** A reference for Contact name */
    EditText mTxtName;

    /** A reference for phone number */
    EditText mTxtPhone;

    /** A variable to inflate the layout file contact.xml*/
    View mContactView;

    /** A variable to hold contact id, which is required for updation and deletion of a contact */
    int mContactId = 0;

    /** Current operation done by this class, default is CONTACT_ADD */
    int mContactAction=CONTACT_ADD;

    /** A callback method */
    @Override
    public void onActivityCreated(Bundle arg0) {
        super.onActivityCreated(arg0);

        /** Getting a reference to Name */
        mTxtName = (EditText) mContactView.findViewById(R.id.txt_name);

        /** Getting a reference to Phone */
        mTxtPhone = (EditText) mContactView.findViewById(R.id.txt_phone);

        /** Creating the loader, if it does not exists */
        getLoaderManager().initLoader(0, null, this);
    };

    /** A callbak method */
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        /** Initializes mContactAction and mContactID using the arguments passed to this fragment by the function setArguments() */
        Bundle b = getArguments();
        if(b!=null){
            if(b.containsKey("contact_action"))
                mContactAction = b.getInt("contact_action");
            if(b.containsKey("contact_id"))
                mContactId = b.getInt("contact_id");
        }

        /** Creates a dialog window */
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());

        /** Inflating the layout file for this dialog window */
        mContactView = getActivity().getLayoutInflater().inflate(R.layout.contact,null);

        /** Click listener for the OK button of the dialog window */
        OnClickListener clickListener = new OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

                /** Setting up values to insert or delete a contact */
                ContentValues contentValues = new ContentValues();
                contentValues.put(ContactsDB.KEY_NAME, mTxtName.getText().toString());
                contentValues.put(ContactsDB.KEY_PHONE, mTxtPhone.getText().toString());

                switch(mContactAction){
                    case CONTACT_ADD:
                        /** Invokes content provider's insert operation */
                        getActivity().getContentResolver().insert(ContactsProvider.CONTENT_URI, contentValues);
                        break;

                    case CONTACT_EDIT:
                        /** Invokes content provider's update operation */
                        Uri uri = ContactsProvider.CONTENT_URI;
                        String pathSegment = Integer.toString(mContactId);
                        uri = Uri.withAppendedPath(uri, pathSegment);
                        getActivity().getContentResolver().update(uri, contentValues, null, null);
                        break;

                    case CONTACT_DEL:
                        /** Invokes content provider's delete operation */
                        uri = ContactsProvider.CONTENT_URI;
                        pathSegment = Integer.toString(mContactId);
                        uri = Uri.withAppendedPath(uri, pathSegment);
                        getActivity().getContentResolver().delete(uri, null, null);
                }

                /** Restarting the MainActivity's loader to refresh the listview */
                getActivity().getSupportLoaderManager().restartLoader(0, null, (LoaderCallbacks<Cursor>)getActivity());
            }
        };

        /** Changing the appearance of the dialog window based on the operation */
        switch(mContactAction){
            case CONTACT_ADD:
                dialogBuilder.setView(mContactView);
                dialogBuilder.setTitle("Add Contact");
                break;
            case CONTACT_EDIT:
                dialogBuilder.setView(mContactView);
                dialogBuilder.setTitle("Edit Contact");
                break;
            case CONTACT_DEL:
                dialogBuilder.setTitle("Delete Contact");
                dialogBuilder.setMessage("Are you sure to delete?");
                break;
        }

        dialogBuilder.setNegativeButton("Cancel", null);

        /** Setting click event handler for the OK button */
        dialogBuilder.setPositiveButton("OK", clickListener);

        return dialogBuilder.create();
    }

    /** A callback method invoked by the loader when initLoader() is called */
    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
        Bundle b = getArguments();

        /** Requesting for the contact name and phone to be edited */
        if(mContactAction==CONTACT_EDIT){
            Uri uri = ContactsProvider.CONTENT_URI;
            String pathSegment = Integer.toString(mContactId);
            uri = Uri.withAppendedPath(uri, pathSegment);
            return new CursorLoader(getActivity(), uri, null, null, null, null);
        }
        else
            return null;
    }

    /** A callback method, invoked after the requested content provider returned all the data */
    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor data) {
        /** populates Contact Name and Phone on edit operation */
        if(data.moveToFirst()){
            mTxtName.setText(data.getString(1));
            mTxtPhone.setText(data.getString(2));
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
    }
}


11. Update the file src/in/wptrafficanalyzer/sqlspinnersmsdemo/MainActivity.java to populate the listview with contacts from SQLite database. Also the “Call” and “SMS” operations are implemented in this class

package in.wptrafficanalyzer.sqlspinnersmsdemo;

import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {

    SimpleCursorAdapter mAdapter;
    ListView mLstContacts;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /** Event handler for click event on Add button */
        OnClickListener addContactListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            /** Creating a bundle object to pass some data to the fragment */
            Bundle args = new Bundle();

            /** Adding current operation to the bundle object */
            args.putInt("contact_action", Contact.CONTACT_ADD);

            /** Getting fragment manager to open the contact fragment */
            /** Here Android's backward compatibility support library function getSupportFragmentManager() is used to support Android 1.6 and above */
            FragmentManager fm = getSupportFragmentManager();

            /** Creating contact dialog fragment */
            Contact contact = new Contact();

            /** Setting the bundle object to this fragment */
            contact.setArguments(args);

            /** Starting a fragment transaction to dyanmically add fragment to the application */
            FragmentTransaction ft = fm.beginTransaction();

            /** Adding fragment to the fragment transaction */
            ft.add(contact, "CONTACT");

            /** The contact dialog fragment is effectively added and opened */
            ft.commit();

        }
    };

    /** Event handler for click event on Edit button */
    OnClickListener editContactListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            int id = 0;

            /** Getting the position of the currently selected item in the listview */
            int position  = mLstContacts.getCheckedItemPosition();

            /** Getting the id of the currently selected contact in the listview */
            if(mAdapter.getCursor().moveToPosition(position))
                id = Integer.parseInt(mAdapter.getCursor().getString(0));

                /** If no item is selected, then corresponding message is shown */
                if(id==0){
                    Toast.makeText(getBaseContext(), "Please Select a contact to edit", Toast.LENGTH_SHORT).show();
                    return;
                }

                /** Creating a bundle object to pass some data to the fragment */
                Bundle args = new Bundle();

                /** Adding contact id to the bundle object */
                args.putInt("contact_id", id);

                /** Adding current operation to the bundle object */
                args.putInt("contact_action", Contact.CONTACT_EDIT);

                /** Getting fragment manager to open the contact fragment */
                /** Here Android's backward compatibility support library function getSupportFragmentManager() is used to support Android 1.6 and above */
                FragmentManager fm = getSupportFragmentManager();

                /** Creating contact dialog fragment */
                Contact contact = new Contact();

                /** Setting the bundle object to this fragment */
                contact.setArguments(args);

                /** Starting a fragment transaction to dyanmically add fragment to the application */
                FragmentTransaction ft = fm.beginTransaction();

                /** Adding fragment to the fragment transaction */
                ft.add(contact, "CONTACT");

                /** The contact dialog fragment is effectively added and opened */
                ft.commit();

            }
        };

        /** Event handler for click event on Delete button */
        OnClickListener delContactListener = new OnClickListener() {

            @Override
            public void onClick(View v) {
                int id = 0;

                /** Getting the position of the currently selected item in the listview */
               int position  = mLstContacts.getCheckedItemPosition();

               /** Getting the id of the currently selected contact in the listview */
               if(mAdapter.getCursor().moveToPosition(position))
                   id = Integer.parseInt(mAdapter.getCursor().getString(0));

                /** If no item is selected, then corresponding message is shown */
                if(id==0){
                    Toast.makeText(getBaseContext(), "Please Select a contact to delete", Toast.LENGTH_SHORT).show();
                    return;
                }

                /** Creating a bundle object to pass some data to the fragment */
                Bundle args = new Bundle();

                /** Adding contact id to the bundle object */
                args.putInt("contact_id", id);

                /** Adding current operation to the bundle object */
                args.putInt("contact_action", Contact.CONTACT_DEL);

                /** Getting fragment manager to open the contact fragment */
                /** Here Android's backward compatibility support library function getSupportFragmentManager() is used to support Android 1.6 and above */
                FragmentManager fm = getSupportFragmentManager();

                /** Creating contact dialog fragment */
                Contact contact = new Contact();

                /** Setting the bundle object to this fragment */
                contact.setArguments(args);

                /** Starting a fragment transaction to dyanmically add fragment to the application */
                FragmentTransaction ft = fm.beginTransaction();

                /** Adding fragment to the fragment transaction */
                ft.add(contact, "CONTACT");

                /** The contact dialog fragment is effectively added and opened */
                ft.commit();
            }
        };

        /** Event handler for click event on Call button */
        OnClickListener callContactListener = new OnClickListener() {

            @Override
            public void onClick(View v) {

                String tel="";

                /** Creating an intent with the dialer's action name  */
                /** Since the intent is created with activity's action name, the intent is an implicit intent */
                Intent intent = new Intent("android.intent.action.DIAL");

                int position  = mLstContacts.getCheckedItemPosition();
                if(mAdapter.getCursor().moveToPosition(position))
                    tel = mAdapter.getCursor().getString(2);

                /** Setting up a uri object with tel no.  */
                Uri data = Uri.parse("tel:"+ tel);

                /** Setting tel no. to the intent object as data */
                intent.setData(data);

                /** Starting the Dialer activity */
                startActivity(intent);

            }
        };

        /** Event handler for click event on SMS button */
        OnClickListener smsContactListener = new OnClickListener() {

            @Override
            public void onClick(View v) {
                String tel="";

                /** Creating an intent with the dialer's action name  */
                /** Since the intent is created with activity's action name, the intent is an implicit intent */
                Intent intent = new Intent("android.intent.action.VIEW");

                int position  = mLstContacts.getCheckedItemPosition();
                if(mAdapter.getCursor().moveToPosition(position))
                    tel = mAdapter.getCursor().getString(2);

                /** Setting up a uri object with tel no.  */
                Uri data = Uri.parse("sms:"+ tel);

                /** Setting Tel no. to the intent object as data */
                intent.setData(data);

                /** Starting the Dialer activity */
                startActivity(intent);

            }
        };

        /** Getting a reference to Add Contact Button */
        Button addContact = (Button) findViewById(R.id.btn_add);
        addContact.setOnClickListener(addContactListener);

        /** Getting a reference to Edit Contact Button */
        Button editContact = (Button) findViewById(R.id.btn_edit);
        editContact.setOnClickListener(editContactListener);

        /** Getting a reference to Delete Contact Button */
        Button delContact = (Button) findViewById(R.id.btn_del);
        delContact.setOnClickListener(delContactListener);

        /** Getting a reference to Call  Button */
        Button callContact = (Button) findViewById(R.id.btn_call);
        callContact.setOnClickListener(callContactListener);

        /** Getting a reference to SMS  Button */
        Button smsContact = (Button) findViewById(R.id.btn_sms);
        smsContact.setOnClickListener(smsContactListener);

        mLstContacts = (ListView) findViewById(R.id.lst_contacts);

        mAdapter = new SimpleCursorAdapter(getBaseContext(),
            android.R.layout.simple_list_item_single_choice,
            null,
            new String[] { ContactsDB.KEY_NAME, ContactsDB.KEY_PHONE},
            new int[] { android.R.id.text1 , android.R.id.text2 }, 0);

        mLstContacts.setAdapter(mAdapter);
        mLstContacts.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

        /** Creating a loader for populating listview from sqlite database */
        getSupportLoaderManager().initLoader(0, null, this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    /** A callback method invoked by the loader when initLoader() is called */
    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
        Uri uri = ContactsProvider.CONTENT_URI;
        return new CursorLoader(this, uri, null, null, null, null);
    }

    /** A callback method, invoked after the requested content provider returned all the data */
    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
        mAdapter.swapCursor(arg1);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        mAdapter.swapCursor(null);
    }
}


12. Update the manifiest file AndroidManifest.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.wptrafficanalyzer.sqlspinnersmsdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="4"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter
                android:label="@string/app_name"
            >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:name="ContactsProvider"
            android:authorities="in.wptrafficanalyzer.sqlspinnersmsdemo.contacts"
            android:exported="false"
        />
    </application>
</manifest>

Note : The highlighted code above specifies that this content provider should be accessed from outside this application


13. Screenshots of the application

List of Contacts

Figure 5: List of Contacts

Add Contact

Figure 6 : Add Contact

Edit Contact

Figure 7 : Edit Contact

Delete contact

Figure 8 : Delete contact

Call a Selected number

Figure 9 : Call a Selected Contact

 

Send SMS to a selected Contact

Figure 10 : Send SMS to a selected Contact


14. Download


15. Reference

http://developer.android.com/guide/index.html


How to hire me?

I am George Mathew, working as software architect and Android app developer at wptrafficanalyzer.in

You can hire me on hourly basis or on project basis for Android applications development.

For hiring me, please mail your requirements to info@wptrafficanalyzer.in.

My other blogs
store4js.blogspot.com


Android Knowledge Quiz

Ready to test your knowledge in Android? Take this quiz :



Tags: , , , , , , , ,

5 Responses to Asynchronously populating listview from SQLite database using Content Providers

  1. Wayne on August 14, 2012 at 9:36 am

    Great website! You’re tutorials are awesome! One question, how do I get the phone number to show up under the name in the list view? TIA

  2. Scott on October 25, 2012 at 6:54 pm

    Tight example bro. Should the mContactsDB be de-referenced in the provider. When it comes to all those crazy-ass lifecycle methods, my eyes usually roll back in the sockets. If the creation occurs in on Create() I suspect the setting it to null should happen in the onPause() and the construction moved to onResume(). What do you think?

  3. sjpm on February 14, 2013 at 4:15 pm

    thanks for great tutorial .
    on had a request put a full text search in databse sqlite tutorial .

  4. Mehmet Karahan on May 9, 2013 at 5:04 am

    This is the best tutorial to couple SQLite database together with ContentProvider. It gave me the whole experience of the ContentProvider and how it behave.

    Thank you.

  5. sartaz on March 29, 2016 at 4:32 pm

    sir

    i need a code of when i write in textbox a ,related to a word should be show in the bottom side whose is stored in sqlite table.after select apple in the bottom side name and price should be show and price would be add,when i select multiple fruit.
    plz provide the code sir,i would thank full to u?

Leave a Reply

Your email address will not be published. Required fields are marked *

Be friend at g+

Subscribe for Lastest Updates

FBFPowered by ®Google Feedburner