實現基本內容提供程式類

1)建立合同類

契約類定義了有助於應用程式使用內容 URI,列名,意圖操作和內容提供程式的其他功能的常量。合同類不會自動包含在提供者中; 提供者的開發者必須定義它們,然後將它們提供給其他開發人員。

提供者通常具有單個許可權,該許可權用作其 Android 內部名稱。為避免與其他提供程式衝突,請使用唯一的內容許可權。由於此建議對於 Android 程式包名稱也是如此,因此你可以將提供程式許可權定義為包含提供程式的程式包名稱的副檔名。例如,如果你的 Android 軟體包名稱為 com.example.appname,則應該向你的提供商授予許可權 com.example.appname.provider

public class MyContract {
    public static final String CONTENT_AUTHORITY = "com.example.myApp";
    public static final String PATH_DATATABLE = "dataTable";
    public static final String TABLE_NAME = "dataTable";
}

內容 URI 是標識提供者中的資料的 URI。內容 URI 包括整個提供程式的符號名稱(其許可權)以及指向表或檔案(路徑)的名稱。可選的 id 部分指向表中的單個行。ContentProvider 的每個資料訪問方法都有一個內容 URI 作為引數; 這允許你確定要訪問的表,行或檔案。在合同類中定義它們。

public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_DATATABLE).build();

// define all columns of table and common functions required

2)建立助手類

幫助程式類管理資料庫建立和版本管理。

public class DatabaseHelper extends SQLiteOpenHelper {

    // Increment the version when there is a change in the structure of database
    public static final int DATABASE_VERSION = 1;
    // The name of the database in the filesystem, you can choose this to be anything
    public static final String DATABASE_NAME = "weather.db";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // Called when the database is created for the first time. This is where the
        // creation of tables and the initial population of the tables should happen.
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Called when the database needs to be upgraded. The implementation
        // should use this method to drop tables, add tables, or do anything else it
        // needs to upgrade to the new schema version.
    }
}

3)建立一個擴充套件 ContentProvider 類的類

public class MyProvider extends ContentProvider {

public DatabaseHelper dbHelper;

public static final UriMatcher matcher = buildUriMatcher();
public static final int DATA_TABLE = 100;
public static final int DATA_TABLE_DATE = 101;

UriMatcher 將許可權和路徑對映到整數值。方法 match() 為 URI 返回一個唯一的整數值(它可以是任意數字,只要它是唯一的)。switch 語句在查詢整個表和查詢單個記錄之間進行選擇。如果 URI 是表的內容 URI,則我們的 UriMatcher 返回 100;如果 URI 指向該表中的特定行,則返回 101。你可以使用 # 萬用字元匹配任何數字和*以匹配任何字串。

public static UriMatcher buildUriMatcher() {
    UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(CONTENT_AUTHORITY, MyContract.PATH_DATATABLE,        DATA_TABLE);
    uriMatcher.addURI(CONTENT_AUTHORITY, MyContract.PATH_DATATABLE + "/#", DATA_TABLE_DATE);
    return uriMatcher;
}

重要提示: addURI() 呼叫的順序很重要! UriMatcher 將從第一個新增到最後一個按順序檢視。由於像 #*這樣的萬用字元很貪婪,因此你需要確保已正確地訂購了 URI。例如:

uriMatcher.addURI(CONTENT_AUTHORITY, "/example", 1);
uriMatcher.addURI(CONTENT_AUTHORITY, "/*",       2);

是正確的排序,因為匹配器將首先尋找/example,然後才能使用/*匹配。如果這些方法呼叫被反轉並且你呼叫了 uriMatcher.match("/example"),那麼 UriMatcher 一旦遇到/*路徑就會停止尋找匹配並返回錯誤的結果!

然後,你需要覆蓋這些功能:

onCreate() :初始化你的提供者。Android 系統在建立提供程式後立即呼叫此方法。請注意,在 ContentResolver 物件嘗試訪問它之前,不會建立提供程式。

@Override
public boolean onCreate() {
    dbhelper = new DatabaseHelper(getContext());
    return true;
}

getType() :返回與內容 URI 對應的 MIME 型別

@Override
public String getType(Uri uri) {
    final int match = matcher.match(uri);
    switch (match) {
        case DATA_TABLE:
            return ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + MyContract.CONTENT_AUTHORITY + "/" + MyContract.PATH_DATATABLE;
        case DATA_TABLE_DATE:
            return ContentResolver.ANY_CURSOR_ITEM_TYPE + "/" + MyContract.CONTENT_AUTHORITY + "/" + MyContract.PATH_DATATABLE;
        default:
            throw new UnsupportedOperationException("Unknown Uri: " + uri);

    }
}

query() :從提供者中檢索資料。使用引數選擇要查詢的表,要返回的行和列以及結果的排序順序。將資料作為 Cursor 物件返回。

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    Cursor retCursor = dbHelper.getReadableDatabase().query(
        MyContract.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
    retCursor.setNotificationUri(getContext().getContentResolver(), uri);
    return retCursor;
}

在你的提供程式中插入一個新行。使用引數選擇目標表並獲取要使用的列值。返回新插入行的內容 URI。

@Override
public Uri insert(Uri uri, ContentValues values)
{
    final SQLiteDatabase db = dbHelper.getWritableDatabase();
    long id = db.insert(MyContract.TABLE_NAME, null, values);
    return ContentUris.withAppendedId(MyContract.CONTENT_URI, ID);
}

delete() :從提供者中刪除行。使用引數選擇表和要刪除的行。返回已刪除的行數。

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int rowsDeleted = db.delete(MyContract.TABLE_NAME, selection, selectionArgs);
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsDeleted;
}

update() :更新提供程式中的現有行。使用引數選擇要更新的表和行以及獲取新列值。返回更新的行數。

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int rowsUpdated = db.update(MyContract.TABLE_NAME, values, selection, selectionArgs);
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
}

4)更新清單檔案

<provider
        android:authorities="com.example.myApp"
        android:name=".DatabaseProvider"/>