Pr.Pg Next Pg

More with Content Providers tutorials

  • As we have seen that we got a bit of an introduction to content providers in the earilier tutorials.

  • We will now discuss them in a bit of more detail.

  • Content providers are the standard interface that connects data in one process with code running in another process.

  • You don't need to develop your own provider if you don't intend to share your data with other applications. However, you do need your own provider to provide custom search suggestions in your own application. You also need your own provider if you want to copy and paste complex data or files from your application to other applications.

  • Android itself includes content providers that manage data such as audio, video, images, and personal contact information. You can see some of them listed in the reference documentation for the android.providerpackage. With some restrictions, these providers are accessible to any Android application.

Example

  • With the help of example we illustrate using various built in Application such as the browser bookmarks, phonebook, call log etc.

  • In this application we will have a list view which will display the list depending on what cursor is used.

  • Make sure that only of the codes for the cursor is executed. You can try the various other Content Providers by uncommenting the statements.

  • Below is the xml layout of the Main Activity.

 

 

main.xml

 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<ListView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:id="@+id/listView">

</ListView>

</LinearLayout>

 

  • Below is the code for the row.xml file which holds the layout for each of the rows in the list view.

 

row.xml

 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_height="wrap_content"

android:padding="5sp"

android:layout_width="fill_parent">

<TextView

android:layout_height="wrap_content"

android:id="@+id/text1"

android:text="Name"

android:textSize="18sp"

android:layout_width="fill_parent"

android:layout_weight="1"></TextView>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/text2"

android:text="Value"

android:textSize="18sp"

android:gravity="right"></TextView>

</LinearLayout>

 

  • We now move on to our java file for the MainActivity.

 

 

MainActivity

 

package com.monster.ContentUserDemo;

 

import android.app.Activity;

import android.content.ContentResolver;

import android.database.Cursor;

import android.os.Bundle;

import android.provider.Browser;

import android.provider.CallLog;

import android.provider.ContactsContract;

import android.provider.ContactsContract.Contacts;

import android.provider.Settings;

import android.util.Log;

import android.widget.ListView;

import android.widget.SimpleCursorAdapter;

 

public class MainActivity extends Activity {

private static final String TAG = "ContentUserDemo";

 

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

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

String[] projection = new String[]

{ContactsContract.CommonDataKinds.Phone._ID,

ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,

ContactsContract.CommonDataKinds.Phone.NUMBER};

 

// Get content provider and cursor

ContentResolver cr = getContentResolver();

Cursor cursor = cr.query(Settings.System.CONTENT_URI, null, null, null, null);

// Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI, null, null, null, null);

// Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,projection, null, null, null);

//Cursor cursor = cr.query(Browser.BOOKMARKS_URI, null, null, null, null);

 

// Let activity manage the cursor

startManagingCursor(cursor);

Log.d(TAG, "cursor.getCount()=" + cursor.getCount());

 

// Get the list view

ListView listView = (ListView) findViewById(R.id.listView);

String[] from = { Settings.System.NAME, Settings.System.VALUE };

// String[] from = { CallLog.Calls.CACHED_NAME, CallLog.Calls.NUMBER };

// String[] from = { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};

// String[] from = { Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL};

int[] to = { R.id.text1, R.id.text2 };

 

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.row, cursor, from, to);

listView.setAdapter(adapter);

}

}

 

  • When you want to access data in a content provider, you use theContentResolver object in your application's Context to communicate with the provider as a client. The ContentResolverobject communicates with the provider object, an instance of a class that implements ContentProvider. The provider object receives data requests from clients, performs the requested action, and returns the results.

  • In our example, we have used a method called query() on the cursor.

  • public abstract Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

  • Added in API level 1.

  • Implement this to handle query requests from clients. This method can be called from multiple threads, as described in Processes and Threads.

Parameters

uri

The URI to query. This will be the full URI sent by the client; if the client is requesting a specific record, the URI will end in a record number that the implementation should parse and add to a WHERE or HAVING clause, specifying that _id value.

projection

The list of columns to put into the cursor. If null all columns are included.

