Android Content provider component

Posted by EOS on Wed, 01 Dec 2021 10:56:40 +0100

Content Provider is one of the components of Android applications. As the only way to share data between applications, the main function of Content Provider is to store and retrieve data and provide excuses for other applications to access data.

The Android system has built-in a series of content providers for some common data types (such as music, video, image, mobile phone address book, contact information, etc.), which are located under the android.provider package. With a specific license, you can access these content providers in your own applications.

There are two ways to share your own data with other applications: create your own Content Provider (that is, a subclass inherited from ContentProvider) or add your own data to the existing Content Provider. The latter needs to ensure that the existing Content Provider has the same data type as your own and has the write permission of the Content Provider. For the Content Provider, the most important are the data model and URI.

1. Data model
The Content Provider provides its stored data to visitors in the form of data table. In the data table, each row is a record, and each column is data with specific type and meaning. Each data record includes a "_ID" value field, which uniquely identifies a piece of data.

2.URI
URI, each Content Provider provides a public URI that can uniquely identify its own data set. If a Content Provider manages multiple data sets, it will assign an independent URI to each data set. The URIs of all content providers begin with "content: / /", where "content:" is the schema used to identify that the data is managed by the Content Provider.

URIs are used in almost all Content Provider operations. Therefore, generally speaking, if it is a self-developed Content Provider, it is best to define the URI as a constant, which not only simplifies the development, but also improves the maintainability of the code.

First, let's introduce how to access the data in the Content Provider. The data in the Content Provider is accessed mainly through the ContentResolver object. The ContentResolver class provides member methods, which can be used to query, insert, modify and delete the data in the Content Provider. Taking query as an example, querying a Content Provider requires the following information.

URI that uniquely identifies the Content Provider
Name of the data field to access.
The data type of the data field

Tip: if you need to access a specific data record, you only need the ID of the record.

There are two methods to query the Content Provider: query() of ContentResolver and managedQuery() of Activity object. Both receive the same parameters and return the Cursor object. The only difference is that the managedQuery method allows the Activity to manage the Cursor life cycle.

The managed Cursor will call its own deactivate method to unload itself when the Activity enters the suspended state, and call its own requery method to re query the generated Cursor object when the Activity returns to the running state. If an unmanaged Cursor object wants to be managed by the Activity, it can be implemented by calling the startManagingCursor method of the Activity.

Android applications can use files or SqlLite databases to store data. The Content Provider provides a way to share data among multiple applications. For example, contact information can be accessed by multiple applications. Content Provider is a class that implements a set of standard methods for providing access to data by other applications.

Applications can perform the following operations in the Content Provider:
Query data

Modify data

Add data

Delete data

/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/MainActivity.java

package com.amaker.ch10.app;

import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

import com.amaker.ch10.app.Employees.Employee;

public class MainActivity extends Activity {

@Override  
public void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.main);  
    // add to  
    insert();  
    // query  
    query();  
    // to update  
    update();  
    // query  
    query();  
    // delete  
    del();  
    // query  
    query();  
}  
// Delete method  
private void del(){  
    // Delete record with ID 1  
    Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1);  
    // Get the ContentResolver and delete it  
    getContentResolver().delete(uri, null, null);  
}  
// to update  
private void update(){  
    // Update record with ID 1  
    Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1);  
    ContentValues values = new ContentValues();  
    // Add employee information  
    values.put(Employee.NAME, "hz.guo");  
    values.put(Employee.GENDER, "male");  
    values.put(Employee.AGE,31);  
    // Get ContentResolver and update  
    getContentResolver().update(uri, values, null, null);  
}  
// query  
private void query(){  
    // Query column array  
       String[] PROJECTION = new String[] {   
               Employee._ID,         // 0  
               Employee.NAME,         // 1  
               Employee.GENDER,     // 2  
               Employee.AGE         // 3  
    };  
    // Query all memo information  
    Cursor c = managedQuery(Employee.CONTENT_URI, PROJECTION, null,  
            null, Employee.DEFAULT_SORT_ORDER);  
    // Determine whether the cursor is empty  
    if (c.moveToFirst()) {  
        // Traversal cursor  
        for (int i = 0; i < c.getCount(); i++) {  
            c.moveToPosition(i);  
            // Get name  
            String name = c.getString(1);  
            String gender = c.getString(2);  
            int age = c.getInt(3);  
            // Output log  
            Log.i("emp", name+":"+gender+":"+age);  
        }  
    }  
}  
// insert  
private void insert(){  
    // Declaration Uri  
    Uri uri = Employee.CONTENT_URI;  
    // Instantiate ContentValues  
    ContentValues values = new ContentValues();  
    // Add employee information  
    values.put(Employee.NAME, "amaker");  
    values.put(Employee.GENDER, "male");  
    values.put(Employee.AGE,30);  
    // Get ContentResolver and insert  
    getContentResolver().insert(uri, values);  
}  

}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/Employees.java

