<h3><span style="color: #000080;"><strong>ContentProvider</strong></span></h3>
<p>A <strong><span style="color: #008000;">ContentProvider</span></strong> provides data from one application to another, when requested. It manages access to a structured set of data. It provides mechanisms for defining data security(i.e. by enforcing read/write permissions)<em>. </em>ContentProvider offer a standard interface that connects data in one process with code running in another process.</p>
<p>When an application wants to access the data of a ContentProvider, it makes a request. These requests are handled by the <span style="color: #008000;"><strong>ContentResolver</strong></span> object, which communicates with the ContentProvider as a client. The provider object receives data requests from clients, performs the requested action, and returns the results in <strong><span style="color: #008000;">cursor</span></strong> format.</p>
<p>In this tutorial, I will create two apps <strong><span style="color: #0000ff;">MyContacts App</span></strong> and <strong><span style="color: #0000ff;">ContactList App</span></strong> and I will demonstrate you how ContactList App will use the MyContact App&#8217;s data (stored in SQLite database ) using contentProvider.</p>
<p>Get <span style="color: #000080;"><strong>GITHUB</strong></span> code from <span style="color: #00ff00;"><span style="color: #0000ff;"><a style="color: #0000ff;" href="https://github.com/arunk7839/contentprovider"><strong>Here</strong></a></span>.</span></p>
<p><amp-youtube layout="responsive" width="1200" height="900" data-videoid="FCvmrXcwzeU" title="Android Content Provider Example using SQLite Database"><a placeholder href="https://www.youtube.com/watch?v=FCvmrXcwzeU"><img src="https://i.ytimg.com/vi/FCvmrXcwzeU/hqdefault.jpg" layout="fill" object-fit="cover" alt="Android Content Provider Example using SQLite Database"></a></amp-youtube></p>
<h3><strong><span style="color: #000080;">Creating a New Project</span></strong></h3>
<p><strong>1</strong>. Create a new project named <span style="color: #0000ff;"><strong>MyContacts</strong></span> in <span style="color: #008000;"><strong>Android Studio</strong></span> from <strong><span style="color: #008000;">File</span> ⇒ <span style="color: #008000;">New Project</span></strong> by filling the required details. When it prompts you to select the activity, choose <span style="color: #008000;"><strong>Empty Activity</strong></span> and continue.</p>
<p><strong>2</strong>. Open <span style="color: #008000;"><strong>build.gradle</strong></span> located in app level and add the following dependency.</p>
<p><strong><span style="color: #0000ff;">build.gradle</span></strong></p>
<pre><code>dependencies {
 
 compile 'com.android.support:design:27.1.1'
 
 <span style="color: #008000;"><strong> //recyclerView</strong></span>
 implementation 'com.android.support:recyclerview-v7:27.0.2'
 
}</code></pre>
<h3><span style="color: #000080;"><strong>Create SQLite Database for MyContacts App</strong></span></h3>
<p><strong>3</strong>. Create a new Java class <span style="color: #008000;"><strong>DBOpenHelper</strong></span> and add the following code. This is our DBHelper class, here we are creating the Contacts Database.</p>
<p><strong><span style="color: #0000ff;">DBOpenHelper.Java</span></strong></p>
<pre><code>package com.c1ctech.mycontacts;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBOpenHelper extends SQLiteOpenHelper {

 <strong><span style="color: #008000;">//Constants for db name and version</span></strong>
 private static final String DATABASE_NAME = "contacts.db";
 private static final int DATABASE_VERSION = 1;

 <strong><span style="color: #008000;"> //Constants for table and columns</span></strong>
 public static final String TABLE_CONTACTS = "contacts";
 public static final String CONTACT_ID = "_id";
 public static final String CONTACT_NAME = "contactName";
 public static final String CONTACT_PHONE = "contactPhone";
 public static final String CONTACT_CREATED_ON = "contactCreationTimeStamp";

 public static final String[] ALL_COLUMNS =
 {CONTACT_ID, CONTACT_NAME, CONTACT_PHONE, CONTACT_CREATED_ON};

 <strong><span style="color: #008000;"> //Create Table</span></strong>
 private static final String CREATE_TABLE =
 "CREATE TABLE " + TABLE_CONTACTS + " (" +
 CONTACT_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
 CONTACT_NAME + " TEXT, " +
 CONTACT_PHONE + " TEXT, " +
 CONTACT_CREATED_ON + " TEXT default CURRENT_TIMESTAMP" +
 ")";

 public DBOpenHelper(Context context) {
 super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase sqLiteDatabase) {
 sqLiteDatabase.execSQL(CREATE_TABLE);
 }

 @Override
 public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
 sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
 onCreate(sqLiteDatabase);
 }
}
</code></pre>
<h3><span style="color: #000080;"><strong>Create Custom Android Content Provider</strong></span></h3>
<p><strong>4</strong>. Create a new Java class named <span style="color: #008000;"><strong>ContactsProvider</strong></span> and make it as subclass of <span style="color: #008000;"><strong>ContentProvider</strong></span> and add the below code.</p>
<h4><span style="color: #000080;"><strong>Creating ContentUri</strong></span></h4>
<p><strong><span style="color: #008000;">ContactsProvider</span></strong> is a subclass of <span style="color: #008000;"><strong>ContentProvider</strong></span> and in order to identify the data in the provider we use <strong><span style="color: #008000;">Content URIs</span></strong>. A Content URI has the following format:</p>
<div id="highlighter_705376" class="syntaxhighlighter ">
<div class="lines">
<pre class="line alt1"><strong><span style="color: #000080;">content://<;authority>;/<;path>;/<;id>;</span></strong></pre>
<div><strong><span style="color: #0000ff;">content:// :</span></strong> Standard prefix indicating the data is controlled by content provider.</div>
<div><strong><span style="color: #0000ff;">Authority : </span></strong>Uniquely identify the particular content provider(package name).</div>
<div><strong><span style="color: #0000ff;">path :</span></strong> Used to determine the type of data(table or file) being requested.</div>
<div><strong><span style="color: #0000ff;">id :</span></strong> specifies which record(row) is being requested.(optional).</div>
<div></div>
<div></div>
<div>
<pre><code>private static final String AUTHORITY = "com.c1ctech.mycontacts";
private static final String BASE_PATH = "contacts";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);</code></pre>
</div>
</div>
</div>
<h4><span style="color: #000080;"><strong>Creating UriMatcher</strong></span></h4>
<p>Remember the ContentResolver is not aware of the internal implementation of our Content Provider class, so whenever we receive a call from the ContentResolver we have to perform an internal check to see if the call was for a the whole table or for a single row in the table.</p>
<p>The way we determine if the call is for a specific row on the table is if the calls contains any qualifier after the table name such as <span style="color: #008000;"><strong>/authority/path/table/2</strong></span> and if the calls is the format of say <strong><span style="color: #008000;">/authority/path/table</span></strong> then we know it is a query for the table.</p>
<p>the provider API includes the convenience class <span style="color: #008000;"><strong>UriMatcher</strong></span>, which maps content URI &#8220;patterns&#8221; to integer values. Add the following code to your class , the “<strong><span style="color: #008000;">#</span></strong>” represents any number after the table indicating a table row.</p>
<pre><code>private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {
 uriMatcher.addURI(AUTHORITY, BASE_PATH, CONTACTS);
 uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CONTACT_ID);
}</code></pre>
<h4><strong><span style="color: #000080;">Override ContentProvider&#8217;s Methods</span></strong></h4>
<p>Here is the list of methods which you need to override in <strong><span style="color: #008000;">ContentProvider</span></strong> class to have your ContentProvider working.All of these methods except <strong><span style="color: #008000;">onCreate()</span></strong> are called by a client application that is attempting to access your content provider:</p>
<ul>
<li><strong><span style="color: #0000ff;">onCreate() </span></strong>method is called when the provider is started.</li>
<li><strong><span style="color: #0000ff;">query()</span></strong> method retrieves data from your provider.The result is returned as a Cursor object.</li>
<li><strong><span style="color: #0000ff;">insert()</span></strong> method inserts a new record into the content provider.Return a content URI for the newly-inserted row.</li>
<li><strong><span style="color: #0000ff;">delete()</span></strong> method deletes an existing record from the content provider.Return the number of rows deleted.</li>
<li><strong><span style="color: #0000ff;">update()</span></strong> method updates an existing record from the content provider.Return the number of rows updated.</li>
<li><strong><span style="color: #0000ff;">getType()</span></strong> method returns the MIME type corresponding to a content URI.</li>
</ul>
<p><strong><span style="color: #0000ff;">ContactsProvider.Java</span></strong></p>
<pre><code>package com.c1ctech.mycontacts;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;

