NOTE:

NOTE: Of late, I have been getting requests for very trivial problems that many of you are facing in your day-to-day work. This blog is not to solve your "project" problems - surely not a "Support" site.
I just love to share my knowledge in my spare time and would appreciate any questions or feedback on the articles and code I have shared. I also do appreciate thought-provoking questions that would lead me to write more articles and share.
But please do not put your day-to-day trivial problems here. Even if you do, you most probably would not get a response here.
Thanks

Search This Blog

x

Tuesday 29 September 2009

Content Provider - Android Developer Tutorial (Part 10)


Content Providers are again one of the fundamental building blocks of the Android Platform. So far, we have looked at Activities, Services, which are basic building blocks. We have also looked at intents, notifications and variations of the same. None of these have dealt with stored data. Content Provider brings us to the concept of how to deal with data stored in the Android mobile esp. if the data has to be shared across applications.

Before we move on to shared data, let us understand the basics of data storage support provided by Android. 

There are 4 ways we can store data:

  • 1.    Preferences
  • 2.    Files
  • 3.    RDBMS (SQLite)
  • 4.    Network

Preferences – Preferences are used to store user preferences for a single application or across applications in a mobile. They are typically name-value pairs accessible to the context.

Files – Files can be stored directly on to the mobile or to extended storage mediums. They are by default not accessible to applications other than the one that created it.

Database (RDBMS) – Android support creation of databases based on SQLite. These are again private to the application that created it.

Network – Android provides API support to store data over the network on to a server, probably
Note that all these are various forms of storing data and most often for a single application. Irrespective of how data is stored, if it has to be shared across applications, Here comes the concept of Content Providers.

Content Providers are the only way to share data across Android applications. They store and retrieve data thus making it accessible to all. Android platform provides default implementations of content providers for data types like audio, video, images, contact information etc.

In the sample I would like to first show how to work with existing content providers like the contact information. We will first view the existing contacts on the phone. We will insert a new contact (hardcoded name and phone number), update the same contact and delete the same contact, in this example. Note that the update and delete will not work till we create a contact through this example.

Introduction to Content Providers:

Irrespective of how the data is stored, Content Providers give a uniform interface to access the data. Data is exposed as a simple table with rows and columns where row is a record and column is a particular data type with a specific meaning. Like a row could be about a single person and the columns could be the person’s first name, number, address, email id etc.

Each record is identified by a unique _ID field which is the key to the record. Each content provider exposes a unique URI that identifies its data set uniquely. This URI is equivalent to a table name in a database. The URI consists of various parts: eg: content://com.colllabera.labs.sai/tasks/123 is a unique URI. content:// is a standard prefix. com.collabera.labs.sai is the authority, tasks is the table name, 123 is the unique _ID.

For the native content providers, these unique URIs are declared as constants in an interface. So, in our program we will be using constants like People.CONTENT_URI which internally translates to content://contacts/people

Let us now look at the code to view all the existing contacts:

//Here is the button to click for viewing the contacts
Button view = (Button)findViewById(R.id.viewButton);
//The method / class that gets invoked when the View button is clicked
view.setOnClickListener(new OnClickListener() {
    public void onClick(View v){
       displayContacts();
       Log.i("NativeContentProvider", "Completed Displaying Contact list");
    }
});
//Here is the displayContacts() method
private void displayContacts() {
      String[] columns = new String[] {People.NAME,People.NUMBER};
      Uri mContacts = People.CONTENT_URI;
      Cursor mCur = managedQuery(mContacts, // Contact URI
                  columns,    // Which columns to return
                  null,       // Which rows to return
                  null,       // Where clause parameters
                  null        // Order by clause
                  );
      if (mCur.moveToFirst()) {
            String name = null;
            String phoneNo = null;
            do {
              name = mCur.getString(mCur.getColumnIndex(People.NAME));
              phoneNo = mCur.getString(mCur.getColumnIndex(People.NUMBER));
              Toast.makeText(NativeContentProvider.this, name + " " + phoneNo, Toast.LENGTH_SHORT).show();
            } while (mCur.moveToNext());
      }
}

Here we are using the Activity.managedQuery(..) to create and execute a query against the provided URI. The comments against the parameters in the code is self-explanatory. This returns a cursor object that can be iterated using the two methods moveToFirst() and moveToNext(). For simplicity sake, I have just toasted the contact name and phone number retrieved. An advanced tutorial can start a new activity that can display this in a ListView.

