Showing posts with label Content Provider in Android Complete Tutorial. Show all posts
Showing posts with label Content Provider in Android Complete Tutorial. Show all posts

Tuesday, July 30, 2013

Content Provider in Android Complete Tutorial

Content Provider in Android Complete Tutorial

                                            content provider is an application component that shares data with other applications.  it manages access to a central repository of data.Content provider generally uses  SQLite database to store and manage data .through one or more tables, similar to tables in a database. A provider is part of an Android application, which often provides its own UI for working with the data. However, content providers are primarily intended to be used by other applications , which access the provider using a provider client object.Example contacts in an application  used to create contacts of people and maintain it.Data stored through contact application is used  by phone dialer application  to make phone call.Messaging is another application which also uses contacts data.Examples of built-in Content Providers in Android OS are:Contacts MediaStore Bookmarks Settings and more.

           Data created in one application can be shared in other applications can be allowed through standard interface to read ,write and modify it.Content providers aslo  handles inter-process communication and secure data access by restricting what and which manner data can be accesed .
Content providers are also useful for reading and writing data that is private to your application and not shared. For example, the Note Pad sample application uses a content provider to save notes.
    
        If you are creating your own content provider then you should create a class that extents contentprovider  the following are the primary callback methods that need to be implemented.
onCreate() which is called to initialize the provider.This method runs on UI thread,best practice is to instantiate database helper, if using database.Here a relevent database and its table(s) are created  to hold data.
query(Uri, String[], String, String[], String) Queries the provider for the record(s) specified by either uri or`selection`/selectionArgs/grouping/having combo.
insert(Uri, ContentValues) Inserts the values into the content provider returning uri that points to the newly inserted record
update(Uri, ContentValues, String, String[]) which updates existing data in the content provider
delete(Uri, String, String[]) Deletes records(s) specified by either the uri or selection/selectionArgs combo. Returns number of records affected.
getType(Uri) Returns the mime time for the given uri. Typically, this MIME type will either be something like vnd.android.cursor.item/staffdetail for a single item or vnd.android.cursor.dir/staffdetails for multiple items.
Content provider is initiated first time it is used via a call to onCreate().There is no callback for cleaning up after the provider.When modifying the data (insert/update/delete), open/close database atomically.When reading the data, leave database open or else the data will get garbage collected.Data access methods (such as insert(Uri, ContentValues) and update(Uri, ContentValues, String, String[])) may be called from many threads at once, and must be thread-safe. Other methods (such as onCreate()) are only called from the application main thread, and must avoid performing lengthy operations.
 Requests to ContentResolver are automatically forwarded to the appropriate ContentProvider instance, so subclasses don't have to worry about the details of cross-process calls.
Content providers should be registered in androidmanifest file like activities and services.The authority
mentioned in contentprovider code should match with the entry in provider in manifest file.
<provider
     android:name=".DeptContentProvider"
    android:authorities="in.ac.srmuniv.cpimpl.contentprovider" />
...
Accessing a Content Provider
A client application accesses the data from a content provider with a ContentResolver object.The ContentResolverobject provides query(), insert(), update(), and delete() methods for accessing data from a content provider.
 The ContentResolver object invokes identically-named methods on an instance of a concrete subclass of ContentProvider,which typically resides in a separate application process.
The ContentProvider acts as an abstraction layer between its data store and the external presentation of dataThe ContentResolver object and the ContentProvider object automatically handle the details of inter-process communication.
·          The ContentProvider may not be in the same application process as the client’s ContentResolver.However, if you implement a content provider for your application, other components in your application can access it through a ContentResolver in exactly the same way as they would access a content provider in a different application.
For example, to get a list of the staffdetails and their phone numbers from the DepartmentDetail content Provider, you callContentResolver.query():
// Queries the user dictionary and returns results
Cursor cursor = getContentResolver().query(
    DeptContentProvider.CONTENT_URI,   // The content URI of the staffdetail table
    projection,                        // The columns of table to return for each row
    selectionClause                    // Selection criteria
    selectionArgs,                     // Selection criteria
    sortOrder);                        // The sort order for the returned rows


Content URIs
content URI is a URI that identifies data in a provider. It consists of:
The scheme, which is always content:// for a content URI
The authority, which is a unique string identifying the specific content provider
The path, which identifies a particular record or collection of records managed by the provider

In our example, the full URI for the "staffdetail" table is:
content://in.ac.srmuniv.cpimpl.contentprovide/IT_Dept

content:// — the scheme identifying this as a content URI
in.ac.srmuniv.cpimpl.contentprovider — the authority of the system user dictionary provider
SRM_UNIV — the path corresponding to the “staffdetails” table