public class ContactsProvider extends ContentProvider {

 private static final String AUTHORITY = "com.c1ctech.mycontacts";
 private static final String BASE_PATH = "contacts";
 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

 private static final int CONTACTS = 1;
 private static final int CONTACT_ID = 2;

 private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

 static {
 uriMatcher.addURI(AUTHORITY, BASE_PATH, CONTACTS);
 uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CONTACT_ID);
 }

 private SQLiteDatabase database;

 @Override
 public boolean onCreate() {
 DBOpenHelper helper = new DBOpenHelper(getContext());
 database = helper.getWritableDatabase();
 return true;
 }

 @Nullable
 @Override
 public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
 Cursor cursor;
 switch (uriMatcher.match(uri)) {
 case CONTACTS:
 cursor = database.query(DBOpenHelper.TABLE_CONTACTS, DBOpenHelper.ALL_COLUMNS,
 s, null, null, null, DBOpenHelper.CONTACT_NAME + " ASC");


 break;
 default:
 throw new IllegalArgumentException("This is an Unknown URI " + uri);
 }
 cursor.setNotificationUri(getContext().getContentResolver(), uri);

 return cursor;
 }

 @Nullable
 @Override
 public String getType(Uri uri) {

 switch (uriMatcher.match(uri)) {
 case CONTACTS:
 return "vnd.android.cursor.dir/contacts";
 default:
 throw new IllegalArgumentException("This is an Unknown URI " + uri);
 }
 }

 @Nullable
 @Override
 public Uri insert(Uri uri, ContentValues contentValues) {
 long id = database.insert(DBOpenHelper.TABLE_CONTACTS, null, contentValues);

 if (id >; 0) {
 Uri _uri = ContentUris.withAppendedId(CONTENT_URI, id);
 getContext().getContentResolver().notifyChange(_uri, null);

 return _uri;
 }
 throw new SQLException("Insertion Failed for URI :" + uri);

 }

 @Override
 public int delete(Uri uri, String s, String[] strings) {
 int delCount = 0;
 switch (uriMatcher.match(uri)) {
 case CONTACTS:
 delCount = database.delete(DBOpenHelper.TABLE_CONTACTS, s, strings);
 break;
 default:
 throw new IllegalArgumentException("This is an Unknown URI " + uri);
 }
 getContext().getContentResolver().notifyChange(uri, null);
 return delCount;
 }

 @Override
 public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
 int updCount = 0;
 switch (uriMatcher.match(uri)) {
 case CONTACTS:
 updCount = database.update(DBOpenHelper.TABLE_CONTACTS, contentValues, s, strings);
 break;
 default:
 throw new IllegalArgumentException("This is an Unknown URI " + uri);
 }
 getContext().getContentResolver().notifyChange(uri, null);
 return updCount;
 }
}</code></pre>
<h3><span style="color: #000080;"><strong>Register the Content Provider</strong></span></h3>
<p><strong>5</strong>. We need to provide an entry for our custom Android Content Provider in the<span style="color: #008000;"> <strong>AndroidManifest.xml</strong></span></p>
<p>Open your <span style="color: #008000;"><strong>AndroidManifest.xml</strong></span> and add the permissions and provider entry as in the following code.</p>
<p>we need to provide the authority and read and write permissions here.<br />
using <span style="color: #008000;"><strong>android:exported=”true”</strong></span> our provider becomes available to other applications.</p>
<p><span style="color: #0000ff;"><strong>AndroidManifest.xml</strong></span></p>
<pre><code><;?xml version="1.0" encoding="utf-8"?>;
<;manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.c1ctech.mycontacts">;

 <;permission android:name="com.c1ctech.mycontacts.READ_DATABASE" android:protectionLevel="normal" />;
 <;permission android:name="com.c1ctech.mycontacts.WRITE_DATABASE" android:protectionLevel="normal" />;

 <;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=".MainActivity">;
 <;intent-filter>;
 <;action android:name="android.intent.action.MAIN" />;

 <;category android:name="android.intent.category.LAUNCHER" />;
 <;/intent-filter>;
 <;/activity>;

 <;provider
 android:authorities="com.c1ctech.mycontacts"
 android:name=".ContactsProvider"
 android:exported="true"
 android:readPermission="com.c1ctech.mycontacts.READ_DATABASE"
 android:writePermission="com.c1ctech.mycontacts.WRITE_DATABASE"
 />;
 <;/application>;