Now, we can move on to creating a new contact. While the button related code will be very similar to the above, let us look at the actual createContact() method.

    private void createContact(String name, String phone) {
      ContentValues contact = new ContentValues();
      contact.put(People.NAME, name);
      insertUri = getContentResolver().insert(People.CONTENT_URI, contact);
      Log.d(getClass().getSimpleName(),insertUri.toString());
      Uri phoneUri = Uri.withAppendedPath(insertUri, People.Phones.CONTENT_DIRECTORY);
      contact.clear();
      contact.put(People.Phones.TYPE, People.TYPE_MOBILE);
      contact.put(People.NUMBER, phone);
      updateUri = getContentResolver().insert(phoneUri, contact);
      Toast.makeText(NativeContentProvider.this, "Created a new contact: " + name + " " + phone, Toast.LENGTH_SHORT).show();
      Log.d(getClass().getSimpleName(),updateUri.toString());
    }

Here we need to understand 2 new classes: ContentResolver and ContentValues. A ContentResolver provides applications access to the content data / model. We can get a handle to a ContentResolver by calling the getContentResolver() method within the Activity. This provides methods to insert, update and delete data. In order to insert data, we need to provide it through a ContentValues object. A ContentValues Object is nothing but a name, value pair where the name of the column is to be mentioned. So, we pass the URI and the ContentValues to insert() method which returns a unique URI with the new ID created. Once we get the ID of the new person/contact inserted, we insert his/her mobile phone details into the related Phones table by using the returned insertUri. The insertUri which is unique to the new record is stored as a class variable to use it in the delete method later. The phoneUri is also stored for updating the same in the updateContact() method later.

Note that People is a class that has implemented various interfaces like android.priovider.BaseColumns, android.provider.Contacts.Phones, android.provider.Contact.PeopleColumns etc. These constants come from the interfaces.

With the above understanding let us see the update and delete methods:

   private void updateContact(String phone) {
      if (updateUri == null) {
            Toast.makeText(NativeContentProvider.this, "There is nothing to update, Please create a contact and then click update", Toast.LENGTH_LONG).show();
      } else {
            ContentValues newPhone = new ContentValues();
            newPhone.put(People.Phones.TYPE, People.TYPE_MOBILE);
            newPhone.put(People.NUMBER, phone);
            getContentResolver().update(updateUri, newPhone, null,null);
            Toast.makeText(NativeContentProvider.this, "Updated the phone number to: " + phone, Toast.LENGTH_SHORT).show();
            Log.i(getClass().getSimpleName(), "Updated the phone number");
      }
    }
   
    private void deleteContact() {
      if (updateUri == null) {
            Toast.makeText(NativeContentProvider.this, "Please create a contact by clicking create button, then I can delete the same", Toast.LENGTH_LONG).show();
           
      } else {
            getContentResolver().delete(insertUri, null, null);
            Toast.makeText(NativeContentProvider.this, "Deleted contact at: " + insertUri.toString(), Toast.LENGTH_SHORT).show();
            updateUri = null;
            insertUri = null;
            Log.i(getClass().getSimpleName(),"Deleted the contact inserted by this program");
      }
    }

These methods only manipulate the freshly created record, for simplicity sake. They call upon the update() and delete() method on the ContentResolver.

The complete code for this example is available here.

Please note that you must add the following permissions to the AndroidManifest.xml file to be able to access the contacts.

<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>

Otherwise you get a SecurityException.

UPDATE: Please note that the article talks about the Contacts API before SDK 2.0. For the newer updated version, please check this article on New Content Provider