The ContentResolver uses the authority to identify the content provider to contact.An application implementing a ContentProvider specifies the provider’s authority in the application manifest.The ContentProvider uses the path to choose the table to access.A provider usually has a path for each table it exposes. Many providers allow you to access a single row in a table by appending an ID value to the end of the URI.
For example, to retrieve a row whose _ID is 4 from DepartmentDetail, you can use this content URI:
Uri singleUri = ContentUri.withAppendedId(DepartmentDetail.CONTENT_URI,4);
The Uri and Uri.Builder classes contain convenience methods for constructing well-formed Uri objects from strings. The ContentUris class contains convenience methods for appending id values to a URI. The previous snippet uses withAppendedId() to append an id to the DepartmentDetail content URI.
Contract Classes
contract class defines constants that help applications work with the content URIs, column names, and
other features of a content provider.  Contract classes are not included automatically with a provider
The provider’s developer has to define them and then make them available to other developers.Many of the providers included with the Android platform have corresponding contract classes in the package android.provider.
               In our example, the DeptartmentContentProvider itself contain content URI and column name constants.We can have them in seperate class also.The content URI for the "staffdetail" table is defined in the DepartmentContentProvider.CONTENT_URI. The DepartmentContentProvider class also contains column name constants.
Requesting Access Permission
      Many content providers require clients to hold a custom access permission to access data from the provider.Your client application’s manifest must include a <uses-permission> element with the permission name defined by the provider.The provider may define separate permissions for "read access" (queries) and "write access" (inserts, updates, and deletes).
              For example, the DepartmentContentProvider can define the permissionandroid.permission.READ_STAFFDETAILS for applications that want to retrieve data, and a separate android.permission.WRITE_STAFFDETAILSY permission for inserting, updating, or deleting data.
Constructing a Query
The ContentResolver.query() method requires several arguments:
uri
The URI, using the content:// scheme, for the content to retrieve.
projection
A list of which columns to return. Passing null returns all columns, which can be inefficient.
selection
A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null returns all rows for the given URI.
selectionArgs
You may include ?s in selection, which are replaced by the values from selectionArgs, in the order that they appear in the selection.
sortOrder
How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passingnull uses the default sort order, which may be unordered.
The ContentResolver.query() client method always returns a Cursor containing the columns specified by the query’s projection for the rows that match the query’s selection criteria.If an internal error occurs, the results of the query depend on the particular provider. It may choose to return null, or it may throw an Exception.
Some Cursor implementations automatically update the object when the provider’s data changes, or trigger methods in an observer object when the Cursor changes, or both.
A Query Example
// A "projection" defines the columns that will be returned for each row
String[] projection =
{
    DepartmentDetail.COLUMN_POSITION,    // Contract class constant for the staff position in deptartment column name
    DepartmentDetail.COLUMN_STAFFNAME,   // Contract class constant for the staff column name
    DepartmentDetail.COLUMN_EMAIL  // Contract class constant for the staff email column name
    DepartmentDetail.COLUMN_PHONENO,
// Contract class constant for the staff phone no: column name
 DepartmentDetail.COLUMN_ID
,
// Contract class constant for the _ID column name
};
 // Defines a string to contain the selection clause
String selectionClause = null;
 // An array to contain selection arguments
String[] selectionArgs = null;
 // Gets a Staff position from the UI spinner selection
String sel=(String)staffCategorySelect.getSelectedItem();
// Does a query against the table and returns a CursorLoader
 CursorLoader cursorLoader = 
new CursorLoader(this,CONTENT_URI, from,"category='"+sel+"'"null,null);
//// Cursor Loader loadInbackground method returns a Cursor object
Cursor c = cursorLoader.loadInBackground();
adapter = new SimpleCursorAdapter(this, R.layout.stafflist_row, c, from,to, 0);
// An ORDER BY clause, or null to get results in the default sort order
String sortOrder = null;
 if (null == c) {
     // Insert code here to handle the error.
} else if (c.getCount() < 1) {        // If the Cursor is empty, the provider found no matches
} else {
    // Insert code here to do something with the results
}
This query is analogous to the SQL statement:
SELECT COLUMN_STAFFNAME,  COLUMN_EMAIL, COLUMN_PHONENO, COLUMN_POSITION,COLUMN_ID FROM staffdetail  WHERE category = <userinput from spinner> ORDER BY COLOUM_ID ASC;
 Inserting Data
To insert data into a provider, call the ContentResolver.insert() method.
This method inserts a new row into the provider and returns a content URI for that row.
This example shows how to insert a new word into the DepartmentDetail Provider:
// Defines a new Uri object that receives the result of the insertion
 private Uri staffdetailUri;
….
// Sets the values of each column received from user entry in staffdetail form activity
ContentValues values = new ContentValues();
                        values.put(DepartmentDetail.COLUMN_STAFFNAME, staffname);
                        values.put(DepartmentDetail.COLUMN_POSITION, position);
                        values.put(DepartmentDetail.COLUMN_PHONENO, description);
                       values.put(DepartmentDetail.COLUMN_EMAIL, summary);
                       if (staffdetailUri == null) {//when insert action bar menu is clicked new irecord added
                             staffdetailUri = getContentResolver().insert(                                                                                                 DeptContentProvider.CONTENT_URI// the SRM University staffdetail content URI
                         values// the values to insert
                          );
                        } else {// Update staffdetail when single press in the list item is done for selection
                                    getContentResolver().update(staffdetailUri, values, nullnull);
                               }