<;/manifest>;
</code></pre>
<h3><span style="color: #000080;"><strong>Creating Layouts</strong></span></h3>
<p><strong>6</strong>. Open <span style="color: #008000;"><strong>activity_main</strong></span> and write the below code.It contains one recyclerView and one floatingActionButton(ic_input_add) for adding contacts in recyclerview.</p>
<p><strong><span style="color: #0000ff;">activity_main.xml</span></strong></p>
<pre><code><;?xml version="1.0" encoding="utf-8"?>;
<;android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".MainActivity">;

 <;android.support.design.widget.AppBarLayout
 android:layout_height="wrap_content"
 android:layout_width="match_parent"
 android:theme="@style/AppTheme.AppBarOverlay">;

 <;android.support.v7.widget.Toolbar
 android:id="@+id/toolbar"
 android:layout_width="match_parent"
 android:layout_height="?attr/actionBarSize"
 android:background="?attr/colorPrimary"
 app:popupTheme="@style/AppTheme.PopupOverlay" />;


 <;/android.support.design.widget.AppBarLayout>;
 <;RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">;

 <;android.support.v7.widget.RecyclerView
 android:layout_marginTop="70dp"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:id="@+id/contact_list"/>;

 <;/RelativeLayout>;

 <;android.support.design.widget.FloatingActionButton
 android:id="@+id/fab"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="bottom|end"
 android:layout_margin="16dp"
 app:srcCompat="@android:drawable/ic_input_add" />;

