In this tutorial, we are going to learn how to create Android Content Provider. ”A content provider manages access to a central repository of data. A provider is part of an Android application, which often provides its own UI for working with the data. However, content providers are primarily intended to be used by other applications, which access the provider using a provider client object”.
If you are planning to share your app data with other application, then you have to implement a content provider and export your provider so that other applications will access it and make use of it.
On the other hand, if you data will be private to your application and you have no need to share it with other application, then it is better to use Android SQLite Database. If you want to learn how to implement android SQLite Database in your project I will suggest you read my tutorial on Android SQLite Database Example.
Android has built-in Content Provider like the Dictionary, Calendar Content Provider, Contact Content Provider.
An app can access these built-in Content Provider either directly or through Intent. You can read more about Android Content Provider here.
What we plan to achieve in this example tutorial
We are going to create a custom android content provider which will server a data repository with SQLite database. The Content Provider is exported and its access is restricted with custom permission. Any application that wants to access, create or modify this content provider must implement the permission.
The app will not have its own functionality or user interaction rather its sore function is to serve as a Content Provider.
We will create a second android application, that will implement the permission provided by the first application and will access and manipulate data in the content provider.
If you are interested to learn how to access data from android built-in content provider, I wrote a tutorial on Android Calendar Content Provider API. I will suggest you read this tutorial.
In the second app, we will only implement a features that will help us to access the whole database table or a single row in the table. We can also insert new record in the database.
Creating a Content Uri for a Provider
A provider usually has a single authority, which serves as its Android-internal name. To avoid conflicts with other providers, you should use Internet domain ownership (in reverse) as the basis of your provider authority. Because this recommendation is also true for Android package names, you can define your provider authority as an extension of the name of the package containing the provider.
The providers Authority follows this format – com.inducesmile.androidcontentprovide.provider
To get the path structure, you are going to append the table you want to access to the Authority as shown – com.inducesmile.androidcontentprovide.provider/table_name
To final create a Content Uri, the content:\\ is added to the part as a prefix. The Uri path will look like this – content://com.inducesmile.androidcontentprovide.provider/table_name
In other to get a visual understanding of what we are going to create in this android tutorial, I have add below some screen shots from the application.
SOME SCREENSHOT FROM THE APPLICATION
First App Screenshot
Second App Screenshot
CREATE THE FIRST ANDROID PROJECT
Lets start to soil our hands in code. Start up your IDE. For this tutorial, I am using the following tools and environment, feel free to use what works for you.
Windows 10
Android Studio
Sony Xperia ZL
Min SDK 16
Target SDK 25
To create a new android application project, follow the steps as stipulated below.
Go to File menu
Click on New menu
Click on Android Application
Enter Project name: AndroidContentProvider
Package: com.inducesmile.androidcontentprovider
Select Empty Activity
Name your activity: MainActivity
Keep other default selections
Continue to click on next button until Finish button is active, then click on Finish Button.
STRINGS.XML
We are going to update our project strings.xml file located in the values folder inside the res folder. Open the file and add the code below to it.
<string name="app_name">Android Content Provider</string>
<resources> <string name="app_name">Android Content Provider</string> <string name="display_content">DISPLAY CONTENT</string> <string name="usage_instructions">This is Android Content Provider Application that shared its data with other apps. To test or access this data, you must install the second application and use it to query and insert data</string> <string name="dictionary_provide_permission">com.inducesmile.androidcontentprovider.DICTIONARY_PROVIDER_PERMISSION</string> </resources>
COLORS.XML
Open the colors.xml file in the same location as the strings.xml file and add the code below to the file.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="colorBlack">#000000</color> <color name="colorWhite">#ffffff</color> <color name="colorBg">#3087A8</color> </resources>
Create a Contract Class
Here, we will prepare the content Uri for the provider and also use variable names to hold the name of the database, table name, and column names in the table.
Create a Java class file and name it ContractDictionary.java or anything you choose. Open the file and add the code below to it.
import android.net.Uri; import android.provider.BaseColumns; public class ContractDictionary { public static final String AUTHORITY = "com.inducesmile.androidcontentprovider.Dictionary"; public static final String PATH = "/words"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + PATH); public static final String CONTENT_DICTIONARY_LIST = "vnd.android.cursor.dir/vnd.com.inducesmile.androidcontentprovider.words"; public static final String CONTENT_DICTIONARY_ITEM = "vnd.android.cursor.item/vnd.com.inducesmile.androidcontentprovider.words"; public static final String DATABASE_NAME = "dictionary"; public static final int DATABASE_VERSION = 1; public static class Dictionary implements BaseColumns{ private Dictionary(){} public static final String TABLE_NAME = "words"; public static final String ID = "_id"; public static final String WORD = "word"; public static final String MEANING = "meaning"; } }
Create SQLiteOpenHelper Class
Next, to create and manage a database, we will need to create a class that inherits from SQLiteOpenHelper. The class will override the onCreate() and onUpgrade() methods of the SQLiteOpenHelper class.
The two methods are responsibe for creating and updating the android SQLite database.
Create a new Java class file and name it SqliteDatabaseManager.java. Open the file and add the code below to it.
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class SqliteDatabaseManager extends SQLiteOpenHelper{ public SqliteDatabaseManager(Context context) { super(context, ContractDictionary.DATABASE_NAME, null, ContractDictionary.DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { String CREATE_PRODUCTS_TABLE = "CREATE TABLE " + ContractDictionary.Dictionary.TABLE_NAME + "(" + ContractDictionary.Dictionary.ID + " INTEGER PRIMARY KEY," + ContractDictionary.Dictionary.WORD + " TEXT," + ContractDictionary.Dictionary.MEANING + " TEXT" + ")"; sqLiteDatabase.execSQL(CREATE_PRODUCTS_TABLE); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + ContractDictionary.Dictionary.TABLE_NAME); onCreate(sqLiteDatabase); } }
Create a Custom Content Provider
Since we have created our SqliteOpenHelper class that will manage the database, we will go further to create a content provider class that will extend the android Content Provider class. The following callback methods are ovverride onCreate(), query(), getType(), insert(), update() and delete().
In the onCreate() callback method, an instance of the SqliteOpenHelper class is created. The getReadableDatabase() and getWritableDatabase() method are call in each callback method as required.
This class makes it possible for other application to access to data store in the SQLite database in this application.
When we create the second application, we will learn how to get access and play around with the SQLite database.
Now, create new Java class file like before and name it DictionaryProvider.java. Open the class and add the code below.
import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.widget.Toast; public class DictionaryProvider extends ContentProvider{ private SqliteDatabaseManager dbManager; private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sUriMatcher.addURI(ContractDictionary.AUTHORITY, ContractDictionary.PATH, 1); sUriMatcher.addURI(ContractDictionary.AUTHORITY, ContractDictionary.PATH + "/#", 2); } @Override public boolean onCreate() { dbManager = new SqliteDatabaseManager(getContext()); return false; } @Nullable @Override public Cursor query(@NonNull Uri uri, String[] projections, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbManager.getWritableDatabase(); Cursor mCursor = null; switch (sUriMatcher.match(uri)){ case 1: mCursor = db.query(ContractDictionary.Dictionary.TABLE_NAME, projections, selection, selectionArgs, null, null, null); break; case 2: selection = selection + ContractDictionary.Dictionary.ID + " = " + uri.getLastPathSegment(); mCursor = db.query(ContractDictionary.Dictionary.TABLE_NAME, projections, selection, selectionArgs, null, null, null); break; default: Toast.makeText(getContext(), "Invalid content uri", Toast.LENGTH_LONG).show(); throw new IllegalArgumentException("Unknown Uri: " + uri); } mCursor.setNotificationUri(getContext().getContentResolver(), uri); return mCursor; } @Nullable @Override public String getType(Uri uri) { switch (sUriMatcher.match(uri)){ case 1: return ContractDictionary.CONTENT_DICTIONARY_LIST; case 2: return ContractDictionary.CONTENT_DICTIONARY_ITEM; default: throw new IllegalArgumentException("Unknown Uri: " + uri); } } @Nullable @Override public Uri insert(Uri uri, ContentValues contentValues) { SQLiteDatabase db = dbManager.getWritableDatabase(); if(sUriMatcher.match(uri) != 1) { throw new IllegalArgumentException("Unknown URI: " + uri); } long rowId = db.insert(ContractDictionary.Dictionary.TABLE_NAME, null, contentValues); if(rowId > 0) { Uri articleUri = ContentUris.withAppendedId(ContractDictionary.CONTENT_URI, rowId); getContext().getContentResolver().notifyChange(articleUri, null); return articleUri; } throw new IllegalArgumentException("Unknown URI: " + uri); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbManager.getWritableDatabase(); int count = 0; switch(sUriMatcher.match(uri)) { case 1: count = db.delete(ContractDictionary.Dictionary.TABLE_NAME, selection, selectionArgs); break; case 2: String rowId = uri.getPathSegments().get(1); count = db.delete(ContractDictionary.Dictionary.TABLE_NAME, ContractDictionary.Dictionary.ID + " = " + rowId + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { SQLiteDatabase db = dbManager.getWritableDatabase(); int count = 0; switch (sUriMatcher.match(uri)){ case 1: count = db.update(ContractDictionary.Dictionary.TABLE_NAME, contentValues, selection, selectionArgs); break; case 2: String rowId = uri.getPathSegments().get(1); count = db.update(ContractDictionary.Dictionary.TABLE_NAME, contentValues, ContractDictionary.Dictionary.ID + " = " + rowId + (!TextUtils.isEmpty(selection) ? " AND (" + ")" : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unknown Uri: " + uri ); } getContext().getContentResolver().notifyChange(uri, null); return count; } }
Update AndroidManifest.xml
Since a provider is part of android component, we are going to add the provider element in the application section in AndroidManifest.xml.
The provider element has a name and authorities attribute which we will specify. We will also add the android:exported=”true” which will make the content provider available to other applications.
Finally, the permission that any application that want to access this content provider will implement before it gets access to it is also specified.
The update version of the AndroidManifest.xml file is shown below.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.inducesmile.androidcontentprovider"> <permission android:name="com.inducesmile.androidcontentprovider.DICTIONARY_PROVIDER_PERMISSION" android:protectionLevel="normal" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" 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.inducesmile.androidcontentprovider.Dictionary" android:name="com.inducesmile.androidcontentprovider.DictionaryProvider" android:exported="true"/> </application> </manifest>
MainActivity class and its layout file
Since this application only expose its content provider to other application to use, we are not going to implement any user interface apart from adding a TextView widget in the layout file with the instruction.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:background="@color/colorBg" tools:context="com.inducesmile.androidcontentprovider.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/colorWhite" android:textSize="15sp" android:text="@string/usage_instructions" android:layout_centerHorizontal="true" android:layout_centerVertical="true"/> </RelativeLayout>
MainActivity class
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Create another android app that will access data the Content Provider App
To create a new android application project, follow the steps as stipulated below.
Go to File menu
Click on New menu
Click on Android Application
Enter Project name: AndroidAccessContentProvider
Package: com.inducesmile.androidaccesscontentprovider
Select Empty Activity
Name your activity: MainActivity
Keep other default selections
Continue to click on next button until Finish button is active, then click on Finish Button.
ADD LIBRARY DEPENDENCIES IN BUILD.GRADLE
We are going to update the module build.gradle file since we are going to add some dependency libraries that the application will make use of.
The update version of the build.gradle is shown below.
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "24.0.1" defaultConfig { applicationId "com.inducesmile.accesscontentprovider" minSdkVersion 16 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.0.1' compile 'com.android.support:design:25.0.1' compile 'com.android.support:cardview-v7:25.0.1' compile 'com.android.support:recyclerview-v7:25.0.1' compile 'com.android.support:support-v4:25.0.1' testCompile 'junit:junit:4.12' }
STRINGS.XML
We are going to update our project strings.xml file located in the values folder inside the res folder. Open the file and add the code below to it.
<resources> <string name="app_name">Access Content Provider</string> <string name="display_dictoinary_provider_words">DISPLAY DICTOINARY PROVIDER WORDS</string> <string name="add_new_provider_content">ADD NEW PROVIDER CONTENT</string> <string name="honesty">Honesty</string> <string name="enter_word">Enter word</string> <string name="enter_meaning">Enter meaning</string> <string name="add_dictionary_word">ADD DICTIONARY WORD</string> <string name="add_to">Add to Content Provider</string> </resources>
COLORS.XML
Open the colors.xml file in the same location as the strings.xml file and add the code below to the file.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#B8861C</color> <color name="colorPrimaryDark">#a37617</color> <color name="colorAccent">#B8651C</color> <color name="colorBg">#F3A968</color> <color name="colorBlack">#000000</color> <color name="colorWhite">#ffffff</color> <color name="colorBorder">#dbd9d9</color> </resources>
SplashActivity class and its layout file
This is the launch activity which a user will see once the app loads. Since we stated that we will only implement methods to query the dictionary content provider and also insert data to it, we will add two Button widgets to the layout file.
activity_splash.xml
Open this layout file and add two button widgets. These button widgets will be wired in the activity class once the instances are obtained.
Open the layout file and add the code below.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_splash" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:background="@color/colorBg" tools:context="com.inducesmile.accesscontentprovider.SplashActivity"> <Button android:id="@+id/dispaly_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorAccent" android:textColor="@color/colorWhite" android:text="@string/display_dictoinary_provider_words" android:padding="20dp"/> <Button android:id="@+id/add_new_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorAccent" android:textColor="@color/colorWhite" android:layout_marginTop="16dp" android:text="@string/add_new_provider_content" android:padding="20dp"/> </LinearLayout>
SplashActivity class
The instances of the button widgets are obtained and wired with on click event listener. Open the file and add the code below to the file.
import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class SplashActivity extends AppCompatActivity { private static final String TAG = SplashActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); Button displayContentButton = (Button)findViewById(R.id.dispaly_content); displayContentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent displayIntent = new Intent(SplashActivity.this, DisplayContentActivity.class); startActivity(displayIntent); } }); Button addContentButton = (Button)findViewById(R.id.add_new_content); addContentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent addIntent = new Intent(SplashActivity.this, AddContentActivity.class); startActivity(addIntent); } }); } }
Add Data to the Content Provider
To add a row data in the Content Provider, we will create EditText widgets and Button widget that will be used to submit filled input box.
Create a new Empty Activity class with its layout file.
activity_add_content.xml
In this layout file add 2 EditText widgets and a Button Widgets. The complete code for this layout file is shown below.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_add_content" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.inducesmile.accesscontentprovider.AddContentActivity"> <EditText android:id="@+id/enter_word" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/enter_word" android:textColorHint="@color/colorBorder" android:textSize="14sp" android:inputType="text" android:background="@drawable/brown_border" android:maxLines="1" android:layout_marginRight="12dp" android:layout_marginEnd="12dp" android:textColor="@color/colorBlack" android:padding="16dp"/> <EditText android:id="@+id/enter_meaning" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/enter_meaning" android:textColorHint="@color/colorBorder" android:textSize="14sp" android:inputType="text" android:background="@drawable/brown_border" android:maxLines="1" android:layout_marginTop="18dp" android:layout_marginRight="12dp" android:layout_marginEnd="12dp" android:textColor="@color/colorBlack" android:padding="16dp"/> <Button android:id="@+id/add_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorAccent" android:textColor="@color/colorWhite" android:layout_marginTop="24dp" android:text="@string/add_dictionary_word" android:padding="20dp"/> </LinearLayout>
AddContentActivity Class
The instances of the View controls in the layout file is obtained in this activity class. When the button is clicked the user input values in the Edittext fields are obtained.
These values are store in a ContentValues object and it is then pass as a parameter to the insert() method of the ContentResolver class.
Open the activity class and add the code below.
import android.content.ContentValues; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class AddContentActivity extends AppCompatActivity { private static final String TAG = AddContentActivity.class.getSimpleName(); private EditText wordInput, meaningInput; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_content); setTitle(getString(R.string.add_to)); wordInput = (EditText)findViewById(R.id.enter_word); meaningInput = (EditText)findViewById(R.id.enter_meaning); Button addContentButton = (Button)findViewById(R.id.add_content); addContentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String word = wordInput.getText().toString(); String meaning = meaningInput.getText().toString(); if(TextUtils.isEmpty(word) || TextUtils.isEmpty(meaning)){ Toast.makeText(AddContentActivity.this, "All input fields must be filled", Toast.LENGTH_LONG).show(); }else{ String AUTHORITY = "com.inducesmile.androidcontentprovider.Dictionary"; String PATH = "/words"; Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + PATH); ContentValues values = new ContentValues(); values.put("word", word); values.put("meaning", meaning); Uri mUri = getContentResolver().insert(CONTENT_URI, values); if(mUri != null){ Toast.makeText(AddContentActivity.this, "Successfully added to Content Provider", Toast.LENGTH_LONG).show(); } } } }); } }
Retrieve all stored column data in the Content Provider
To retrieve some columns or all the data from the Content Provider app, you can use the Content Uri with the query() method of the ContentResolver class.
Since we are going to display rows of data, We are going to use a RecyclerView with an Adapter which will bind the data source to items of the Recyclerview.
activity_display_content.xml
Add a RecyclerView widget in this layer file. The complete source code is as shown.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_display_content" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.inducesmile.accesscontentprovider.DisplayContentActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/list_dictionary" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="12dp" android:scrollbars="none" /> </RelativeLayout>
DisplayContentActivity Class
Get the instance of the RecyclerView. Set a linear layout manager to it. Prepare the adapter instance and pass it as a parameter to the RecyclerView object.
We use the query() method of the ContentResolver class to return a cursor object. We loop through the cursor to obtain the data we need to bind in the adapter class.
Open this file and add the code below to it.
import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class DisplayContentActivity extends AppCompatActivity { private static final String TAG = DisplayContentActivity.class.getSimpleName(); public static final String AUTHORITY = "com.inducesmile.androidcontentprovider.Dictionary"; public static final String PATH = "/words"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + PATH); private RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_display_content); recyclerView = (RecyclerView)findViewById(R.id.list_dictionary); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setHasFixedSize(true); Cursor mCursor = getContentResolver().query(CONTENT_URI, null, null, null, null, null); List<String> words = new ArrayList<>(); if(mCursor.moveToFirst()){ do{ String word = mCursor.getString(1); words.add(word); }while(mCursor.moveToNext()); DictionaryAdapter mAdapter = new DictionaryAdapter(DisplayContentActivity.this, words); recyclerView.setAdapter(mAdapter); }else{ Toast.makeText(DisplayContentActivity.this, "Nothing is inside the cursor ", Toast.LENGTH_LONG).show(); } mCursor.close(); } }
RecyclerView Adapter and ViewHolder Classes
The RecyclerView makes use of an Adapter and a ViewHolder classes. The Adapter class in turn inflates a layout file which represents each data item of the RecyclerView.
Create the below class and add the code associated with each of them.
DictionaryAdapter Class
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.util.List; public class DictionaryAdapter extends RecyclerView.Adapter<DictionaryViewHolder>{ private Context context; private List<String> wordList; public DictionaryAdapter(Context context, List<String> wordList) { this.context = context; this.wordList = wordList; } @Override public DictionaryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.word_list_layout, parent, false); return new DictionaryViewHolder(view); } @Override public void onBindViewHolder(DictionaryViewHolder holder, int position) { String rowContent = wordList.get(position); holder.word.setText(rowContent); } @Override public int getItemCount() { return wordList.size(); } }
DictionaryViewHolder Class
import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.TextView; public class DictionaryViewHolder extends RecyclerView.ViewHolder{ public TextView word; public DictionaryViewHolder(View itemView) { super(itemView); word = (TextView)itemView.findViewById(R.id.word); } }
word_list_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="8dp"> <TextView android:id="@+id/word" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/honesty" android:padding="8dp" android:textSize="15sp"/> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="8dp" android:background="@color/colorBorder"/> </LinearLayout>
This brings us to the end of this tutorial. I hope that you have learn something. Run your app and see for yourself.
You can download the code for this tutorial above. If you are having hard time downloading the tutorial, kindly contact me.
Remember to subscribe with your email address to be among the first to receive my new android blog post once it is published.
may i get the full code of content provider example