The content URI returned in newUri identifies the newly-added row, with the following format:
content:// in.ac.srmuniv.cpimpl.contentprovider /SRM_UNIV/<id_value>     
Deleting Data
Deleting rows is similar to retrieving row data.
Invoke ContentResolver.delete() to perform the update.
Specify selection criteria for the rows you want to delete.
The method returns the number of rows deleted.
For example, the following snippet deletes rows whose appid matches "user".
// Defines selection criteria for the rows you want to delete
String selectionClause = DepatmentDetail.COLUMN_POSITION + " LIKE ?";
String[] selectionArgs = {"Dean"};
// Defines a variable to contain the number of rows deleted
int rowsDeleted = 0;
// Deletes the words that match the selection criteria
rowsDeleted = getContentResolver().delete(
    DeptContentProvider.CONTENT_URI + "/" ,   // the user dictionary content URI
    selectionClause                    // the column to select on
    selectionArgs                      // the value to compare to

);
DELETE from staffdetail WHERE 'category'LIKE '?'
the placeholder is replaced by selectionArgs which is "Dean"


1.Create  Android project with details as listed in the table below.              
   
Property name
Property value
Project name
SRM_ContentProviderImpl
Package name
in.ac.srmuniv.cpimpl
Activity name
Mainactivity
Layout xml name
staff_list
     
2.Copy the code  to the file staff_list.xml in res/layout folder 
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

    <TextView
        android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/no_list" />


</LinearLayout>

3.Copy the code  to the file staffdetail_row.xml in res/layout folder 
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="80dp"
        android:layout_height="66dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginTop="4dp"
        android:src="@drawable/srmseal" >
    </ImageView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/data1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textColor="#EF3F6F"
            android:textSize="16sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/data2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/data3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textStyle="italic"
            android:typeface="sans" />

        <TextView
            android:id="@+id/data4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textStyle="bold"
            android:typeface="sans" />
    </LinearLayout>

</LinearLayout>
4.Copy the code  to the file staffdetail_edit.xml in res/layout folder 

<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/deptdetail"
            android:textAlignment="center"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textSize="@dimen/heading" />
    </LinearLayout>

    <Space
        android:layout_width="wrap_content"
        android:layout_height="50dp" />

    <TableLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TableRow
            android:id="@+id/tableRow4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:id="@+id/textView5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Name"
                android:textAppearance="?android:attr/textAppearanceMedium"/>

            <EditText
                android:id="@+id/editText4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ems="10" >

                <requestFocus />
            </EditText>
        </TableRow>

        <TableRow
            android:id="@+id/tableRow1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/position"
                android:textAppearance="?android:attr/textAppearanceMedium"/>

            <Spinner
                android:id="@+id/spinner1"
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:entries="@array/staff_positions"/>
        </TableRow>

        <TableRow
            android:id="@+id/tableRow2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:id="@+id/textView3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/email"
                android:textAppearance="?android:attr/textAppearanceMedium"/>

            <EditText
                android:id="@+id/editText2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ems="10"
                android:inputType="textEmailAddress"/>
        </TableRow>

        <TableRow
            android:id="@+id/tableRow3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:id="@+id/textView4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/phone"
                android:textAppearance="?android:attr/textAppearanceMedium"/>

            <EditText
                android:id="@+id/editText3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ems="10"
                android:inputType="phone"/>
        </TableRow>
    </TableLayout>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="@string/submit"
        android:textAlignment="center" />

</LinearLayout>

5.Copy the code  to the file string.xml in res/values folder 
<?xml version="1.0"encoding="utf-8"?>
<resources>

    <string name="app_name">SRM_ContentProviderImp</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="no_list">No list of people available for now</string>
    <string name="menu_insert">Add Item</string>
    <string name="menu_delete">Delete the Detail of the Staff</string>
    <string name="deptdetail">SRM University</string>
    <string name="position">Position</string>
    <string name="email">E-Mail</string>
    <string name="phone">Phone No:</string>
    <string name="submit">Submit</string>

</resources>

6.Copy the code  to the file staffposition.xml in res/values folder 
<?xml version="1.0"encoding="utf-8"?>
<resources>

    <string-array name="staff_positions">
        <item>AsstProfessor</item>
        <item>Professor</item>
        <item>Dean</item>
        <item>Director</item>
    </string-array>

</resources>
7.Copy the listmenu.xml in res/menu folder
<?xml version="1.0"encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/insert"
        android:showAsAction="always"
        android:title="Insert">
    </item>
    <item
        android:id="@+id/delete"
        android:showAsAction="always"
        android:title="Delete ALL ">
    </item>


</menu>
8.Copy the code in DepartmentDetail.java.
packagein.ac.srmuniv.cpimpl;

