Understand Content Provider In Xamarin With Visual Studio 2015


Every Android application is made of four parts - Activity, Broadcast Receiver, ContentProvider and Service. ContentProvider manages access to central repository of data, and provides data from one application to another application whenever required, on a request basis. This request resolves around ContentResolver. ContentProvider works in data access layer in Android applications. The interaction between ContentProvider and other components is shown in the below figure.



Lifecycle of Accessing ContentProvider

A pattern for accessing a ContentProvider from our User Interface uses a CursorLoader to run a query in the background mode. Activity or Fragment in our User Interface calls a CursorLoader to the query, which gets the ContentProvider using the ContentResolver. Accessing ContentProvider pattern is shown in below figure. 


There are five built in ContentProviders - Browser, CallLog Contacts, Media Store, Settings, User Dictionary, and Voicemail.

In this article, I am using Contacts built-in ContentProvider for reading contacts and adding new contacts.

Step 1 Create new project for Android application 


I have selected “Blank App (Android)” template for this article.

Step 2 Adding User Permission to read and write contacts

We need to get permission from Android OS for reading and writing Contacts data from storage. We can do this in two ways.

1) Add <user-permission> in AndroidMenifest.xml
2) By right clicking on project, select ‘property’, select AndroidMenifest.xml, Tick “READ_CONTACTS” and “WRITE_CONTACTS”.
By doing this, you can find <user-permission> in AndroidMenifest.xml.
  1. <?xml version="1.0"encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ContentProviderDemo.ContentProviderDemo" 
  3.                 android:versionCode="1" android:versionName="1.0" android:installLocation="auto">  
  4.     <uses-sdk android:minSdkVersion="16" />  
  5.     <uses-permission android:name="android.permission.READ_CONTACTS" />  
  6.     <uses-permission android:name="android.permission.WRITE_CONTACTS" />  
  7.     <application android:label="ContentProviderDemo"></application>  
  8. </manifest>  

Step 3 Application Layout

In this article, I have used two layouts and two Activities. First is “main.axml” where I have used two buttons (one for “Read Contacts” and other for “Add New Contact”) and a Listview to display Contacts. 

“addnewcontact.axml” layout file contains three editboxes where I have taken three inputs from user as “First Name”, “Last Name” and “Phone no”, and two buttons, “Add” for adding a new contact, and “Cancel” for canceling the operation. Designer view of “main.axml” and “addnewcontact.axml” is shown below:

Step 4 Read Contacts and Add new Contact

My project contains two Activity classes -  “MainActivity” and “Addnewcontact”. As I discussed previously, for accessing data, we need to request and for that, we need to give URI string to “CursorLoader”.

It will pass to “ContentResolver” as I discussed previously in “Accessing ContentProvider” section. For Read Contacts, first I need to set “CursorLoader” and set cursor in background mode using “LoadInBackground()” method. Final code snippet of OnCreate() method of “MainActivity.cs” is shown below. 

OnCreate( ) method of MainActivity.cs

  1. public class MainActivity : Activity  
  2. {  
  3.     private SimpleCursorAdapter adapter;  
  4.     ListView contactlist;  
  5.     protected override void OnCreate(Bundle bundle)  
  6.     {  
  7.            base.OnCreate(bundle);  
  8.            // Set our view from the "main" layout resource  
  9.            SetContentView(Resource.Layout.Main);  
  10.            Button readcontact = (Button)FindViewById(Resource.Id.btnreadcontacts);  
  11.            Button addnewcontact = (Button)FindViewById(Resource.Id.btnaddnewcontacts);  
  12.            readcontact.Click += Readcontact_Click;  
  13.            addnewcontact.Click += Addnewcontact_Click;  
  14. }  
  16. private void Addnewcontact_Click(object sender, System.EventArgs e)  
  17. {  
  18.             Intent addcontact = new Intent(thistypeof(Addnewcontact));  
  19.             StartActivity(addcontact);  
  20. }  
  22. private void Readcontact_Click(object sender, System.EventArgs e)  
  23. {  
  24.              var uri = ContactsContract.Contacts.ContentUri;  
  25.              contactlist = (ListView)FindViewById(Resource.Id.contactlist);  
  26.              string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id,  
  27.                                                   ContactsContract.Contacts.InterfaceConsts.DisplayName  
  28.                                                 };  
  29.               var loader = new CursorLoader(this, uri, projection, nullnullnull);  
  30.               var cursor = (ICursor)loader.LoadInBackground();  
  31.               var fromColumns = new string[] {ContactsContract.Contacts.InterfaceConsts.DisplayName };  
  32.               var toControlIds = new int[] { Android.Resource.Id.Text1 };  
  33.               adapter = new SimpleCursorAdapter(this, Android.Resource.Layout.SimpleListItem1, cursor, fromColumns, toControlIds);  
  34.               contactlist.Adapter = adapter;  
  35. }  
  36. }  