<;/android.support.design.widget.CoordinatorLayout>;</code></pre>
<p><strong>7</strong>. Create a new layout <strong><span style="color: #008000;">dialog_contact_details</span> </strong>and write the below code.It represents the layout set for an <span style="color: #008000;"><strong>Alertdialog</strong></span>.</p>
<p><strong><span style="color: #0000ff;">dialog_contact_details.xml</span></strong></p>
<pre><code><;?xml version="1.0" encoding="utf-8"?>;
<;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/layout_root"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 android:padding="10dp">;

 <;TextView
 android:id="@+id/text_view_emp_id"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="center"
 android:text="@string/enter_contact_details"
 android:textSize="20sp"
 android:textStyle="bold" />;

 <;EditText
 android:id="@+id/editTextDialogNameInput"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:hint="@string/enterName" />;


 <;EditText
 android:id="@+id/editTextDialogPhoneInput"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:hint="@string/enterPhoneNumber" />;

<;/LinearLayout>;</code></pre>
<p><strong>8</strong>. Under <span style="color: #008000;"><strong>res->;menu</strong></span> folder create a new menu resource file <span style="color: #008000;"><strong>main_menu</strong></span> and write the below code.It contains one item <span style="color: #008000;"><strong>deleteAllContacts</strong></span> used to delete all contacts stored in provider.</p>
<p><span style="color: #0000ff;"><strong>main_menu.xml</strong></span></p>
<pre><code><;menu xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 tools:context="com.androidtutorialpoint.mycontacts.MainActivity">;
 <;item
 android:id="@+id/deleteAllContacts"
 android:orderInCategory="100"
 android:title="@string/delete_all_contacts"
 app:showAsAction="never" />;
<;/menu>;
</code></pre>
<h4><strong><span style="color: #000080;">Creating Adapter For RecyclerView</span></strong></h4>
<p><strong>9</strong>. Create a model class <strong><span style="color: #008000;">Contact</span></strong> in your root folder(com.c1ctech.mycontacts) used while working with recyclerView.</p>
<p><strong><span style="color: #0000ff;">Contact.Java</span></strong></p>
<pre><code>package com.c1ctech.mycontacts;

public class Contact {

 private String contact_name;
 private String contact_phone;

 public Contact(String contact_name, String contact_phone) {
 this.contact_name = contact_name;
 this.contact_phone = contact_phone;
 }

 public String getContact_name() {
 return contact_name;
 }

 public void setContact_name(String contact_name) {
 this.contact_name = contact_name;
 }

 public String getContact_phone() {
 return contact_phone;
 }