importandroid.content.Context;
importandroid.database.sqlite.SQLiteDatabase;
importandroid.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DepartmentDetail extends SQLiteOpenHelper {
    // Database table
    public static final String TABLE_NAME = "staffdetail";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_STAFFNAME = "staffname";
    public static final String COLUMN_POSITION = "category";
    public static final String COLUMN_EMAIL = "email";
    public static final String COLUMN_PHONENO = "phoneno";
    private static final String DATABASE_NAME = "srmfaculty.db";
    private static final int DATABASE_VERSION = 1;

    // Database creation SQL statement
    private static final String DATABASE_CREATE = "create table " + TABLE_NAME
            + "(" + COLUMN_ID + " integer primary key autoincrement, "
            + COLUMN_STAFFNAME + " text not null, " + COLUMN_POSITION
            + " text not null, " + COLUMN_EMAIL + " text not null,"
            + COLUMN_PHONENO + " integer not null"

            + ");";

    publicDepartmentDetail(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Method is called during creation of the database
    @Override
    public voidonCreate(SQLiteDatabase database) {
        database.execSQL(DATABASE_CREATE);
    }

    // Method is called during an upgrade of the database,
    // e.g. if you increase the database version
    @Override
    public voidonUpgrade(SQLiteDatabase database, int oldVersion,
            int newVersion) {
        Log.w("DepartmentDetail", "Upgrading database from version "
                + oldVersion + " to " + newVersion
                + ", which will destroy all old data");
        database.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(database);
    }


}
9.Copy the code in DeptContentProvider.java. which extends ContentProvider

packagein.ac.srmuniv.cpimpl;

import java.util.Arrays;
import java.util.HashSet;

importandroid.content.ContentProvider;
importandroid.content.ContentResolver;
importandroid.content.ContentValues;
importandroid.content.UriMatcher;
importandroid.database.Cursor;
importandroid.database.sqlite.SQLiteDatabase;
importandroid.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
importandroid.text.TextUtils;

public class DeptContentProvider extends ContentProvider {

    // database
    private DepartmentDetail database;

    // Used for the UriMacher
    private static final int STAFFS = 10;
    private static final int STAFF_ID = 20;

    private static final String AUTHORITY = "in.ac.srmuniv.cpimpl.contentprovider";

    private static final String BASE_PATH = "IT_Dept";
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
            + "/" + BASE_PATH);

    public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
            + "/deptdetails";
    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
            + "/deptdetail";

    private static final UriMatcher sURIMatcher = new UriMatcher(
            UriMatcher.NO_MATCH);
    static {
        sURIMatcher.addURI(AUTHORITY, BASE_PATH, STAFFS);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", STAFF_ID);
    }

    @Override
    public boolean onCreate() {
        database = newDepartmentDetail(getContext());
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {

        // UisngSQLiteQueryBuilder instead of query() method
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

        // Check if the caller has requested a column which does not exists
        checkColumns(projection);

        // Set the table
        queryBuilder.setTables(DepartmentDetail.TABLE_NAME);

        int uriType = sURIMatcher.match(uri);
        switch (uriType) {
        case STAFFS:
            break;
        case STAFF_ID:
            // Adding the ID to the original query
            queryBuilder.appendWhere(DepartmentDetail.COLUMN_ID + "="
                    + uri.getLastPathSegment());
            break;
        default:
            throw newIllegalArgumentException("Unknown URI: " + uri);
        }

        SQLiteDatabase db = database.getWritableDatabase();
        Cursor cursor = queryBuilder.query(db, projection, selection,
                selectionArgs, null, null, sortOrder);
        // Make sure that potential listeners are getting notified
        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

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

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        long id = 0;
        switch (uriType) {
        case STAFFS:
            id = sqlDB.insert(DepartmentDetail.TABLE_NAME, null, values);
            break;
        default:
            throw newIllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return Uri.parse(BASE_PATH + "/" + id);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        int rowsDeleted = 0;
        switch (uriType) {
        case STAFFS:
            rowsDeleted = sqlDB.delete(DepartmentDetail.TABLE_NAME, selection,
                    selectionArgs);
            break;
        case STAFF_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(DepartmentDetail.TABLE_NAME,
                        DepartmentDetail.COLUMN_ID + "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(DepartmentDetail.TABLE_NAME,
                        DepartmentDetail.COLUMN_ID + "=" + id + " and "
                                + selection, selectionArgs);
            }
            break;
        default:
            throw newIllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return rowsDeleted;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {

        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        int rowsUpdated = 0;
        switch (uriType) {
        case STAFFS:
            rowsUpdated = sqlDB.update(DepartmentDetail.TABLE_NAME, values,
                    selection, selectionArgs);
            break;
        case STAFF_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsUpdated = sqlDB.update(DepartmentDetail.TABLE_NAME, values,
                        DepartmentDetail.COLUMN_ID + "=" + id, null);
            } else {
                rowsUpdated = sqlDB.update(DepartmentDetail.TABLE_NAME, values,
                        DepartmentDetail.COLUMN_ID + "=" + id + " and "
                                + selection, selectionArgs);
            }
            break;
        default:
            throw newIllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return rowsUpdated;
    }

    private voidcheckColumns(String[] projection) {
        String[] available = { DepartmentDetail.COLUMN_POSITION,
                DepartmentDetail.COLUMN_STAFFNAME,
                DepartmentDetail.COLUMN_EMAIL, DepartmentDetail.COLUMN_PHONENO,
                DepartmentDetail.COLUMN_ID };
        if (projection != null) {
            HashSet<String> requestedColumns = new HashSet<String>(
                    Arrays.asList(projection));
            HashSet<String> availableColumns = new HashSet<String>(
                    Arrays.asList(available));
            // Check if all columns which are requested are available
            if(!availableColumns.containsAll(requestedColumns)) {
                throw newIllegalArgumentException(
                        "Unknown columns in projection");
            }
        }
    }

}
10.Copy the code in MainActivity.java Activity.

packagein.ac.srmuniv.cpimpl;

importin.ac.srmuniv.cpimpl.R;
importandroid.annotation.SuppressLint;
importandroid.annotation.TargetApi;
importandroid.app.ListActivity;
importandroid.app.LoaderManager;
importandroid.content.CursorLoader;
importandroid.content.Intent;
importandroid.content.Loader;
importandroid.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
importandroid.view.ContextMenu;
importandroid.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
importandroid.view.MenuInflater;
importandroid.view.MenuItem;
import android.view.View;
importandroid.widget.AdapterView.AdapterContextMenuInfo;
importandroid.widget.ListView;
importandroid.widget.SimpleCursorAdapter;

/*
 * MainActivity displays the existing staff details
 * in a list
 *
 * You can create new ones via the ActionBar entry "INSERT"
 * You can delete all the items in database via the ActionBar entry "DELETE ALL"
 * You can delete existing ones via a long press on the item
 */

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class  MainActivity extends ListActivity implements
        LoaderManager.LoaderCallbacks<Cursor> {

    private static final int DELETE_ID = Menu.FIRST + 1;
    private SimpleCursorAdapter adapter;

    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.staff_list);
        this.getListView().setDividerHeight(2);
        fillData();
        registerForContextMenu(getListView());
    }

    // Create the menu based on the XML defintion
    @Override
    public booleanonCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.listmenu, menu);
        return true;
    }

    // Reaction to the menu selection
    @Override
    public booleanonOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.insert:
            createStaffdetail();
            return true;
        case R.id.delete:
            Uri uri = Uri.parse(DeptContentProvider.CONTENT_URI + "/");
            getContentResolver().delete(uri, null, null);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public booleanonContextItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case DELETE_ID:
            AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
                    .getMenuInfo();
            Uri uri = Uri
                    .parse(DeptContentProvider.CONTENT_URI + "/" + info.id);
            getContentResolver().delete(uri, null, null);
            fillData();
            return true;
        }
        return super.onContextItemSelected(item);
    }

    private void createStaffdetail() {
        Intent i = new Intent(this, StaffDetailActivity.class);
        startActivity(i);
    }

    // Opens the second activity if an entry is clicked
    @Override
    protected voidonListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Intent i = new Intent(this, StaffDetailActivity.class);
        Uri todoUri = Uri.parse(DeptContentProvider.CONTENT_URI + "/" + id);
        i.putExtra(DeptContentProvider.CONTENT_ITEM_TYPE, todoUri);

        startActivity(i);
    }

    @SuppressLint("NewApi")
    private void fillData() {

        // Fields from the database (projection)
        // Must include the _id column for the adapter to work
        String[] from = new String[] { DepartmentDetail.COLUMN_STAFFNAME,
                DepartmentDetail.COLUMN_EMAIL, DepartmentDetail.COLUMN_PHONENO,
                DepartmentDetail.COLUMN_POSITION };
        // Fields on the UI to which we map
        int[] to = new int[] { R.id.data1, R.id.data2, R.id.data3, R.id.data4 };

        getLoaderManager().initLoader(0, null, this);
        adapter = new SimpleCursorAdapter(this, R.layout.staffdetail_row, null,
                from, to, 0);

        setListAdapter(adapter);
    }

    @Override
    public voidonCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add(0, DELETE_ID, 0, R.string.menu_delete);
    }

    // Creates a new loader after the initLoader () call
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String[] projection = { DepartmentDetail.COLUMN_ID,
                DepartmentDetail.COLUMN_STAFFNAME,
                DepartmentDetail.COLUMN_EMAIL, DepartmentDetail.COLUMN_PHONENO,
                DepartmentDetail.COLUMN_EMAIL, DepartmentDetail.COLUMN_POSITION };
        CursorLoader cursorLoader = new CursorLoader(this,
                DeptContentProvider.CONTENT_URI, projection, null, null, null);
        return cursorLoader;
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    public voidonLoadFinished(Loader<Cursor> loader, Cursor data) {
        adapter.swapCursor(data);
    }

    @Override
    public voidonLoaderReset(Loader<Cursor> loader) {
        // data is not available anymore, delete reference
        adapter.swapCursor(null);
    }

}