package com.amaker.ch10.app;

import android.net.Uri;
import android.provider.BaseColumns;

/**

  • Address book constant class
    */

public final class Employees {

// Authorization constant  
public static final String AUTHORITY = "com.amaker.provider.Employees";  
private Employees() {}  
// Inner class  
public static final class Employee implements BaseColumns {  
    // Construction method  
    private Employee() {}  
    // Access Uri  
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/employee");  
    // Content type  
    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.amaker.employees";  
    public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.amaker.employees";  
      
    // Default sort constant  
    public static final String DEFAULT_SORT_ORDER = "name DESC";// Sort by name  
    // Table field constant  
    public static final String NAME = "name";                    // full name  
    public static final String GENDER= "gender";                // Gender  
    public static final String AGE = "age";                     // Age  
}  

}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/EmployeeProvider.java

package com.amaker.ch10.app;

import java.util.HashMap;

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.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

import com.amaker.ch10.app.Employees.Employee;

public class EmployeeProvider extends ContentProvider{

// Database help class  
private DBHelper dbHelper;  
// Uri tool class  
private static final UriMatcher sUriMatcher;  
// Query and update conditions  
private static final int EMPLOYEE = 1;  
private static final int EMPLOYEE_ID = 2;  
// Query column set  
private static HashMap<String, String> empProjectionMap;  
static {  
    // Uri matching tool class  
    sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
    sUriMatcher.addURI(Employees.AUTHORITY, "employee", EMPLOYEE);  
    sUriMatcher.addURI(Employees.AUTHORITY, "employee/#", EMPLOYEE_ID);  
    // Instantiate query column collection  
    empProjectionMap = new HashMap<String, String>();  
    // Add query column  
    empProjectionMap.put(Employee._ID, Employee._ID);  
    empProjectionMap.put(Employee.NAME, Employee.NAME);  
    empProjectionMap.put(Employee.GENDER, Employee.GENDER);  
    empProjectionMap.put(Employee.AGE, Employee.AGE);  
}  

// Create is call  
public boolean onCreate() {  
    // Instantiate database help class  
    dbHelper = new DBHelper(getContext());  
    return true;  
}  
// Add method  
public Uri insert(Uri uri, ContentValues values) {  
    // Get database instance  
    SQLiteDatabase db = dbHelper.getWritableDatabase();  
    // Insert data and return row ID  
    long rowId = db.insert(DBHelper.EMPLOYEES_TABLE_NAME, Employee.NAME, values);  
    // If the insertion is successful, the uri is returned  
    if (rowId > 0) {  
        Uri empUri = ContentUris.withAppendedId(Employee.CONTENT_URI, rowId);  
        getContext().getContentResolver().notifyChange(empUri, null);  
        return empUri;  
    }  
    return null;  
}  
// Delete method  
public int delete(Uri uri, String selection, String[] selectionArgs) {  
    // Get database instance  
    SQLiteDatabase db = dbHelper.getWritableDatabase();  
     // Get database instance  
    int count;  
    switch (sUriMatcher.match(uri)) {  
    // Delete according to specified conditions  
    case EMPLOYEE:  
        count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, selection, selectionArgs);  
        break;  
    // Delete according to the specified condition and ID  
    case EMPLOYEE_ID:  
        String noteId = uri.getPathSegments().get(1);  
        count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, Employee._ID + "=" + noteId  
                + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);  
        break;  

