Content Providers ContentResolver with an example in Android

Content Providers are the main component of Android app development. The first introduction was for share data with other app or within the application. But now can store and secure your data during uses. Content providers have an interface that connects data in one process with code running in another process. Where ContentResolver resolves a URI to a specific Content Provider.

Content Providers ContentResolver example tutorial studio

If you want to share data or donate want to, you may use a content provider because it provides a great abstraction. This abstraction allows you to make modifications to your application data storage implementation without affecting other existing applications that rely on access to your data. In this whole scenario, only your content provider is affected and not the applications accessing it.

Content providers can use for structured data like SQLite relation database and unstructured data such as Images, Video and Audio files. Its manage access to a variety of data storage source.

Content Providers control over the permissions

  • Restrict Access –  Only within your application
  • Grant blanket permission – Can access data from other applications
  • Configure different permissions for reading and writing data

NoteCursorLoader objects depend on content providers to run asynchronous queries that return the results to the UI layer in the application.

Before starting just get in What is ContentResolver :

To access data in a content provider, you have to use the ContentResolver object in your application’s Context to communicate with the provider as a client.

TheContentResolver methods provide the basic “CRUD” (create, retrieve, update, and delete) functions of persistent storage.

Let’s build an App for Content Providers 

You can code to access an existing content provider in another application, or can create a new content provider in your application to share data with other Android applications.

This example tutorial is to cover the basics of working with existing content providers.

Content Providers ContentResolver example tutorial studio database

In this example, we build an app for contact list (like a phone directory). Where all contact will store in database SQLite and access them we use ContentProvider and ContentResolver.

CursorAdapter: Adapter that exposes data from a Cursor to a ListView widget.

CursorLoader: Run asynchronous queries that return the results to the UI layer in the application.

Content URIs<prefix>://<authority>/<data_type>/<id>

#Description
prefixcontent:// standard prefix indicates data controlled by Content Providers
authorityName content provider Like contactsbrowser, etc. For third-party content providers. 

 

It could be a fully qualified name, such as in.eyehunt.mycontactcontentproviders

data_typeType of data that this particular provider provides.
idSpecific record request. For example, search for contact number 3 in the Contacts.
Step 1. Create a new project “ Build Your First Android App in Kotlin 
Step 2. Start With you add floating action button and ListView in “activity_main.xml

Before add icons in a mipmap resource file and outline_delete.png & baseline_add_white.png

Add Strings res in project

<resources>
    <string name="app_name">MyContact Content Providers</string>
    <string name="name">Enter name</string>
    <string name="id">ID</string>
    <string name="number">Enter Number</string>
</resources>

Now come into main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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">
    <ListView
        android:id="@+id/lv_contacts"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabtn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:clickable="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:srcCompat="@mipmap/baseline_add_white" />

</android.support.constraint.ConstraintLayout>
Step 3. Create a resource file “row_contact.xml” to show the item as an in List
<?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="@mipmap/ic_launcher" />
    <TextView
        android:id="@+id/tv_name"
        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/tv_phone"
        android:layout_width="match_parent"
        android:layout_height="36dp"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/tv_name"
        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>
Step 4. Create a dialog box resource file “dialog_box.xml
<?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="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:padding="10dp">
    <EditText
        android:id="@+id/et_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/name" />
    
    <EditText
        android:id="@+id/et_number"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/number"
        android:inputType="number"/>

</LinearLayout>
Step 5. Create a menu “main_,menu.xml”

if you don’t have any menu resource file then create first “Android Resource directory” then create resource file “main_menu.xml”

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_delete"
        android:icon="@mipmap/outline_delete"
        android:title="Item"
        app:showAsAction="always" />
</menu>
Step 6. Create a class DatabaseHandler extends SQLiteOpenHelper

Create a table and database to store contacts

package in.eyehunt.mycontactcontentproviders;

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

/**
 * Created by Eyehunt Team on 03/07/18.
 */
public class DatabaseHandler extends SQLiteOpenHelper {

    //Constants for db name and version
    private static final String DATABASE_NAME = "contacts.db";
    private static final int DATABASE_VERSION = 1;

    //Constants for table and columns
    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";

    //Create Table
    private static final String CREATE_TABLE =
            "CREATE TABLE " + TABLE_CONTACTS + " (" +
                    CONTACT_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                    CONTACT_NAME + " TEXT, " +
                    CONTACT_PHONE + " TEXT " +
                    ")";