11.Copy the code in StaffDetailActivity.java Activity.

importin.ac.srmuniv.cpimpl.R;
importandroid.app.Activity;
importandroid.content.ContentValues;
importandroid.content.res.Resources;
importandroid.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
importandroid.text.TextUtils;
import android.view.View;
importandroid.widget.ArrayAdapter;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.Spinner;
importandroid.widget.Toast;

/*
 * StaffDetailActivity allows to enter a new staff detail entry
 * or to change an existing
 */
public class StaffDetailActivity extends Activity {

    private EditText nameText;
    private EditText emailText;
    private EditText phoneText;
    private Spinner staffCategorySelect;
    private Uri staffdetailUri;
    String[] staffPositions;

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.staffdetailedit);

        nameText = (EditText) findViewById(R.id.editText4);
        emailText = (EditText) findViewById(R.id.editText2);
        phoneText = (EditText) findViewById(R.id.editText3);
        Button confirmButton = (Button) findViewById(R.id.button1);
        staffCategorySelect = (Spinner) findViewById(R.id.spinner1);

        Resources res = getResources();
        staffPositions = res.getStringArray(R.array.staff_positions);

        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, staffPositions);
        // Drop down layout style - list view with radio button
        dataAdapter
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        // attaching data adapter to spinner
        staffCategorySelect.setAdapter(dataAdapter);

        Bundle extras = getIntent().getExtras();

        // Check from the saved Instance
        staffdetailUri = (bundle == null) ? null : (Uri) bundle
                .getParcelable(DeptContentProvider.CONTENT_ITEM_TYPE);

        // Or passed from the other activity
        if (extras != null) {
            staffdetailUri = extras
                    .getParcelable(DeptContentProvider.CONTENT_ITEM_TYPE);

            fillData(staffdetailUri);
        }

        confirmButton.setOnClickListener(newView.OnClickListener() {
            public void onClick(View view) {
                if (TextUtils.isEmpty(emailText.getText().toString())) {
                    makeToast();
                } else {
                    setResult(RESULT_OK);
                    finish();
                }
            }

        });
    }

    private void fillData(Uri uri) {
        String[] projection = { DepartmentDetail.COLUMN_STAFFNAME,
                DepartmentDetail.COLUMN_EMAIL,
                DepartmentDetail.COLUMN_POSITION,
                DepartmentDetail.COLUMN_PHONENO };
        Cursor cursor = getContentResolver().query(uri, projection, null, null,
                null);
        if (cursor != null) {
            cursor.moveToFirst();

        }
        nameText.setText(cursor.getString(cursor
                .getColumnIndexOrThrow(DepartmentDetail.COLUMN_STAFFNAME)));
        staffCategorySelect.setSelection(staffPositionID(cursor));
        emailText.setText(cursor.getString(cursor
                .getColumnIndexOrThrow(DepartmentDetail.COLUMN_EMAIL)));
        phoneText.setText(cursor.getString(cursor
                .getColumnIndexOrThrow(DepartmentDetail.COLUMN_PHONENO)));

        // Always close the cursor
        cursor.close();
    }

    protected voidonSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        saveState();
        outState.putParcelable(DeptContentProvider.CONTENT_ITEM_TYPE,
                staffdetailUri);
    }

    @Override
    protected void onPause() {
        super.onPause();
        saveState();
    }

    private void saveState() {
        String staffname = nameText.getText().toString();
        String position = (String) staffCategorySelect.getSelectedItem();// positionText.getText().toString();
        String summary = emailText.getText().toString();
        String description = phoneText.getText().toString();

        // Only save if either staff details
        // are available

        if(description.length() == 0 && summary.length() == 0) {
            return;
        }

        ContentValues values = new ContentValues();
        values.put(DepartmentDetail.COLUMN_STAFFNAME, staffname);
        values.put(DepartmentDetail.COLUMN_POSITION, position);
        values.put(DepartmentDetail.COLUMN_PHONENO, description);
        values.put(DepartmentDetail.COLUMN_EMAIL, summary);

        if (staffdetailUri == null) {
            // New staffdetail
            staffdetailUri = getContentResolver().insert(
                    DeptContentProvider.CONTENT_URI, values);
        } else {
            // Update staffdetail
            getContentResolver().update(staffdetailUri, values, null, null);
        }
    }

    private void makeToast() {
        Toast.makeText(StaffDetailActivity.this, "Please enter value",
                Toast.LENGTH_LONG).show();
    }

    intstaffPositionID(Cursor cursor) {

        int i = 0;
        String pos = cursor.getString(cursor
                .getColumnIndexOrThrow(DepartmentDetail.COLUMN_POSITION));
        for (String s : staffPositions) {

            if (pos.equals(s))
                break;
            i++;
        }
        return i;
    }
}