In the above code, for accessing contacts of Android phone, we need to use Uri as “ContactsContract.Contacts.ContentUri”. I have used SimpleCursorAdapter() method which is easy adapter to bind columns value from cursor to View.

OnCreate() method of Addnewcontact.cs

  1. protected override void OnCreate(Bundle savedInstanceState)  
  2. {  
  3.          base.OnCreate(savedInstanceState);  
  4.          SetContentView(Resource.Layout.addnewcontact);  
  6.          Button addnewcontact = (Button)FindViewById(Resource.Id.btnadd);  
  7.          Button cancel = (Button)FindViewById(Resource.Id.btncancel);  
  9.          addnewcontact.Click += Addnewcontact_Click;  
  10.          cancel.Click += Cancel_Click;  
  11. }  
  13. private void Cancel_Click(object sender, EventArgs e)  
  14. {  
  15.                OnBackPressed();  
  16. }  
  17. private void Addnewcontact_Click(object sender, EventArgs e)  
  18. {  
  19.                EditText txtfirstname = (EditText)FindViewById(Resource.Id.edtfirstname);  
  20.                EditText txtlastname = (EditText)FindViewById(Resource.Id.edtlastname);  
  21.                EditText txtphoneno = (EditText)FindViewById(Resource.Id.edtphoneno);  
  22.                string lastname = (txtlastname.Text).ToString();  
  23.                string firstname = (txtfirstname.Text).ToString();  
  24.                string phone = (txtphoneno.Text).ToString();  
  26.                List<ContentProviderOperation>contactadd = new List<ContentProviderOperation>();  
  28.                ContentProviderOperation.Builder builder = ContentProviderOperation.NewInsert(ContactsContract.RawContacts.ContentUri);  
  29.                builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountType, null);  
  30.                builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountName, null);  
  31.                contactadd.Add(builder.Build());  
  33.                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);  
  34.                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);  
  35.                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,  
  36.                                            ContactsContract.CommonDataKinds.StructuredName.ContentItemType);  
  37.                builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.FamilyName, lastname);  
  38.                builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.GivenName, firstname);  
  39.                contactadd.Add(builder.Build());  
  41.                //Add Phone Number  
  42.                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);  
  43.                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);  
  44.                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,  
  45.                                               ContactsContract.CommonDataKinds.Phone.ContentItemType);  
  46.                builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, phone);  
  47.                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,  
  48.                                               ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);  
  49.                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Label, "Mobile");  
  50.                contactadd.Add(builder.Build());  
  52.            //Add the new contact  
  53.            ContentProvider Result[] res;  
  54.             try  
  55.             {  
  56.                 res = ContentResolver.ApplyBatch(ContactsContract.Authority, contactadd);  
  57.                 Toast.MakeText(this"Contact added sucessfully", ToastLength.Short).Show();  
  58.             }  
  59.             catch  
  60.             {  
  61.                 Toast.MakeText(this"Contact not added", ToastLength.Long).Show();  
  62.             }  
  63.         }  
  64. }  

In the above code snippet, I used OnBackPressed() method for click event of “Cancel” button that takes us back to “MainActivity”. Also, you can see that in the above code, “contactadd” is the List where I am collecting user entered information i.e. first name, last name, and phone no. Then, I am adding that contact using ContentResolver.


Below, you can see that we can read contacts and we can add new contact. By default, I am setting phone number type as “Mobile”. You can see this in the above snippet code.


In this article, we learned about the lifecycle of ContentProvider, how to add user permission in Application, and how to use built-in ContentProvider.

Up Next
    Ebook Download
    View all
    View all