    default:  
        throw new IllegalArgumentException("FALSE URI " + uri);  
    }  
    getContext().getContentResolver().notifyChange(uri, null);  
    return count;  
}  

// Get type  
public String getType(Uri uri) {  
    return null;  
}  

// Query method  
public Cursor query(Uri uri, String[] projection, String selection,  
        String[] selectionArgs, String sortOrder) {  
     SQLiteQueryBuilder qb = new SQLiteQueryBuilder();  
        switch (sUriMatcher.match(uri)) {  
        // Query all  
        case EMPLOYEE:  
            qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);  
            qb.setProjectionMap(empProjectionMap);  
            break;  
        // Query by ID  
        case EMPLOYEE_ID:  
            qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);  
            qb.setProjectionMap(empProjectionMap);  
            qb.appendWhere(Employee._ID + "=" + uri.getPathSegments().get(1));  
            break;  
        default:  
            throw new IllegalArgumentException("Uri Wrong! " + uri);  
        }  

        // Use default sort  
        String orderBy;  
        if (TextUtils.isEmpty(sortOrder)) {  
            orderBy = Employee.DEFAULT_SORT_ORDER;  
        } else {  
            orderBy = sortOrder;  
        }  

        // Get database instance  
        SQLiteDatabase db = dbHelper.getReadableDatabase();  
        // Returns a collection of cursors  
        Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);  
        c.setNotificationUri(getContext().getContentResolver(), uri);  
        return c;  
}  

// Update method  
public int update(Uri uri, ContentValues values, String selection,  
        String[] selectionArgs) {  
    // Get database instance  
    SQLiteDatabase db = dbHelper.getWritableDatabase();  
    int count;  
    switch (sUriMatcher.match(uri)) {  
    // Update according to specified conditions  
    case EMPLOYEE:  
        count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, selection, selectionArgs);  
        break;  
    // Update based on specified criteria and ID  
    case EMPLOYEE_ID:  
        String noteId = uri.getPathSegments().get(1);  
        count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, Employee._ID + "=" + noteId  
                + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);  
        break;  
    default:  
        throw new IllegalArgumentException("FALSE URI " + uri);  
    }  
    getContext().getContentResolver().notifyChange(uri, null);  
    return count;  
}  

}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/DBHelper.java

package com.amaker.ch10.app;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.amaker.ch10.app.Employees.Employee;
/**

  • Database tool class
    */

public class DBHelper extends SQLiteOpenHelper{

// Database name constant  
private static final String DATABASE_NAME = "Employees.db";  
// Database version constant  
private static final int DATABASE_VERSION = 1;  
// Table name constant  
public static final String EMPLOYEES_TABLE_NAME = "employee";  
// Construction method  
public DBHelper(Context context) {  
    // Create database  
    super(context, DATABASE_NAME,null, DATABASE_VERSION);  
}  

// Called on Creation  
public void onCreate(SQLiteDatabase db) {  
    db.execSQL("CREATE TABLE " + EMPLOYEES_TABLE_NAME + " ("  
            + Employee._ID + " INTEGER PRIMARY KEY,"  
            + Employee.NAME + " TEXT,"  
            + Employee.GENDER + " TEXT,"  
            + Employee.AGE + " INTEGER"  
            + ");");  
}  

// Called on version update  
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
    // Delete table  
    db.execSQL("DROP TABLE IF EXISTS employee");  
    onCreate(db);  
}  

}
/Chapter10_ContentProvider_01_Test02/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"

  package="com.amaker.ch10.app" 
  android:versionCode="1" 
  android:versionName="1.0"> 
<application android:icon="@drawable/icon" android:label="@string/app_name"> 
  
    <provider android:name="EmployeeProvider"   
    android:authorities="com.amaker.provider.Employees"/> 
  
    <activity android:name=".MainActivity" 
              android:label="@string/app_name"> 
        <intent-filter> 
            <action android:name="android.intent.action.MAIN" /> 
            <category android:name="android.intent.category.LAUNCHER" /> 
        </intent-filter> 
    </activity> 

</application> 
<uses-sdk android:minSdkVersion="3" /> 

</manifest>

Topics: Android