-
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.
- <?xml version="1.0"encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ContentProviderDemo.ContentProviderDemo"
- android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
- <uses-sdk android:minSdkVersion="16" />
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS" />
- <application android:label="ContentProviderDemo"></application>
- </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
- public class MainActivity : Activity
- {
- private SimpleCursorAdapter adapter;
- ListView contactlist;
- protected override void OnCreate(Bundle bundle)
- {
- base.OnCreate(bundle);
-
- SetContentView(Resource.Layout.Main);
- Button readcontact = (Button)FindViewById(Resource.Id.btnreadcontacts);
- Button addnewcontact = (Button)FindViewById(Resource.Id.btnaddnewcontacts);
- readcontact.Click += Readcontact_Click;
- addnewcontact.Click += Addnewcontact_Click;
- }
-
- private void Addnewcontact_Click(object sender, System.EventArgs e)
- {
- Intent addcontact = new Intent(this, typeof(Addnewcontact));
- StartActivity(addcontact);
- }
-
- private void Readcontact_Click(object sender, System.EventArgs e)
- {
- var uri = ContactsContract.Contacts.ContentUri;
- contactlist = (ListView)FindViewById(Resource.Id.contactlist);
- string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id,
- ContactsContract.Contacts.InterfaceConsts.DisplayName
- };
- var loader = new CursorLoader(this, uri, projection, null, null, null);
- var cursor = (ICursor)loader.LoadInBackground();
- var fromColumns = new string[] {ContactsContract.Contacts.InterfaceConsts.DisplayName };
- var toControlIds = new int[] { Android.Resource.Id.Text1 };
- adapter = new SimpleCursorAdapter(this, Android.Resource.Layout.SimpleListItem1, cursor, fromColumns, toControlIds);
- contactlist.Adapter = adapter;
- }
- }
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
- protected override void OnCreate(Bundle savedInstanceState)
- {
- base.OnCreate(savedInstanceState);
- SetContentView(Resource.Layout.addnewcontact);
-
- Button addnewcontact = (Button)FindViewById(Resource.Id.btnadd);
- Button cancel = (Button)FindViewById(Resource.Id.btncancel);
-
- addnewcontact.Click += Addnewcontact_Click;
- cancel.Click += Cancel_Click;
- }
-
- private void Cancel_Click(object sender, EventArgs e)
- {
- OnBackPressed();
- }
- private void Addnewcontact_Click(object sender, EventArgs e)
- {
- EditText txtfirstname = (EditText)FindViewById(Resource.Id.edtfirstname);
- EditText txtlastname = (EditText)FindViewById(Resource.Id.edtlastname);
- EditText txtphoneno = (EditText)FindViewById(Resource.Id.edtphoneno);
- string lastname = (txtlastname.Text).ToString();
- string firstname = (txtfirstname.Text).ToString();
- string phone = (txtphoneno.Text).ToString();
-
- List<ContentProviderOperation>contactadd = new List<ContentProviderOperation>();
-
- ContentProviderOperation.Builder builder = ContentProviderOperation.NewInsert(ContactsContract.RawContacts.ContentUri);
- builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountType, null);
- builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountName, null);
- contactadd.Add(builder.Build());
-
- builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
- builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
- builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
- ContactsContract.CommonDataKinds.StructuredName.ContentItemType);
- builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.FamilyName, lastname);
- builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.GivenName, firstname);
- contactadd.Add(builder.Build());
-
-
- builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
- builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
- builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
- ContactsContract.CommonDataKinds.Phone.ContentItemType);
- builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, phone);
- builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
- ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
- builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Label, "Mobile");
- contactadd.Add(builder.Build());
-
-
- ContentProvider Result[] res;
- try
- {
- res = ContentResolver.ApplyBatch(ContactsContract.Authority, contactadd);
- Toast.MakeText(this, "Contact added sucessfully", ToastLength.Short).Show();
- }
- catch
- {
- Toast.MakeText(this, "Contact not added", ToastLength.Long).Show();
- }
- }
- }
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.
Output
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.
Summary
In this article, we learned about the lifecycle of ContentProvider, how to add user permission in Application, and how to use built-in ContentProvider.