 public void setContact_phone(String contact_phone) {
 this.contact_phone = contact_phone;
 }
}</code></pre>
<p><strong>10</strong>. Create a new layout <span style="color: #008000;"><strong>contact_list_item</strong></span> and write the below code.It represents the layout of a single item of a <strong><span style="color: #008000;">recyclerview</span></strong> .</p>
<p><strong><span style="color: #0000ff;">contact_list_item.xml</span></strong></p>
<!-- WP QUADS Content Ad Plugin v. 2.0.98.1 -->
<div class="quads-location quads-ad2" id="quads-ad2" style="float:none;margin:0px;">

</div>

<pre><code><;?xml version="1.0" encoding="utf-8"?>;
<;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:gravity="center_vertical"
 android:padding="4dp">;

 <;ImageView
 android:id="@+id/imageDocIcon"
 android:layout_width="72dp"
 android:layout_height="72dp"
 android:src="@drawable/profile_pic" />;

 <;TextView
 android:id="@+id/nameTextView"
 android:layout_width="wrap_content"
 android:layout_height="36dp"
 android:layout_alignParentEnd="true"
 android:layout_alignParentRight="true"
 android:layout_marginLeft="15dp"
 android:layout_marginTop="5dp"
 android:layout_toEndOf="@+id/imageDocIcon"
 android:layout_toRightOf="@+id/imageDocIcon"
 android:text="Dummy Text"
 android:textColor="@android:color/black"
 android:textSize="20sp"
 android:textStyle="bold" />;

 <;TextView
 android:id="@+id/phoneTextView"
 android:layout_width="match_parent"
 android:layout_height="36dp"
 android:layout_alignParentEnd="true"
 android:layout_alignParentRight="true"
 android:layout_below="@+id/nameTextView"
 android:layout_marginLeft="15dp"
 android:layout_toEndOf="@+id/imageDocIcon"
 android:layout_toRightOf="@+id/imageDocIcon"
 android:text="Dummy Text"
 android:textColor="@android:color/black"
 android:textSize="15sp" />;

<;/RelativeLayout>;</code></pre>
<p><strong>11</strong>. Create a class named <strong><span style="color: #008000;">ContactsAdapter</span></strong> and write the below code.Its object is used to set as adapter in recyclerView.</p>
<p><strong><span style="color: #0000ff;">ContactsAdapter.Java</span></strong></p>
<pre><code>package com.c1ctech.mycontacts;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.widget.TextView;

import java.util.List;

public class ContactsAdapter extends RecyclerView.Adapter<;ContactsAdapter.ViewHolder>; {


 Context mContext;
 private List<;Contact>; items;

 public ContactsAdapter(Context mContext, List<;Contact>; items) {
 this.mContext = mContext;
 this.items = items;
 }

 @NonNull
 @Override
 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 View v = LayoutInflater.from(mContext).inflate(R.layout.contact_list_item, parent, false);
 return new ViewHolder(v);
 }

 @Override
 public void onBindViewHolder(ViewHolder holder, int position) {
 Contact item = items.get(position);
 holder.phone_no.setText(item.getContact_phone());
 holder.name.setText(item.getContact_name());

 }

 @Override
 public int getItemCount() {
 return items.size();
 }

 public static class ViewHolder extends RecyclerView.ViewHolder {
 public TextView name;
 public TextView phone_no;

 public ViewHolder(View itemView) {
 super(itemView);
 name = (TextView) itemView.findViewById(R.id.nameTextView);
 phone_no = (TextView) itemView.findViewById(R.id.phoneTextView);
 }
 }
}</code></pre>
<p><strong>12</strong>. Now open <strong><span style="color: #008000;">MainActivity</span></strong> and write the below code.</p>
<p><strong><span style="color: #0000ff;">MainActivity.Java</span></strong></p>
<pre><code>package com.c1ctech.mycontacts;