50 comments:

  1. Hi Sai Geetha,

    I've tried your tutorial program and everything seems to work perfectly.
    But when I went to "Contacts" which is built in the Android Emulator, I didn't see "Sample Name" in the contact list. The only way I could see "Sample Name" is through Menu->Search Contacts.
    Is there something missing?

    ReplyDelete
  2. Hi MSW,

    There are various options or groups to view the contacts in Android. By default, "My Contacts" group alone is shown. Hence the newly added contact which is not added to the "My Contacts" group does not show up.
    If you go the the menu in contacts and click on "Display Group" and select "All Contacts" you will be able to see the just added "Sample Name" in the contact list.

    ReplyDelete
  3. Hi Sai Geetha,

    I understand now.Thanks for the explanation.
    Could you please give tutorial about sending and receiving chat message using GTalk service?
    I always love your tutorial. :)

    ReplyDelete
  4. Your tutorials hav been a great help to me...
    As a beginner...i find these very useful......Thank you once again..

    I am using android 2.0....which suggests to use android.provider.ContactsContract instead of android.provider.Contacts.People(which is deprecated in this version..)

    so could u please help me to develop an app which can View,Create,Edit and Modify the contact list of android 2 ....

    Thanks in advance..

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Hi Vishnu,

    I will update it to the last API and post it. But it will take a while as I am help up with other things.

    In the meantime, if you do crack it, kindly share the same.

    ReplyDelete
  7. Hi Sai,
    How to use HttpConnections in Android.
    Can u plz give any tutorial for this?

    ReplyDelete
  8. Sai,

    I read your 10 introductory tutorials and they are excellent! Well done!

    ReplyDelete
  9. hi,

    your tutorials were extremely helpful in understanding android as a beginner.
    im just repeating the request that vishnu made, can you please update some of the posts with the new API because some parts of it such as contacts.people are now deprecated.

    Thanks a lot,
    Shoikat

    ReplyDelete
  10. update tutorial (content provider) SDK 2.1??

    thx

    ReplyDelete
  11. Hi Sai Geeta,

    I have some scenarios to work out by using sqlite3.If you can give me your mail ID i can mail you the things .Please help me.

    ReplyDelete
  12. my mail ID is prasanth.shaker@gmail.com

    ReplyDelete
  13. Hi Geetha,

    Can you please explain how to create our own contentProvider with all the utilites and READ/WRITE Permission for other application to use it.

    ReplyDelete
  14. Hi,
    i am developing application for send email with image attachment.i have write code for image first store in sd card and then send email,so i have memory problem accrued,so i want to image will not store in sdcard and then send email with attachment.how is it possible,please give sample code for me..
    Thanks..

    ReplyDelete
  15. Hi Sai,
    Can you help me in setting permissions for the given example in android 2.2.

    ReplyDelete
  16. Hi,

    I am tired of playing with content provider for calendar.I have to add a event in android calendar please help me with this I am using 2.2

    Sam

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. Hey sai,

    i am trying to use a custom content provider with a simple cursor adapter. I saw a while back you were going to write an article on how to get data from content provider and display it in a list view. was wondering if you can point me in the right direction.

    ReplyDelete
  19. is there have to make any change while we use this sample for api level 9...??

    ReplyDelete
  20. Hey bhavana,

    the contacts api is deprecated.. google introduced a new api quite some time ago.. you can look at http://blog.app-solut.com/2011/03/working-with-the-contactscontract-to-query-contacts-in-android for an introduction to the new api

    ReplyDelete
  21. Hi,
    Thank you for giving so many details and am not getting how to access from data base could you please help

    ReplyDelete
  22. Hi,
    i hav run the above code in my machine,
    they are not run properly , its show only NAME,
    not NUMBER

    ReplyDelete
  23. Nice tutorials, I really appreciate them.

    I've been studying Android development for a while, haven't produced nothing commercial yet, hope to do it some day...

    I think that you, being a professional, participated on some projects that weren't about building stand-alone apps... meaning that in some way, the app used the Cloud (sending a file by HTTP, getting some data from a server, etc.)

    Hope you consider this domain enough "thought-provoking" to create a tutorial, I know that I and

    ReplyDelete
  24. Really great tutorial,

    I am newer to the Android,& know my requirement is adding profile picture to the particular contact.

    I am Trying following code it shows SQlite Error & some time it execute with out error but image not set to the contact.
    plz help me,

    i was passing personId which is getting from ContactsContract.Contacts._ID

    Bitmap bitmap=BitmapFactory.decodeFile("/sdcard/Image.jpg");

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);

    ContentValues values = new ContentValues();
    values.put(ContactsContract.Data.RAW_CONTACT_ID, personId);
    values.put(ContactsContract.CommonDataKinds.Photo.PHOTO,
    bytes.toByteArray());
    values.put(ContactsContract.Data.MIMETYPE,
    ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE );
    context.getContentResolver().update
    (ContactsContract.Data.CONTENT_URI, values,
    ContactsContract.Data.RAW_CONTACT_ID + " = " + personId, null);

    ReplyDelete
  25. hai sai geetha gaaru,
    content provider concept is very useful to me as beginer of android.
    what is the differnce between emulator and simulator?

    ReplyDelete
  26. as apple company is using the name "simulator"
    google used the name "Emulator" inorder to simulate our outputs's

    ReplyDelete
  27. Hi Sai,

    I have checked into android database(Contacts2.db)
    and I found that contact is not getting deleted from raw_contact and data table.
    But if I delete contact form android contact application contact is getting deleted from raw_contact and data table.
    Can you please explain why?

    ReplyDelete
  28. Hi,
    I was wondering how to reverse this article, I want to share with the phonebook not the other way around. I have an application that downloads contacts from a webserivce. I would like to share this information with the phonebook but not insert or add it - I want the information to remain stored in the application database.
    Your articles are always very useful I was wondering if you knew how to do this?

    Thanks

    ReplyDelete
  29. can u plz,,, explain the contentObserver concept MAM,,,,

    ReplyDelete
  30. Hello mam ,
    Your tutorial is very good . I tried the first example of Content Provider which is running based on the People.Number and name i.e default property provided by the android itself.
    I m able to get the name of the person saved in the contact successfully but Person.Number is returning null .. can u please provided me some solutions for this .....
    Thanx n advance..

    ReplyDelete
  31. I this tutorial everything is working fine..but number is not displaying..will you please give the solution for that.

    Thank You.

    ReplyDelete
  32. Hi SaiGeetha,

    Thanks for your nice tutorial,im a begginer in android,i have one problem in my project,if you give me solution then it will be of great pleasure.my query is
    Im doing for Turkish Sorting in ICS.
    so i have added new java file TrCursor.java where the sorting rule is defined and used the RuleBasedCollator Concept in android Frameworks and this class i am making use in providers (Contactprovider2.java).but im getting error like
    Error Parsing API.
    i tried a lot but same error.
    is this the limitation of android ICS?
    because in ICS PeopleActivity has replaced contacts module so some new API has added in ICS.
    So please solve my issue.waiting for your reply.

    Thanks in advance

    Regards,
    Chandu

    ReplyDelete
  33. GREAT EXPLANATORY SKILLS !!!
    Thanks a Ton

    ReplyDelete
  34. Hi..
    how to retrieve the contact names and corresponding phone numbers and display it in the list.please give the hint how to solve this..

    Thanks and Regards
    Girish

    ReplyDelete
  35. excellent explanation on contents

    ReplyDelete
  36. Hi Geetha, you are doing Very Great Job, Thanks , for much information,Keep sharing such a wonderful information..!

    ReplyDelete
  37. How we can add photo in contact?

    ReplyDelete
  38. really good tutorial..... :)

    ReplyDelete
  39. store and retrieve data thus making it accessible to all. Android platform provides default implementations of content providers for data types like audio, video, images, contact information.thanks for it.

    ReplyDelete
  40. Hiiiiiii Geetha This is Good. I want Google Maps and Location Based Services tutorial

    ReplyDelete
  41. thanks, really good tutorial

    ReplyDelete
  42. hiii geetha mam,
    i have develope one application in android.in that my mobile call, message,e-mails all are divert on my any friend number when i forgett my mobile in my home or anywhere, so for that i want to help me in designing ,or some layouts from you.this application develope for my last year project MCA.
    also you can suggest me any subject.

    ReplyDelete
  43. great job thanks you..........

    ReplyDelete
  44. Am new to android , so that am not able to move forward with sqlite DB.
    first of all, how to configure sqlite db in our eclipse.
    what are things i should so b4 starting sqlite in my android application.

    ReplyDelete
  45. how to code for
    Listing Calendar Events using content resolver in android.
    Please help me i am new to android...

    ReplyDelete
  46. hi,
    this is very well for us....
    but , we have one problem regarding this...

    can you show pics about its working...how is it working...
    thanks...

    ReplyDelete
  47. Dear saigeetha, In the above example i couldn't see a class (content Provider).
    Pls help out, Is it possible to share stored data with the help of activity?

    Thanks

    ReplyDelete