Content Provider in Android Complete Tutorial
Content Provider in Android Complete TutorialContent Provider in Android Complete Tutorial
A 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.
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.
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
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
A 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 Classes
A 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:
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
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, null, null);
}
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
8.Copy the code in DepartmentDetail.java.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>
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
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.
1.Create Android project with details as listed in the table below.
2.Copy the code to the file staffdetail.xml in res/layout folder
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>
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.
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).
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'