import android.app.LoaderManager;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<;Cursor>; {

 ContactsAdapter adapter;
 RecyclerView rv_list;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);


 rv_list = (RecyclerView) findViewById(R.id.contact_list);
 rv_list.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
 rv_list.setLayoutManager(new LinearLayoutManager(this));

 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 setSupportActionBar(toolbar);
 getLoaderManager().initLoader(0, null, this);
 FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
 fab.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {

 LayoutInflater li = LayoutInflater.from(MainActivity.this);
 View getEmpIdView = li.inflate(R.layout.dialog_contact_details, null);

 AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);

 <strong><span style="color: #008000;">// set dialog_contact_details.xmll to alertdialog builder</span></strong>
 alertDialogBuilder.setView(getEmpIdView);

 final EditText nameInput = (EditText) getEmpIdView.findViewById(R.id.editTextDialogNameInput);
 final EditText phoneInput = (EditText) getEmpIdView.findViewById(R.id.editTextDialogPhoneInput);
 <strong><span style="color: #008000;">// set dialog message</span></strong>

 alertDialogBuilder
 .setCancelable(false)
 .setPositiveButton("Add", new DialogInterface.OnClickListener() {
 public void onClick(DialogInterface dialog, int id) {
 <strong><span style="color: #008000;">// get user input and set it to result
 // edit text</span></strong>
 insertContact(nameInput.getText().toString(), phoneInput.getText().toString());
 restartLoader();

 }
 }).create()
 .show();

 }
 });
 }


 private void insertContact(String contactName, String contactPhone) {
 ContentValues values = new ContentValues();
 values.put(DBOpenHelper.CONTACT_NAME, contactName);
 values.put(DBOpenHelper.CONTACT_PHONE, contactPhone);
 Uri contactUri = getContentResolver().insert(ContactsProvider.CONTENT_URI, values);
 Toast.makeText(this, "Created Contact " + contactName, Toast.LENGTH_LONG).show();
 }

 private void deleteAllContacts() {

 getContentResolver().delete(ContactsProvider.CONTENT_URI, null, null);
 restartLoader();
 Toast.makeText(this, "All Contacts Deleted", Toast.LENGTH_LONG).show();
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 <strong><span style="color: #008000;">// Inflate the menu; this adds items to the action bar if it is present.</span></strong>
 getMenuInflater().inflate(R.menu.menu_main, menu);
 return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
 
 switch (item.getItemId()) {
 case R.id.deleteAllContacts:
 deleteAllContacts();
 return true;
 }

 return super.onOptionsItemSelected(item);
 }

 private void restartLoader() {
 getLoaderManager().restartLoader(0, null, this);
 }


 @Override
 public Loader<;Cursor>; onCreateLoader(int i, Bundle bundle) {
 return new CursorLoader(this, ContactsProvider.CONTENT_URI, null, null, null, null);
 }

 @Override
 public void onLoadFinished(Loader<;Cursor>; loader, Cursor cursor) {

 List<;Contact>; list = new ArrayList<;>;();

 while (cursor.moveToNext()) {
 int index1 = cursor.getColumnIndex(DBOpenHelper.CONTACT_NAME);
 int index2 = cursor.getColumnIndex(DBOpenHelper.CONTACT_PHONE);
 String name = cursor.getString(index1);
 String phone_no = cursor.getString(index2);

 Contact contact = new Contact(name, phone_no);
 list.add(contact);
 }

 adapter = new ContactsAdapter(this, list);
 rv_list.setAdapter(adapter);

 }

 @Override
 public void onLoaderReset(Loader<;Cursor>; loader) {

 }

}</code></pre>
<p>In the <span style="color: #008000;"><strong>MainActivity.java</strong></span> we are implementing the <span style="color: #008000;"><strong>LoaderManager.LoaderCallbacks</strong></span> interface to work with loader.</p>
<p>In the <strong><span style="color: #008000;"><em>onCreate()</em></span></strong> method on clicking the <span style="color: #008000;"><strong>FloatingActionButton</strong></span> we are invoking an <span style="color: #008000;"><strong>AlertDialog</strong></span> to input the Contact’s Name and Phone number.</p>
<p>On clicking the <span style="color: #008000;"><strong>Add</strong></span> button of the Dialog, <strong><span style="color: #008000;"><em>insertContact()</em></span></strong> method is called, which uses the <span style="color: #008000;"><strong><em>insert()</em></strong></span> method of our custom Android Content Provider to insert a new record into the database.</p>
<p>Similarly, we have an option in the Menu to delete all the existing contacts by calling the <strong><span style="color: #008000;"><em>delete()</em></span></strong> method of our custom Android Content Provider .</p>
<p>Next, we have implemented the methods for the <span style="color: #008000;"><strong>LoaderManager.LoaderCallbacks</strong></span> interface</p>
<ol>
<li><strong><span style="color: #0000ff;"><em>restartLoader(int id, Bundle args, LoaderCallbacks callback)</em> </span></strong>: It restarts an existing Loader with the particular id.</li>
<li><strong><span style="color: #0000ff;"><em>onCreateLoader(int id, Bundle args)</em></span></strong> : whenever we initialize loader using the <strong><span style="color: #008000;">initLoader</span></strong> like this:
<pre><strong><span style="color: #008000;">getLoaderManager().initLoader(0, null, this);</span></strong></pre>
<p>This methods get automatically triggered ,runs in a separate thread,loads the data from the provider and return a new Loader for the given id .</li>
<li><strong><span style="color: #0000ff;"><em>onLoadFinished(Loader loader, Cursor cursor)</em></span></strong> : This method is Called when a previously created loader has finished its load.It runs in main thread .@param <strong><span style="color: #008000;">loader</span></strong> indicates the Loader that has finished and @param <strong><span style="color: #008000;">cursor</span></strong> indicates the data generated by the Loader.</li>
<li><strong><span style="color: #0000ff;"><em>onLoaderReset(Loader loader)</em></span></strong> : This method is called when a previously created loader is being reset, and thus making its data unavailable.</li>
</ol>
<p>Now run the app and add few contacts. It should create a list sorted by the Name in the alphabetical order like this.</p>
<p><img class="alignnone wp-image-816 " src="https://c1ctech.com/wp-content/uploads/2018/09/Screenshot_1537442057-576x1024.png" alt="" width="349" height="621" /></p>
<p><img class="alignnone wp-image-817 " src="https://c1ctech.com/wp-content/uploads/2018/09/Screenshot_1537442321-576x1024.png" alt="" width="344" height="611" /></p>
<h4></h4>
<h3><span style="color: #000080;"><strong>Creating the ContactList App(consumer app) </strong></span></h3>
<p><strong>13</strong>. Now we will create another app <span style="color: #008000;"><strong>ContactList</strong></span> in the same way we have created the <strong><span style="color: #008000;">MyContacts</span></strong> App earliar.</p>
<p>To retrieve data from a provider, follow these basic steps:</p>
<ol>
<li>Request the read access permission for the provider.</li>
<li>Define the code that sends a query to the provider.</li>
</ol>
<p><span style="color: #0000ff;"><strong>Request the read access permission for the provider</strong></span></p>
<p>Add the following permissions to use the ContactsProvider in the <span style="color: #008000;"><strong>AndroidManifest.xml</strong></span></p>
<pre><code><;uses-permission android:name="com.c1ctech.mycontacts.READ_DATABASE" />;
<;uses-permission android:name="com.c1ctech.mycontacts.WRITE_DATABASE" />;</code></pre>
<p><span style="color: #0000ff;"><strong>Define the code that sends a query to the provider</strong></span></p>
<pre><code>private static final String AUTHORITY = "com.c1ctech.mycontacts";
private static final String BASE_PATH = "contacts";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