12.Copy the code given below in Androidmanifest.xml 


<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.ac.srmuniv.cpimpl"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".StaffDetailActivity"
            android:windowSoftInputMode="stateVisible|adjustResize">
        </activity>

        <provider
            android:name=".DeptContentProvider"
           android:authorities="in.ac.srmuniv.cpimpl.contentprovider"
            android:enabled="true"
            android:exported="true"
            android:grantUriPermissions="true" >
        </provider>
    </application>



</manifest>                                                                            

13.Run the application in the emulator.                                                  



 Fig 1 Shows MainActivity  when   application has no data in content provider maintained database   click 
            insert option  in action bar to call StaffdetailEdit Activity.
Fig 2 shows StaffdetailEdit Activity which enables user to enter details and on submit button clicked  the data are updated in to database
 
Fig 3 Updated data in database is listed in ListView immediately.
Fig 4 Shows List of staffs with details in listview populated by querying content provider.

Fig 5 shows we can delete individual elements in database by making long press on the selected element to invoke context menu.Delete operation on the content provider is called to remove the specific row from database . Delete All option in action bar will delete entire list from database.

1.Create  Android project with details as listed in the table below.              
 
Property name
Property value
Project name
SRM_ContentProvider2
Package name
in.ac.srmuniv.cp
Activity name
Mainactivity
Layout xml name
staffdetail
   
