07/08/2021 Content Provider | Alexandria
MODULE
Content Provider
Nawfal Ali Updated 6 May 2020
Q) I want to export my data to other applications, what should I do?
A) Implement the Content Provider (CP) Class on top of your Room Database.
Q) Do I need to implement the CP class if my data is private to my application only? A) In this case, there is no need to implement the CP class.
So, what is Content Provider?
CP is a class that helps applications to share their data with other applications on the same device. In other words, as the name suggests, Content Providers makes your application a provider of data which is served by Room Database or any other interfaces.
Now, let¡¯s implement the content provider class in the tasks application.
Step 1) right-click the package ¡®provider¡¯ and add a new content provider as shown below:
Q) How can I access the Content Provider of an application?
A) Access to the data is provided via a Universal Resource Identi er (URI) de ned by the Content Provider.
https://www.alexandriarepository.org/module/content-provider/
1/8
07/08/2021 Content Provider | Alexandria
Q) What is URL Authority?
A) it is a unique name that identi es the content provider. You cannot have two content providers with the same authority value on the same device.
After adding the content provider class to your project, a new element has been added to the manifest that declares the CP class and its authorities.
1. 2. 3. 4. 5. 6.
android:exported=”true”>
The Content Provider Application
https://www.alexandriarepository.org/module/content-provider/
2/8
07/08/2021 Content Provider | Alexandria
onCreate()
In this method, we should get an instance of the Room database that we have created earlier.
where db is declared as :
1. TasksDatabase db;
query()
This method is used to query the database and return data to the caller. It needs the following parameters:
Uri: maps to the table name
projection: list of columns that should be included in each row
selection: is a string that represents the where clause
Selection Arguments: an array of strings represents values that should be embedded in the selection statement sort order: a string that indicates whether to sort the data in ascending or descending order.
For example, let¡¯s have the following SQL statement:
1. selectname,age,salaryfromuserswhereage>25andsalary<1500orderbysalaryASC; The mapping table should be:
1. 2. 3. 4. 5.
@Override
publicbooleanonCreate(){
db = TasksDatabase.getDB(getContext()); return true;
}
ARGUMENT Uri
projection Selection
Selection Argument
SQL VALUE content_authority/users
[¡°name¡±,¡±age¡±,¡±salary¡±]
case 1: ¡°where age>25 and salary<1500¡± case 2: ¡°where age>? and salary¡±
for case 1: null
for case 2: [¡°25¡ä¡ä,¡±1500¡±]
Q) What methods do I need to implement in the content provider class?
A) you have to implement the following methods:
onCreate() which is called to initialize the provider
query(Uri, String[], Bundle, CancellationSignal) which returns data to the caller
insert(Uri, ContentValues) which inserts new data into the content provider
update(Uri, ContentValues, String, String[]) which updates existing data in the content provider delete(Uri, String, String[]) which deletes data from the content provider
getType(Uri) which returns the MIME type of data in the content provider
https://www.alexandriarepository.org/module/content-provider/
3/8
07/08/2021 Content Provider | Alexandria
ARGUMENT SQL VALUE
sort order ¡°salary ASC¡± or null for default
So, the query() method implementation will be:
1. 2. 3. 4. 5. 6. 7. 8. 9.
10. 11. 12. 13. 14.
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); builder.setTables(Task.TABLE_NAME);
String query = builder.buildQuery(projection, selection, null, null, sortOrder, null);
final Cursor cursor = db .getOpenHelper()
.getReadableDatabase()
.query(query, selectionArgs);
return cursor; }
Q) What is ¡®Cursor¡¯ which is used as a return type to query method?
A) This interface provides random read-write access to the result set returned by a database query. [Anrdoid Docs]
In other words, its a data structure that holds one or more rows retrieved from a database. It contains methods to move the cursor to the next row, previous, rst, or to the last row.
insert()
This method inserts a new row to the database and returns a new Uri with the inserted row ID.
1. 2. 3. 4. 5. 6. 7. 8. 9.
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
long rowId = db
.getOpenHelper()
.getWritableDatabase()
.insert(Task.TABLE_NAME, 0, contentValues);
return ContentUris.withAppendedId(CONTENT_URI, rowId); }
https://www.alexandriarepository.org/module/content-provider/
4/8
07/08/2021 Content Provider | Alexandria
Q) What format does Content Values use?
A) The content values data structure uses the key-value pair format.
Q) What is the di erence between Content Values and Bundle? A) The keys in the content values are the table¡¯s columns names.
Q) What is the di erence between Content Values and Cursor?
A) Content Values can hold the data of one row only, while Cursor might contain data for multiple rows.
delete()
This method is used to delete one or more rows from the database.
1. 2. 3. 4. 5. 6. 7. 8. 9.
10. 11.
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) { int deletionCount;
deletionCount = db
.getOpenHelper()
.getWritableDatabase()
.delete(Task.TABLE_NAME, selection, selectionArgs);
return deletionCount; }
The return of this method is the number of rows that get a ected by the delete operation.
update()
1. 2. 3. 4. 5. 6. 7. 8. 9.
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int updateCount;
updateCount = db
.getOpenHelper()
.getWritableDatabase()
.update(Task.TABLE_NAME, 0, values, selection, selectionArgs);
return updateCount;
}
Q) What is contentValues?
A) It is a special data structure that is used to hold the data of one row only. It is used to send data to the database.
https://www.alexandriarepository.org/module/content-provider/
5/8
07/08/2021 Content Provider | Alexandria
https
6/8
This method is used to update an existing row in the database. It accepts similar parameters as the insert method. It returns the number of rows that get a ected by the update operation.
getType()
UriMatcher()
This method is used to create a new instance of the UriMatcher class. In this method, we give each URI a unique code that will be used later by the content provider¡¯s methods to tell which table to use or to retrieve the requested ID.
Q) What is the purpose of the getType() method?
A) It is used by applications to retrieve the MIME type of the given content URI. In other words, is used to tell the other application the type of the return of the given URI.
1. private static final int MULTIPLE_ROWS_TASKS = 1;
2. private static final int SINGLE_ROW_TASKS = 2;
3.
4. privatestaticUriMatchercreateUriMatcher(){
5.
6. final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
7. final String authority = CONTENT_AUTHORITY;
8.
9. //sUriMatcher will return code 1 if uri like authority/tasks
10. uriMatcher.addURI(authority, Task.TABLE_NAME, MULTIPLE_ROWS_TASKS);
11.
12. //sUriMatcher will return code 2 if uri like e.g. authority/tasks/7 (where 7 is id of row in tasks table)
13. uriMatcher.addURI(authority, Task.TABLE_NAME + "/#", SINGLE_ROW_TASKS);
14.
15. return uriMatcher;
16. }
In the code above(line@13), the ¡®#¡¯ character represents an integer value which represents an ID. Now, let¡¯s assume we have another table called ¡®user¡¯, then the new UriMatacher will be:
1. privatestaticUriMatchercreateUriMatcher(){ 2.
3. final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
4. final String authority = CONTENT_AUTHORITY;
5.
6. //sUriMatcher will return code 1 if uri like authority/tasks
7. uriMatcher.addURI(authority, Task.TABLE_NAME, MULTIPLE_ROWS_TASKS);
8.
9. //sUriMatcher will return code 2 if uri like e.g. authority/tasks/7 (where 7 is id of row in tasks table)
10. uriMatcher.addURI(authority, Task.TABLE_NAME + "/#", SINGLE_ROW_TASKS);
11.
12. //sUriMatcher will return code 1 if uri like authority/users
13. uriMatcher.addURI(authority, "users", MULTIPLE_ROWS_USERS);
://www.alexandriarepository.org/module/content-provider/
07/0
https://www.alexandriarepository.org/module/content-provider/ 7/8
/2021 Content Provider | Alexandria
This approach will provide us with the ability to retrieve data from the caller such as the id of the row that the caller is intended to delete.
1. 2. 3. 4. 5. 6.
7. 8. 9.
10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.
public int delete(Uri uri, String selection, String[] selectionArgs) { int uriType = sUriMatcher.match(uri);
int deletionCount = 0;
switch (uriType) {
case MULTIPLE_ROWS_TASKS: //no trailing row id so selection may indicate more than 1 row needs to be deleted
if they can be found
deletionCount = db
.getOpenHelper()
.getWritableDatabase()
.delete(Task.TABLE_NAME, selection, selectionArgs); break;
case SINGLE_ROW_TASKS: //trailing row id, so just one row to be deleted if it can be found String id = uri.getLastPathSegment();
String selectionId = Task.COLUMN_ID + " = ?";
String [] selectionArgsId={String.valueOf(id)};
deletionCount = db
.getOpenHelper()
.getWritableDatabase()
.delete(Task.TABLE_NAME, selectionId, selectionArgsId); break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
return deletionCount; }
How to access the content provider from other applications?
Q) I need to query and retrieve data from another application that works as a content provider. Do I need to implement Room database or content provider?
A)None of them is required. You should use the ContentResolver class.
14. 15. 16. 17. 18. 19.
//sUriMatcher will return code 2 if uri like e.g. authority/users/7 (where 7 is id of row in users table)
uriMatcher.addURI(authority, "users" + "/#", SINGLE_ROW_USERS); return uriMatcher;
}
8
07/08/2021 Content Provider | Alexandria
Now, to query the tasks table and show the number of rows in a text view:
Where tV is a reference to the text view. getCount() is a method that returns an integer represents the number of rows in the cursor (number rows retrieved from the content provider of the other application)
How to send a row to be saved in the database of the other application:
Remember: the insert method needs the data of the new row to be wrapped(inside) by ContentValues class.
1. Uri uri= Uri.parse("content://fit2081.tasks.db.provider/tasks");
2. Cursor result= getContentResolver().query(uri,null,null,null);
3. tV.setText(result.getCount()+"");
1. public static final String COLUMN_NAME = "taskName";
2. public static final String COLUMN_DESCRIPTION = "taskDescription";
3. 4.
5. ContentValues values= new ContentValues();
6. values.put(COLUMN_NAME,"New Task Name");
7. values.put(COLUMN_DESCRIPTION,"New Task Desc");
8. Uri uri2= getContentResolver().insert(uri,values);
Copyright ý Monash University, unless otherwise stated. All Rights Reserved, except for individual components (or items) marked with their own licence restrictions
Copyright ý 2021 Monash University, unless otherwise stated
Disclaimer and Copyright Privacy
Service Status
Q) What is ContentResolver (CR)?
A) CR is used to access the content provider. The content resolver object contains a set of methods that mirror those of the content provider (insert, query, delete etc.).
https://www.alexandriarepository.org/module/content-provider/
8/8