selection

A selection criteria to apply when filtering rows. If null then all rows are included.

selectionArgs

You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.

sortOrder

How the rows in the cursor should be sorted. If null then the provider is free to define the sort order.

  • We then use the startManagingCursor() method which will help to take casre of the cursor lifecycle based in the activity’s lifecycle. When the activity will be destroyed the all managed Cursors will be closed automatically. This method takes in as its parameter the cursor to be managed.

  • Note The method startManagingCursor is deprecated for API 11 and later and hence we have to use CursorLoader class with LoaderManager instead.

  • Below is the code for API 11 and higher.

 

 

 

package com.monster.ContentUserDemo;

 

importjava.security.KeyStore.LoadStoreParameter;

 

import android.app.Activity;

import android.app.LoaderManager;

import android.app.LoaderManager.LoaderCallbacks;

import android.content.ContentResolver;

import android.content.CursorLoader;

import android.content.Loader;

import android.database.Cursor;

import android.os.Bundle;

import android.provider.Browser;

import android.provider.CallLog;

import android.provider.ContactsContract;

import android.provider.ContactsContract.Contacts;

import android.provider.Settings;

import android.util.Log;

import android.widget.ListView;

import android.widget.SimpleCursorAdapter;

 

 

public class MainActivity extends Activity implements LoaderCallbacks<Cursor> {

private static final String TAG = "ContentUserDemo";

private SimpleCursorAdapter mAdapter;

private LoaderManager.LoaderCallbacks<Cursor> callBacks;

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

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

ListView listView = (ListView) findViewById(R.id.listView);

String[] from = { Settings.System.NAME, Settings.System.VALUE };

// String[] from = { CallLog.Calls.CACHED_NAME, CallLog.Calls.NUMBER };

// String[] from = { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};

// String[] from = { Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL};

int[] to = { R.id.text1, R.id.text2 };

// Initialize the adapter. Note that we pass a 'null' Cursor as the

// third argument. We will pass the adapter a Cursor only when the

// data has finished loading for the first time (i.e. when the

// LoaderManager delivers the data to onLoadFinished). Also note

// that we have passed the '0' flag as the last argument. This

// prevents the adapter from registering a ContentObserver for the

// Cursor (the CursorLoader will do this for us!).

mAdapter = new SimpleCursorAdapter(this, R.layout.row, null, from, to,1);

listView.setAdapter(mAdapter);

 

//The activity which implements LoaderCallbacks<Cursor> interface

callBacks = this;

 

// Initialize the Loader with id '1' and callbacks 'mCallbacks'.

// If the loader doesn't already exist, one is created. Otherwise,

// the already created Loader is reused. In either case, the

// LoaderManager will manage the Loader across the Activity/Fragment

// lifecycle, will receive any new loads once they have completed,

// and will report this new data back to the 'mCallbacks' object.

LoaderManager lm = getLoaderManager();

lm.initLoader(1, null, callBacks);

 

// Get the list view

}

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

// TODO Auto-generated method stub

// Get content provider and cursor

CursorLoader cursor = new CursorLoader(this,Settings.System.CONTENT_URI, null, null, null,null);

// CursorLoader cursor = new CursorLoader(this,CallLog.Calls.CONTENT_URI, null, null, null, null);

// CursorLoader cursor = new CursorLoader(this,ContactsContract.CommonDataKinds.Phone.CONTENT_URI,projection, null, null, null);

//CursorLoader cursor = new CursorLoader(this,Browser.BOOKMARKS_URI, null, null, null, null);

return cursor;

}

 

public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {

// The asynchronous load is complete and the data

// is now available for use. Only now can we associate

// the queried Cursor with the SimpleCursorAdapter.

mAdapter.swapCursor(arg1);

}

 

public void onLoaderReset(Loader<Cursor> arg0) {

// For whatever reason, the Loader's data is now unavailable.

// Remove any references to the old data by replacing it with

// a null Cursor.

mAdapter.swapCursor(null);

}

}

 

  • Below are the screenshots for the application.

 

Pr.Pg border                                              Next Pg