This example will show you how to use android ContentResolver to read mobile contacts data and display it in a list view and how to add new contact data programmatically.
If you can not watch the above video, you can see it on the youtube URL https://youtu.be/dSLROQgte0Y
1. Android Read Write Contacts Example Overview.
- When you click the first button, it will start another activity AddPhoneContactActivity to let you add a new contact.
- When you click the second button, it will list all the existing contacts and display the name, phone number, and phone type in the below ListView.
- After adding a new contact, you can click the second button again to list newly added user contact.
- All the code use android provided contact content provider to manipulate the data.
1.1 Read Phone Contacts Java Code.
- To read existing contact, you can use the below code.
- First, get the Phone.CONTENT_URI which is a system-provided phone contact URI.
- Then query it and get an SQLite database Cursor. You can loop the cursor to get all existing contacts.
// Get query phone contacts cursor object. Uri readContactsUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; Cursor cursor = getContentResolver().query(readContactsUri, null, null, null, null);
1.2 Add New Contact.
- First, you need to add an empty contact to system contacts, this will just insert an empty record in the contact database without any contact data, it will just return the system-generated raw contact id.
- The content provider URI should use ContactsContract.RawContacts.CONTENT_URI.
// Inser an empty contact. ContentValues contentValues = new ContentValues(); Uri rawContactUri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, contentValues); // Get the newly created contact raw id. long ret = ContentUris.parseId(rawContactUri);
1.3 Add Contact Display Name.
- After adding a new empty contact and get the raw contact id, you should add the contact display name using the below code.
- The content provider URI should use ContactsContract.Data.CONTENT_URI.
private void insertContactDisplayName(Uri addContactsUri, long rawContactId, String displayName) { ContentValues contentValues = new ContentValues(); contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); // Each contact must has an mime type to avoid java.lang.IllegalArgumentException: mimetype is required error. contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); // Put contact display name value. contentValues.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, displayName); getContentResolver().insert(addContactsUri, contentValues); }
1.4 Add Contact Phone Number.
- Then use the below method to add a contact phone number.
- The content provider URI should use ContactsContract.Data.CONTENT_URI also.
private void insertContactPhoneNumber(Uri addContactsUri, long rawContactId, String phoneNumber, String phoneTypeStr) { // Create a ContentValues object. ContentValues contentValues = new ContentValues(); // Each contact must has an id to avoid java.lang.IllegalArgumentException: raw_contact_id is required error. contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); // Each contact must have a mime type to avoid java.lang.IllegalArgumentException: mimetype is required error. contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); // Put phone number value. contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber); // Calculate phone type by user selection. int phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_HOME; if("home".equalsIgnoreCase(phoneTypeStr)) { phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_HOME; }else if("mobile".equalsIgnoreCase(phoneTypeStr)) { phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE; }else if("work".equalsIgnoreCase(phoneTypeStr)) { phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_WORK; } // Put phone type value. contentValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, phoneContactType); // Insert new contact data into phone contact list. getContentResolver().insert(addContactsUri, contentValues); }
2. Android Contact Operation Example Source Code.
2.1 List Exist Contacts Activity.
- ListPhoneContactsActivity.java
package com.dev2qa.example.datasharing.phonecontacts; import android.Manifest; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.ContactsContract; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; import com.dev2qa.example.R; import java.util.ArrayList; import java.util.List; public class ListPhoneContactsActivity extends AppCompatActivity { // Store all phone contacts list. // Each String format is " DisplayName \r\n Phone Number \r\n Phone Type " ( Jerry \r\n 111111 \r\n Home) . private List<String> phoneContactsList = new ArrayList<String>(); // This is the phone contacts list view's data adapter. private ArrayAdapter<String> contactsListDataAdapter; ListView contactsListView = null; private int PERMISSION_REQUEST_CODE_READ_CONTACTS = 1; private int PERMISSION_REQUEST_CODE_WRITE_CONTACTS = 2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_phone_contacts); setTitle("dev2qa.com - Android Content Resolver Example."); // Get contacts list view. contactsListView = (ListView)findViewById(R.id.display_phone_ocntacts_list_view); // Create the list view data adapter. contactsListDataAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, phoneContactsList); // Set data adapter to the list view. contactsListView.setAdapter(contactsListDataAdapter); // Click this button start add phone contact activity. Button addPhoneContactsButton = (Button)findViewById(R.id.add_phone_contacts_button); addPhoneContactsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(!hasPhoneContactsPermission(Manifest.permission.WRITE_CONTACTS)) { requestPermission(Manifest.permission.WRITE_CONTACTS, PERMISSION_REQUEST_CODE_WRITE_CONTACTS); }else { AddPhoneContactActivity.start(getApplicationContext()); } } }); // Click this button to get and display phone contacts in the list view. Button readPhoneContactsButton = (Button)findViewById(R.id.read_phone_contacts_button); readPhoneContactsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(!hasPhoneContactsPermission(Manifest.permission.READ_CONTACTS)) { requestPermission(Manifest.permission.READ_CONTACTS, PERMISSION_REQUEST_CODE_READ_CONTACTS); }else { readPhoneContacts(); } } }); } // Check whether user has phone contacts manipulation permission or not. private boolean hasPhoneContactsPermission(String permission) { boolean ret = false; // If android sdk version is bigger than 23 the need to check run time permission. if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // return phone read contacts permission grant status. int hasPermission = ContextCompat.checkSelfPermission(getApplicationContext(), permission); // If permission is granted then return true. if (hasPermission == PackageManager.PERMISSION_GRANTED) { ret = true; } }else { ret = true; } return ret; } // Request a runtime permission to app user. private void requestPermission(String permission, int requestCode) { String requestPermissionArray[] = {permission}; ActivityCompat.requestPermissions(this, requestPermissionArray, requestCode); } // After user select Allow or Deny button in request runtime permission dialog // , this method will be invoked. @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); int length = grantResults.length; if(length > 0) { int grantResult = grantResults[0]; if(grantResult == PackageManager.PERMISSION_GRANTED) { if(requestCode==PERMISSION_REQUEST_CODE_READ_CONTACTS) { // If user grant read contacts permission. readPhoneContacts(); }else if(requestCode==PERMISSION_REQUEST_CODE_WRITE_CONTACTS) { // If user grant write contacts permission then start add phone contact activity. AddPhoneContactActivity.start(getApplicationContext()); } }else { Toast.makeText(getApplicationContext(), "You denied permission.", Toast.LENGTH_LONG).show(); } } } // Read and display android phone contacts in list view. private void readPhoneContacts() { // First empty current phone contacts list data. int size = phoneContactsList.size(); for(int i=0;i<size;i++) { phoneContactsList.remove(i); i--; size = phoneContactsList.size(); } // Get query phone contacts cursor object. Uri readContactsUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; Cursor cursor = getContentResolver().query(readContactsUri, null, null, null, null); if(cursor!=null) { cursor.moveToFirst(); // Loop in the phone contacts cursor to add each contacts in phoneContactsList. do{ // Get contact display name. int displayNameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME); String userDisplayName = cursor.getString(displayNameIndex); // Get contact phone number. int phoneNumberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); String phoneNumber = cursor.getString(phoneNumberIndex); // Get contact phone type. String phoneTypeStr = "Mobile"; int phoneTypeColumnIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE); int phoneTypeInt = cursor.getInt(phoneTypeColumnIndex); if(phoneTypeInt== ContactsContract.CommonDataKinds.Phone.TYPE_HOME) { phoneTypeStr = "Home"; }else if(phoneTypeInt== ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE) { phoneTypeStr = "Mobile"; }else if(phoneTypeInt== ContactsContract.CommonDataKinds.Phone.TYPE_WORK) { phoneTypeStr = "Work"; } StringBuffer contactStringBuf = new StringBuffer(); contactStringBuf.append(userDisplayName); contactStringBuf.append("\r\n"); contactStringBuf.append(phoneNumber); contactStringBuf.append("\r\n"); contactStringBuf.append(phoneTypeStr); phoneContactsList.add(contactStringBuf.toString()); }while(cursor.moveToNext()); // Refresh the listview to display read out phone contacts. contactsListDataAdapter.notifyDataSetChanged(); } } }
- activity_list_phone_contacts.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <Button android:id="@+id/add_phone_contacts_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Add Phone Contact"/> <Button android:id="@+id/read_phone_contacts_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Read Phone Contact"/> <ListView android:id="@+id/display_phone_ocntacts_list_view" android:layout_width="match_parent" android:layout_height="wrap_content"> </ListView> </LinearLayout>
2.2 Add New Contact Activity.
- AddPhoneContactActivity.java
package com.dev2qa.example.datasharing.phonecontacts; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; import com.dev2qa.example.R; public class AddPhoneContactActivity extends AppCompatActivity { private EditText displayNameEditor; private EditText phoneNumberEditor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_phone_contact); setTitle("dev2qa.com - Android Add Phone Contact Example."); displayNameEditor = (EditText)findViewById(R.id.add_phone_contact_display_name); phoneNumberEditor = (EditText)findViewById(R.id.add_phone_contact_number); // Initialize phone type dropdown spinner. final Spinner phoneTypeSpinner = (Spinner)findViewById(R.id.add_phone_contact_type); String phoneTypeArr[] = {"Mobile", "Home", "Work"}; ArrayAdapter<String> phoneTypeSpinnerAdaptor = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, phoneTypeArr); phoneTypeSpinner.setAdapter(phoneTypeSpinnerAdaptor); // Click this button to save user input phone contact info. Button savePhoneContactButton = (Button)findViewById(R.id.add_phone_contact_save_button); savePhoneContactButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Get android phone contact content provider uri. //Uri addContactsUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; // Below uri can avoid java.lang.UnsupportedOperationException: URI: content://com.android.contacts/data/phones error. Uri addContactsUri = ContactsContract.Data.CONTENT_URI; // Add an empty contact and get the generated id. long rowContactId = getRawContactId(); // Add contact name data. String displayName = displayNameEditor.getText().toString(); insertContactDisplayName(addContactsUri, rowContactId, displayName); // Add contact phone data. String phoneNumber = phoneNumberEditor.getText().toString(); String phoneTypeStr = (String)phoneTypeSpinner.getSelectedItem(); insertContactPhoneNumber(addContactsUri, rowContactId, phoneNumber, phoneTypeStr); Toast.makeText(getApplicationContext(),"New contact has been added, go back to previous page to see it in contacts list." , Toast.LENGTH_LONG).show(); finish(); } }); } // This method will only insert an empty data to RawContacts.CONTENT_URI // The purpose is to get a system generated raw contact id. private long getRawContactId() { // Inser an empty contact. ContentValues contentValues = new ContentValues(); Uri rawContactUri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, contentValues); // Get the newly created contact raw id. long ret = ContentUris.parseId(rawContactUri); return ret; } // Insert newly created contact display name. private void insertContactDisplayName(Uri addContactsUri, long rawContactId, String displayName) { ContentValues contentValues = new ContentValues(); contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); // Each contact must has an mime type to avoid java.lang.IllegalArgumentException: mimetype is required error. contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); // Put contact display name value. contentValues.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, displayName); getContentResolver().insert(addContactsUri, contentValues); } private void insertContactPhoneNumber(Uri addContactsUri, long rawContactId, String phoneNumber, String phoneTypeStr) { // Create a ContentValues object. ContentValues contentValues = new ContentValues(); // Each contact must has an id to avoid java.lang.IllegalArgumentException: raw_contact_id is required error. contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); // Each contact must have a mime type to avoid java.lang.IllegalArgumentException: mimetype is required error. contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); // Put phone number value. contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber); // Calculate phone type by user selection. int phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_HOME; if("home".equalsIgnoreCase(phoneTypeStr)) { phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_HOME; }else if("mobile".equalsIgnoreCase(phoneTypeStr)) { phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE; }else if("work".equalsIgnoreCase(phoneTypeStr)) { phoneContactType = ContactsContract.CommonDataKinds.Phone.TYPE_WORK; } // Put phone type value. contentValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, phoneContactType); // Insert new contact data into phone contact list. getContentResolver().insert(addContactsUri, contentValues); } // ListPhoneContactsActivity use this method to start this activity. public static void start(Context context) { Intent intent = new Intent(context, AddPhoneContactActivity.class); context.startActivity(intent); } }
- activity_add_phone_contact.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="1dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:width="0dp" android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Display Name : " android:gravity="right"/> <EditText android:id="@+id/add_phone_contact_display_name" android:layout_weight="2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:width="0dp" android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Phone Number : " android:gravity="right" /> <EditText android:id="@+id/add_phone_contact_number" android:layout_weight="2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:width="0dp" android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Phone Type : " android:gravity="right" /> <Spinner android:id="@+id/add_phone_contact_type" android:layout_weight="1.3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:spinnerMode="dropdown"/> </LinearLayout> <Button android:id="@+id/add_phone_contact_save_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Save Phone Contact"/> </LinearLayout>
2.3 Android Manifest Xml File.
- AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.dev2qa.example"> <!-- Need below permissions.--> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".datasharing.contacts.ListPhoneContactsActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".datasharing.contacts.AddPhoneContactActivity" /> </application> </manifest>
Reference
Great example!!! Thank you very much.