    // All columns
    public static final String[] ALL_COLUMNS =
            {CONTACT_ID, CONTACT_NAME, CONTACT_PHONE };

    public DatabaseHandler(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);
    }
}
Step 7. Create a MyContactsProvider class extends ContentProvider

The override must methods and add this code to perform the operation in DB thru Content Providers

package in.eyehunt.mycontactcontentproviders;

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.NonNull;
import android.support.annotation.Nullable;

public class MyContactsProvider extends ContentProvider {

    private static final String AUTHORITY = "in.eyehunt.mycontactcontentproviders";
    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() {
        DatabaseHandler handler  = new DatabaseHandler(getContext());
        database = handler.getWritableDatabase();
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s,
                        @Nullable String[] strings1, @Nullable String s1) {
        Cursor cursor;
        switch (uriMatcher.match(uri)) {
            case CONTACTS:
                cursor =  database.query(DatabaseHandler.TABLE_CONTACTS,DatabaseHandler.ALL_COLUMNS,
                        s,null,null,null,DatabaseHandler.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(@NonNull 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(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        long id = database.insert(DatabaseHandler.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(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        int delCount = 0;
        switch (uriMatcher.match(uri)) {
            case CONTACTS:
                delCount =  database.delete(DatabaseHandler.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(@NonNull Uri uri, @Nullable ContentValues contentValues,
                      @Nullable String s, @Nullable String[] strings) {
        return 0;
    }
}
Step 8. Create ContactsCursorAdapter  adapter extends CursorAdapter
package in.eyehunt.mycontactcontentproviders;

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;

public class ContactsCursorAdapter extends CursorAdapter {
    public ContactsCursorAdapter(Context context, Cursor c, int flags) {
        super(context, c, flags);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {

        return LayoutInflater.from(context).inflate(
                R.layout.row_contact,viewGroup,false );
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        String contactName = cursor.getString(
                cursor.getColumnIndex(DatabaseHandler.CONTACT_NAME));
        String contactPhone = cursor.getString(
                cursor.getColumnIndex(DatabaseHandler.CONTACT_PHONE));
        TextView nameTextView = (TextView) view.findViewById(R.id.tv_name);
        TextView phoneTextView = (TextView) view.findViewById(R.id.tv_phone);
        nameTextView.setText(contactName);
        phoneTextView.setText(contactPhone);

    }
}
Step 8. Add the following code in MainActivity.java class
package in.eyehunt.mycontactcontentproviders;

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.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

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

    private CursorAdapter cursorAdapter;

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

        cursorAdapter = new ContactsCursorAdapter(this, null, 0);

        ListView list = (ListView) findViewById(R.id.lv_contacts);
        list.setAdapter(cursorAdapter);
        getLoaderManager().initLoader(0, null, this);

        // add new record - dialog box
        FloatingActionButton fabtn_add = (FloatingActionButton) findViewById(R.id.fabtn_add);
        fabtn_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

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

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setTitle("Add new contact");
                builder.setView(getEmpIdView);

                final EditText et_name = (EditText) getEmpIdView.findViewById(R.id.et_name);
                final EditText et_number = (EditText) getEmpIdView.findViewById(R.id.et_number);
                // set dialog message

                builder
                        .setCancelable(false)
                        .setPositiveButton("Add", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                // get user input and set it to result
                                insertContact(et_name.getText().toString(), et_number.getText().toString());
                                restartLoader();

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

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

    // Delete all contacts
    private void deleteAllContacts() {

        getContentResolver().delete(MyContactsProvider.CONTENT_URI, null, null);
        restartLoader();
        Toast.makeText(this, "All contacts has deleted", Toast.LENGTH_LONG).show();
    }

    // reload all data in listivew
    private void restartLoader() {
        getLoaderManager().restartLoader(0, null, this);
    }

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

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

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

    }

    //set menu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

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

        return super.onOptionsItemSelected(item);
    }
}
Step 9. Run the application, in the emulator or On your Android device
Output screenshot Content Providers ContentResolver example in Android  :
Content Providers ContentResolver example output

 

Video Output

Download source code Android Content Providers ContentResolver example

https://github.com/EyeHunts/MyContactContentProviders

Note : This example (Project) is developed in Android Studio 3.1.3 . Tested on Android 9 ( Android-P), compile SDK version API 26: Android 8.0 (Oreo)

MinSdkVersion=”15″

TargetSdkVersion=”27″

Coding in Java


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.