@Override
public Loader<;Cursor>; onCreateLoader(int id, Bundle bundle) {
<span style="color: #008000;"><strong>//loads data from the content provider</strong></span>
 if (id == 0) {
 return new CursorLoader(this, CONTENT_URI, null, null, null, null);
 }
 return null;

}

@Override
public void onLoadFinished(Loader<;Cursor>; loader, Cursor cursor) {
<strong><span style="color: #008000;">//Getting data from MyContacts App as cursor object</span></strong>
 List<;Contact>; list = new ArrayList<;>;();
/<strong><span style="color: #008000;">/Adding cursor data in a list</span></strong>
 while (cursor.moveToNext()) {

 String name = cursor.getString(1);
 String phone_no = cursor.getString(2);

 Contact contact = new Contact(name, phone_no);
 list.add(contact);
 }
<strong><span style="color: #008000;">//passing list to adapter which will display the list items in recyclerView</span></strong>
 adapter = new ContactsAdapter(this, list);
 rv_list.setAdapter(adapter);


}</code></pre>
<p><strong>14</strong>. Open activity_main.xml and write the below code.It is similar to the layout of <strong><span style="color: #008000;">MyContacts</span></strong> except in place of FloatingAction Button with property <strong><span style="color: #008000;">app:srcCompat=”@android:drawable/ic_input_add”</span></strong> we use <strong><span style="color: #008000;">app:srcCompat=”@android:drawable/ic_popup_sync”.</span></strong></p>
<p><span style="color: #0000ff;"><strong>activity_main.xml</strong></span></p>
<pre><code><;?xml version="1.0" encoding="utf-8"?>;
<;android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".MainActivity">;

 <;android.support.design.widget.AppBarLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:theme="@style/AppTheme.AppBarOverlay">;

 <;android.support.v7.widget.Toolbar
 android:id="@+id/toolbar"
 android:layout_width="match_parent"
 android:layout_height="?attr/actionBarSize"
 android:background="?attr/colorPrimary"
 app:popupTheme="@style/AppTheme.PopupOverlay" />;


 <;/android.support.design.widget.AppBarLayout>;


 <;RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">;

 <;android.support.v7.widget.RecyclerView

 android:id="@+id/contact_list"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_marginTop="70dp"

 />;

 <;/RelativeLayout>;

 <;android.support.design.widget.FloatingActionButton
 android:id="@+id/fab"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="bottom|end"
 android:layout_margin="16dp"
 app:srcCompat="@android:drawable/ic_popup_sync" />;