2.Copy the code  to the file staffdetail.xml in res/layout folder 
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="@dimen/activity_horizontal_margin"
            android:text="@string/staffcategoryselect"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

        <Space
            android:layout_width="20dp"
            android:layout_height="match_parent" />

        <Spinner
        android:id="@+id/spinner1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:entries="@array/staff_positions" />

    </LinearLayout>

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

    <TextView
        android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/no_list" />


</LinearLayout>

3.Copy the code  to the file staffdetail_row.xml in res/layout folder 
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="80dp"
        android:layout_height="66dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginTop="4dp"
        android:src="@drawable/srmseal" >
    </ImageView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/data1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textColor="#8FBFFF"
            android:textSize="16sp"
            android:textStyle="bold" />

<TextView android:id="@+id/data2"
    android:textSize="12sp"        
    android:textStyle="bold"     
    android:layout_width="wrap_content"        
    android:layout_height="wrap_content"/>
<TextView android:id="@+id/data3"
    android:typeface="sans"
    android:textSize="12sp"
    android:textStyle="italic"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView android:id="@+id/data4"
    android:typeface="sans"
    android:textSize="12sp"
    android:textStyle="bold"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView android:id="@+id/data5"
    android:textSize="12sp"        
    android:textStyle="bold"
    android:textColor="#FF0000"       
    android:layout_width="fill_parent"        
    android:layout_height="wrap_content"/>
    </LinearLayout>

</LinearLayout>

5.Copy the code  to the file string.xml in res/values folder 
<?xml version="1.0"encoding="utf-8"?>
<resources>

    <string name="app_name">SRM_ContentProvider2</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="no_list">No list of people available for now</string>
    <string name="staffcategoryselect">SelectCategory</string>

</resources>

6.Create a new xml file in res/value folder name it staffposition.xml

<?xml version="1.0"encoding="utf-8"?>
<resources>
        <string-array name="staff_positions">
        <item>AsstProfessor</item>
        <item>Professor</item>
        <item>Dean</item>
        <item>Director</item>
    </string-array>
</resources>

7.Copy the code in MainActivity.java.

import in.ac.srmuniv.cp.R;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
importandroid.annotation.SuppressLint;
import android.annotation.TargetApi;
importandroid.app.ListActivity;
import android.app.LoaderManager;
importandroid.content.CursorLoader;
import android.content.Loader;
importandroid.content.res.Resources;
importandroid.database.Cursor;
import android.view.Menu;
import android.view.View;
importandroid.widget.AdapterView;
importandroid.widget.AdapterView.OnItemSelectedListener;
importandroid.widget.ArrayAdapter;
importandroid.widget.SimpleCursorAdapter;
importandroid.widget.Spinner;

@SuppressLint("NewApi")
public class MainActivity extends ListActivity
{
      public static final String COLUMN_ID = "_id";
      public static final String COLUMN_STAFFNAME= "staffname";
      public static final String COLUMN_POSITION= "category";
      public static final String COLUMN_EMAIL= "email";
      public static final String COLUMN_PHONENO= "phoneno";
     
      private static final String AUTHORITY = "in.ac.srmuniv.cpimpl.contentprovider";
      private static final String BASE_PATH = "IT_Dept";
      public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
          + "/" + BASE_PATH);
     
      private SimpleCursorAdapter adapter;
      private Spinner staffCategorySelect;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.staffdetail);
        this.getListView().setDividerHeight(2);
        staffCategorySelect=(Spinner)findViewById(R.id.spinner1);
         Resources res = getResources();
            String []staffPositions = res.getStringArray(R.array.staff_positions);
           
            ArrayAdapter<String> dataAdapter = newArrayAdapter<String>(this,
                    android.R.layout.simple_spinner_item,staffPositions);
         // Drop down layout style - list view with radio button
            dataAdapter
                    .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

            // attaching data adapter to spinner
            staffCategorySelect.setAdapter(dataAdapter);
            staffCategorySelect.setOnItemSelectedListener(newOnItemSelectedListener()
                    {
                    @Override

                    public voidonNothingSelected(AdapterView<?> arg0) { }
                    @Override
                    public voidonItemSelected(AdapterView<?> arg0, View arg1,
                            int arg2, long arg3) {
                        fillData();
                       
                    }
                    });

       
        registerForContextMenu(getListView());
       
    }

    @Override
    public booleanonCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @SuppressLint("NewApi")
    private void fillData() {

        // Fields from the database (projection)
        // Must include the _id column for the adapter to work
       
        String[] from = new String[] { COLUMN_STAFFNAME,COLUMN_EMAIL,COLUMN_PHONENO,COLUMN_POSITION,COLUMN_ID};
        // Fields on the UI to which we map
        int[] to = new int[] { R.id.data1,R.id.data2,R.id.data3,R.id.data4 };

        String sel=(String)staffCategorySelect.getSelectedItem();
            CursorLoader cursorLoader = new CursorLoader(
                this,
                CONTENT_URI, from,"category ='"+ sel+"'", null,
                null);
                Cursor c = cursorLoader.loadInBackground();
        adapter = new SimpleCursorAdapter(this, R.layout.stafflist_row, c, from,
            to, 0);

        setListAdapter(adapter);
      }

}

