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.
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
Note: CursorLoader
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.
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 |
---|---|
prefix | content:// standard prefix indicates data controlled by Content Providers |
authority | Name content provider Like contacts, browser, etc. For third-party content providers.
It could be a fully qualified name, such as in.eyehunt.mycontactcontentproviders |
data_type | Type of data that this particular provider provides. |
id | Specific 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 :
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