<;/android.support.design.widget.CoordinatorLayout>;</code></pre>
<p><strong>15</strong>. Open <strong><span style="color: #008000;">MainActivity.Java</span></strong> and write following code.The code for <span style="color: #008000;"><strong>MainActivity</strong></span> is pretty much same as the <span style="color: #008000;"><strong>MyContacts</strong></span> app, We have just removed the code for inserting and deleting the <span style="color: #008000;"><strong>Contacts</strong></span> and we are just displaying those records.<br />
<strong><span style="color: #0000ff;">MainActivity.Java </span></strong></p>
<pre><code>package com.c1ctech.contactlist;

import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;


import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<;Cursor>;, View.OnClickListener {

 ContactsAdapter adapter;
 RecyclerView rv_list;
 FloatingActionButton fab;

 private static final String AUTHORITY = "com.c1ctech.mycontacts";
 private static final String BASE_PATH = "contacts";
 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

 <strong><span style="color: #008000;">// Constant to identify the requested operation</span></strong>
 private static final int CONTACTS = 1;
 private static final int CONTACT_ID = 2;

 private boolean firstTimeLoaded = false;


 private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

 static {
 uriMatcher.addURI(AUTHORITY, BASE_PATH, CONTACTS);
 uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CONTACT_ID);
 }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 rv_list = (RecyclerView) findViewById(R.id.contact_list);

 rv_list.setLayoutManager(new LinearLayoutManager(this));
 rv_list.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 setSupportActionBar(toolbar);

 fab = (FloatingActionButton) findViewById(R.id.fab);
 fab.setOnClickListener(this);
 }


 @Override
 public Loader<;Cursor>; onCreateLoader(int id, Bundle bundle) {
 if (id == 0) {
 return new CursorLoader(this, CONTENT_URI, null, null, null, null);
 }
 return null;

 }

 @Override
 public void onLoadFinished(Loader<;Cursor>; loader, Cursor cursor) {

 List<;Contact>; list = new ArrayList<;>;();

 while (cursor.moveToNext()) {

 String name = cursor.getString(1);
 String phone_no = cursor.getString(2);

 Contact contact = new Contact(name, phone_no);
 list.add(contact);
 }

 adapter = new ContactsAdapter(this, list);
 rv_list.setAdapter(adapter);

 }

 @Override
 public void onLoaderReset(Loader<;Cursor>; loader) {
 
 }

 @Override
 public void onClick(View view) {
 switch (view.getId()) {
 case R.id.fab:
 if (firstTimeLoaded == false) {
 getLoaderManager().initLoader(0, null, this);
 firstTimeLoaded = true;
 } else {
 getLoaderManager().restartLoader(0, null, this);
 }

 break;
 default:
 break;
 }

 }
}</code></pre>
<p>When you run <span style="color: #008000;"><strong>ContactList App</strong></span> ,you find refresh button ,when you click on it you get all the contacts stored in <strong><span style="color: #008000;">MyContacts App </span></strong><span style="color: #000000;">like this:</span></p>
<p><img class="aligncenter wp-image-815 " src="https://c1ctech.com/wp-content/uploads/2018/09/Screenshot_1537442085-576x1024.png" alt="" width="419" height="745" /></p>
<p> ;</p>
<p>I hope this tutorial will help you in understanding how to work with <strong><span style="color: #000080;">contentProvider</span></strong> in sharing data from one application to another.</p>
<p> ;</p>