8.11.Copy the code given below in Androidmanifest.xml 

<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.ac.srmuniv.cp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="17" />
  
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="in.ac.srmuniv.cp.MainActivity"
            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>
12.Run the application in the emulator. 



Figure 6 When the category of staff is selcted it lists the specific category of staff details only inin listview 


Figure 7 Shows the 'Android component interaction diagram' for the Content provider tutorial
Code Explanation
  The demonstration project SRM_ContentProviderImpl is designed for creating  details for faculty of university.You have MainActivity with Action Bar to insert  staffdetail ,when insert menu is pressed  StaffDetailEditActivity  is called which provides form for entering staff detail.When delete_all menu is pressed it  removes all the list of staffdetails from the database governed by content provider.Available list of staff details stored in database are displayed in the list  you can long press the row element to get option menu asking you to delete the particular element from data base.An item select  from list will  provide option  to edit the staff detail and update the detail in database.
             The project contains neccessary classes for implementing content provider.To implement  content provider and publish data which can be used by another application it uses  DeptContentProvider class which extends ContentProvider.Content provider uses SQLite database srmfaculty.db.To implement SQLite database for handling querying,insert,update and delete DepartmentDetail class which extends SQLiteOpenHelper.
                                                         MainActivity which a ListActivity  is the UI for the content provider application which uses staff_list.xml  to display  the faculty details list. the customized listview uses staffdetail_row.xml for displaying staffdetail in each row of the listview..Action bar based menu is achived by setting the attribute  android:showAsAction="always"of item element in listmenu.xml in res/menu folder.When insert menu of action bar is clicked  onOptionsItemSelected(MenuItem item) callback method is called,in the method StaffDetailEditActivity is invoked which provides form for entering staffdetails .After entering neccessary details submit button has to be pressed will invoke contentresolver to insert values to the database of contentprovider.The following is the code getContentResolver().insert(DeptContentProvider.CONTENT_URI,values).Figure 2 shows the StaffDetailEditActivity where details of staff are entered.Figure 3 shows the entered staff detail available in listview of Mainactivity.Figure 4 depicts the populated listview of content provider loaded through LoaderManager.LoaderCallbacks<Cursor> listener implemented by Mainactivity.
Delete menu option selected content resolver deletes values from content provider.The following code getContentResolver().delete(uri, null, null) with uri representing content provider uri path,since second and third parameters of   delete method are null entire list of elements in database are deleted.It is advicable to use    a dialog box to confirm deletion.Figure 5 shows the screen shot for deleting a single element in the content provider as well as the menu 'Delete all' will empty the entire list of items from content provider.
                                                     Inserted values of staffdetail are listed in the listview.user can select each element representing staffdetail  a 'single press will call onContextItemSelected(MenuItem item) callback method.StaffDetailEditActivity is invoked  it takes the intent extra from MainActivity, the uri for the particular row in staffdetail database is created based on   listitem seleced whose id is  also is the id for the data in contentprovider the staffdetails database. In StaffDetailActivity  getContentResolver().query(uri, projection, null, null,null) will be called with uri retrived from the Bundle will create the cursor object which retrives the staffdetail selected  and presents in the form for user to edit.This time contentresolver will update on submit button being pressed the following code implements it.getContentResolver().update(staffdetailUri, values, null, null).
        <provider
            android:name=".DeptContentProvider"
           android:authorities="in.ac.srmuniv.cpimpl.contentprovider"
            android:enabled="true"
            android:exported="true"
            android:grantUriPermissions="true" >
the above entry in AndroidManifest.xml of SRM_ContentProviderImpl App depicts the authority which is a unique identifier will be used by other application to identify and use the content provider.the parameter 
android:exported="true" ensures content provider is sharable across many Apps.

                The  second App SRM_ContentProvider2 uses the  contentprovider previously created by SRM_ContentProviderImpal.This application allows to choose faculty position and display the list of  faculties  and thier details belonging to selected postion.The application can be extended so that a group message or mail can be send to specific group of faculties.A sinilar application can be developed where you can enter or retrive all the product details in one application i.e the content provider application similar to SRM_ContentProviderImpl and  have other applications that uses the content provider similar toSRM_ContentProvider2,for example an sales application for sales people which can select product based on category to moniter sales and  another application for logistics people here the application can keep track of product delivery which  will also consume the same content provider.
It consist of MainActivity which has spinner to select the faculty position.
                        CursorLoader cursorLoader = new CursorLoader(this,CONTENT_URI, from,"category ='"+ sel+"'"null,null);
         The above code will be called when a item in the spinner is selected the selection is faculty position which forms the query in CursorLoader which is a new feature from honey comb version.The second parameter of the CursorLoader constructor is the CONTENT_URI is the content provider uri publically available for all application.The thrid parameter "from" is the projection which is the array of Strings representing coloums of databsae. the fourth parameter is the selection criteria ,here the selection criteria is 'category' which is selected through spinner. SimpleCursoradapter will inflate the list of items got through querying content provider.For example if "AssistantProfessor" item is selected as faculty position list of AssistantProfessors and their details already through the content provider application.Figure 6 shows the screen shot when 'selection category' spinner is selected for 'Assistant Professor'