Android之自定义ContentProvider详解
第一個版本 ?對android中MIME類型的理解
初始MIME類型,是在學(xué)習(xí)ContentProvider的時候。
??????當(dāng)在創(chuàng)建自己的ContentProvider的時,需要從抽象類ContentProvider中派生出自己的子類,并實現(xiàn)其中5個抽象方法:
- query(Uri, String[], String, String[], String) 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
?????? 至于前四個方法,不是本文想要討論的重點,就不做冗余的闡述了;有意思的是這個方法getType(Uri),根據(jù)幫助文檔的解釋,它返回一個MIME類型。
?????? 首先,先百度了一下MIME類型,根據(jù)百度百科的解釋:MIME:全稱Multipurpose Internet Mail Extensions,多功能Internet 郵件擴(kuò)充服務(wù)。它是一種多用途網(wǎng)際郵件擴(kuò)充協(xié)議,在1992年最早應(yīng)用于電子郵件系統(tǒng),但后來也應(yīng)用到瀏覽器。MIME類型就是設(shè)定某種擴(kuò)展名的文件用一種應(yīng)用程序來打開的方式類型,當(dāng)該擴(kuò)展名文件被訪問的時候,瀏覽器會自動使用指定應(yīng)用程序來打開。多用于指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。
????? 看完百度百科的解釋,相信大家和我一樣,仍然不解。結(jié)合一個例子,與老師交流之后,我的理解是這樣的:
?????? 在ContentProvider的getType(Uri)方法中,可以顯示的返回一個MIME類型,該方法返回一個字符串,可以是任意的字符串,當(dāng)我們顯示的返回該MIME類型的時候,相當(dāng)于通過該方法的驗證,Provider可以識別自身其他方法返回的Cursor的內(nèi)容,不需要在進(jìn)行更多的驗證;如果返回其他的字符串(非android能夠識別的MIME類型,例如直接返回當(dāng)前的包名),則Provider在執(zhí)行其他方法后,返回Cursor類型的時候,需要再次進(jìn)行驗證。
??? 還是云里霧里的?下面來看一個使用了MIME類型的自定義ContentProvider的例子:
import android.net.Uri;
public class Shopping {
?
// 定義數(shù)據(jù)庫的名字
public static final String DATABASE_NAME = "shopping_db";
// 定義數(shù)據(jù)庫的版本
public static final int DATABASE_VERSION = 1;
// 表的名字
public static final String TABLE_NAME = "t_shopping";
// 定義數(shù)據(jù)庫的字段
public static final String FIELD_ID = "_id";
public static final String FIELE_NAME = "product_name";
// 定義訪問的類型
public static final int ITEM = 1;
public static final int ITEM_ID = 2;
// 定義MIME類型,訪問單個記錄
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.stone.shopping";
// 訪問數(shù)據(jù)集
public static final String CONTENT_ITEM = "vnd.android.cursor.dir/vnd.stone.shopping";
// 定義訪問ContentProvider權(quán)限
public static final String AUTHORITY = "com.stone.shopping";
// 定義URI
public static final Uri URI = Uri.parse("content://" + AUTHORITY + "/item");
}?
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
public class MyDbHelper extends SQLiteOpenHelper {
public MyDbHelper(Context context, String name, CursorFactory factory,?int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE " + Shopping.TABLE_NAME + " ( "?+?
Shopping.FIELD_ID + " INTEGER primary key autoincrement, "?+ " " + Shopping.FIELE_NAME + " TEXT)";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String sql = "DROP TABLE IF EXISTS " + Shopping.TABLE_NAME;
db.execSQL(sql);
onCreate(db);
}
}??
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.text.TextUtils;
public class MyProvider extends ContentProvider {
private MyDbHelper myDbHelper;
private static final UriMatcher mUriMatcher; // 進(jìn)行匹配的Uri的設(shè)定
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(Shopping.AUTHORITY, "item", Shopping.ITEM);
mUriMatcher.addURI(Shopping.AUTHORITY, "item/#", Shopping.ITEM_ID);
}
@Override
public boolean onCreate() {
// 創(chuàng)建數(shù)據(jù)庫
myDbHelper = new MyDbHelper(getContext(), Shopping.DATABASE_NAME, null, Shopping.DATABASE_VERSION);
return true;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = myDbHelper.getWritableDatabase();
int count = 0;
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
ount = db.delete(Shopping.TABLE_NAME, selection, selectionArgs);
break;
case Shopping.ITEM_ID:
// 通過Uri獲取Id,根據(jù)主鍵進(jìn)行刪除
String id = uri.getPathSegments().get(1);
System.out.println(String.valueOf(uri.getPathSegments().size()));
count = db.delete(Shopping.TABLE_NAME,Shopping.FIELD_ID + "=" + id, selectionArgs);
break;
default:
throw new IllegalArgumentException();
}
// 通知數(shù)據(jù)發(fā)生改變
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = myDbHelper.getWritableDatabase();
long row = 0;
if (mUriMatcher.match(uri) != Shopping.ITEM) {
throw new IllegalArgumentException();
}
row = db.insert(Shopping.TABLE_NAME, Shopping.FIELD_ID, values);
if (row > 0) {
Uri noteUri = ContentUris.withAppendedId(Shopping.URI, row);
getContext().getContentResolver().notifyChange(uri, null);
return noteUri;
}
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = myDbHelper.getReadableDatabase();
Cursor cursor = null;
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
cursor = db.query(Shopping.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
break;
case Shopping.ITEM_ID:
String id = uri.getPathSegments().get(1);
cursor = db.query(Shopping.TABLE_NAME, projection,?Shopping.FIELD_ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""),
selectionArgs,?null, null, sortOrder);
break;
default:
throw new IllegalArgumentException();
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,?String[] selectionArgs) {
SQLiteDatabase db = myDbHelper.getWritableDatabase();
int count = 0;
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
count = db.update(Shopping.TABLE_NAME, values, selection, selectionArgs);
break;
case Shopping.ITEM_ID:
String id = uri.getPathSegments().get(1);
count = db.update(Shopping.TABLE_NAME, values, Shopping.FIELD_ID?+ "="?+ id?+ (!TextUtils.isEmpty(selection) ? " AND (" + selection?+ ')' : ""),
selectionArgs);
break;
default:
throw new IllegalArgumentException();
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri uri) { // 進(jìn)行Uri匹配完成不同的處理工作
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
return Shopping.CONTENT_ITEM;
case Shopping.ITEM_ID:
return Shopping.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException();
}
}
}
??? 在上面的例子中,首先有一個Shopping類,定義了一系列的常量。包括訪問的數(shù)據(jù)庫的相關(guān)信息和URI的定義,其中最重要的就是下面的兩句,MIME類型的定義:
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.stone.shopping";
public static final String CONTENT_ITEM = "vnd.android.cursor.dir/vnd.stone.shopping";?
??? 其次是一個MyDbHelper類,繼承自SQLiteOpenHelper類,用于一些數(shù)據(jù)庫相關(guān)操作,這里就不贅述了。
??? 最后的MyProvider類使我們的重頭戲,首先我們來看這一段代碼:
private static final UriMatcher mUriMatcher; // 進(jìn)行匹配的Uri的設(shè)定
static {
?? mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
?? mUriMatcher.addURI(Shopping.AUTHORITY, "item", Shopping.ITEM);
?? mUriMatcher.addURI(Shopping.AUTHORITY, "item/#", Shopping.ITEM_ID);
}
??? UriMatcher表示一個Uri的匹配器,它會對我們請求的Uri進(jìn)行匹配,而匹配的格式就是這里我們通過addURI()方法添加格式。
??? 接下來,首先執(zhí)行的就是getType(Uri)方法,下面來看該方法體中的代碼:
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
return Shopping.CONTENT_ITEM;
case Shopping.ITEM_ID:
return Shopping.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException();
}???
??? 當(dāng)請求過來的Uri通過mUriMatcher.match(uri)方法進(jìn)行匹配,根據(jù)不同的匹配值來返回不同的MIME類型。下面我們來結(jié)合query(Uri, String[], String, String[], String)這個方法來解釋一下:
??? 在該方法中,返回一個Cursor游標(biāo)對象。而Cursor中是單條的記錄還是一個集合,需要和在getType()方法中返回的類型保持一致。當(dāng)返回的MIME類型是Shopping.CONTENT_ITEM時,Cursor應(yīng)該是一個集合;當(dāng)返回的MIME類型是Shopping.CONTENT_ITEM_TYPE時,Cursor應(yīng)該是單條記錄。
??? 由于在getType()方法里面,我們顯示的返回了android平臺可以識別的MIME類型,所以在執(zhí)行query()方法返回Cursor對象的時候,系統(tǒng)將不需要再進(jìn)行驗證,從而可以說是節(jié)省了系統(tǒng)開銷。
?
????話已至此,那么何謂android平臺可以識別的MIME類型呢?下面來分析一下MIME類型的結(jié)構(gòu):
????其實,MIME類型其實就是一個字符串,中間有一個 “/” 來隔開,“/”前面的部分是系統(tǒng)識別的部分,就相當(dāng)于我們定義一個變量時的變量數(shù)據(jù)類型,通過這個“數(shù)據(jù)類型”,系統(tǒng)能夠知道我們所要表示的是個什么東西。至于 “/” 后面的部分就是我們自已來隨便定義的“變量名”了。
????那么,既然MIME類型就是一個字符串,那么我們的getType()自然也可以隨便返回一個系統(tǒng)不能識別的字符串啦?沒錯,有些時候我們確實也這樣處理,比如說可以這樣寫:
?
public String getType(Uri uri) {
return getContext().getPackageName();?
}
?
??? 這里,我們把當(dāng)前上下文的包名返回了。這樣處理的結(jié)果是怎樣的呢?
?
??? 簡單的說,系統(tǒng)不能夠識別它了,也就不會做任何處理。仍然以query()方法來說,當(dāng)執(zhí)行完方法體(這里需要注意一下:在這種情況下,即使我們沒有通過返回MIME類型字符串來進(jìn)行驗證處理,但是在query()方法中再次對Uri進(jìn)行了匹配并根據(jù)不同的Uri類型進(jìn)行了不同的操作)返回Cursor對象的時候,這時候系統(tǒng)不能肯定返回的Cursor對象是否合法,因此需要對其進(jìn)行驗證,這樣對系統(tǒng)資源算是一個浪費了吧。所以,我們最好還是顯示的返回一個MIME類型吧,當(dāng)然要寫正確了,讓我們android平臺可以識別。
sourceurl:http://blog.csdn.net/h3g2010/article/details/6093366
第二個版本
在Android中,每個程序都在自己的進(jìn)程中運行,互不干擾.這樣的好處不說了,但是帶來的問題就是想要在程序之間實現(xiàn)數(shù)據(jù)共享,在沒有其它工具的幫助下,就難以實現(xiàn)了.為了解決這個問題,ContentProvider就派上用場了.
一,說說ContentProvider怎么用.
???1,把你想要共享出去的數(shù)據(jù)用一個URl表示出來.如:content://contacts/people/5(聯(lián)系人信息中Id位5的聯(lián)系人記錄).或者這樣也行:Uri person =ContentUris.withAppendedId(People.CONTENT_URI,5);來封裝.
?? 2,所有的Content Providers都會實現(xiàn)一些共同的接口,可以通過唯一的ContentResolveer來向外提供數(shù)據(jù),冰進(jìn)行一系列的增刪改查;ContentResolver cr = getContentResplver();
?? 3,cr利用定義好的uri(作為參數(shù)送給cr封裝好的方法里面進(jìn)行一系列的操作);
至于ContentProvider的實例化,這些不需要我們?nèi)プ?系統(tǒng)會做這件事.對于ContentProvider,正常情況下,只需一個,但是ContentResolver可以存在多個,在不同進(jìn)程中的
ContentResolver可以使用同一個ContentProvider.
二,定義自己的ContentProvider
??? 根據(jù)我個人的理解,這作用就有點像J2EE里面的DAO的作用.
?? ?
??? 1,實現(xiàn)一個定義節(jié)本字段的類.示例如下:
???????? ?
???????? ?
? public class NotePad
{
?? ?//ContentProvider的uri
?? ?public static final String?? ?AUTHORITY?? ?= "com.google.provider.NotePad";
?? ?private NotePad(){}
?? ?// 定義基本字段
?? ?public static final class Notes implements BaseColumns
?? ?{
?? ??? ?private Notes(){}
?? ??? ?public static final Uri?? ??? ?CONTENT_URI?? ??? ??? ?= Uri.parse("content://" + AUTHORITY + "/notes");
?? ??? ?// 新的MIME類型-多個
?? ??? ?public static final String?? ?CONTENT_TYPE?? ??? ?= "vnd.android.cursor.dir/vnd.google.note";
?? ??? ?// 新的MIME類型-單個
?? ??? ?public static final String?? ?CONTENT_ITEM_TYPE?? ?= "vnd.android.cursor.item/vnd.google.note";
?? ??? ?public static final String?? ?DEFAULT_SORT_ORDER?? ?= "modified DESC";
?? ??? ?//字段
?? ??? ?public static final String?? ?TITLE?? ??? ??? ??? ?= "title";
?? ??? ?public static final String?? ?NOTE?? ??? ??? ??? ?= "note";
?? ??? ?public static final String?? ?CREATEDDATE?? ??? ?= "created";
?? ??? ?public static final String?? ?MODIFIEDDATE?? ??? ?= "modified";
?? ?}
}
???????? ?
?解釋一下MIME類型,假如你要處理的數(shù)據(jù)類型是新的類型,就得定義一個新的MIME類型,一邊ContentProvider.getType(url)來調(diào)用;
?粉單個與多個;
?
?2,創(chuàng)建自己的ContentProvider
???? ?
????如果要共享的是數(shù)據(jù)庫,我們在這里可以封裝一個SqlLiteOpenHelper,以便建庫建表 ,對于 SqlLiteOpenHelper 用過數(shù)據(jù)庫的人應(yīng)該都懂,在這里就不贅述了;
?? ?
??? 然后在ContentProvider里面實現(xiàn)增刪改查,另外如果有自定義類型的話,還的在ContentProvider劉main實現(xiàn)一個方法?? ?
?? ??? ?
?? ?public String getType(Uri uri)
?? ?{
?? ??? ?switch (sUriMatcher.match(uri))
?? ??? ?{
?? ??? ??? ?case NOTES:
?? ??? ??? ??? ?return Notes.CONTENT_TYPE;
?? ??? ??? ?case NOTE_ID:
?? ??? ??? ??? ?return Notes.CONTENT_ITEM_TYPE;
?? ??? ??? ?default:
?? ??? ??? ??? ?throw new IllegalArgumentException("Unknown URI " + uri);
?? ??? ?}
?? ?}
?
?實例如下:
?
???? public class NotePadProvider extends ContentProvider
{
?? ?private static final String?? ??? ??? ??? ?TAG?? ??? ??? ??? ??? ?= "NotePadProvider";
?? ?// 數(shù)據(jù)庫名
?? ?private static final String?? ??? ??? ??? ?DATABASE_NAME?? ??? ?= "note_pad.db";
?? ?private static final int?? ??? ??? ??? ?DATABASE_VERSION?? ?= 2;
?? ?// 表名
?? ?private static final String?? ??? ??? ??? ?NOTES_TABLE_NAME?? ?= "notes";
?? ?private static HashMap<String, String>?? ?sNotesProjectionMap;
?? ?private static final int?? ??? ??? ??? ?NOTES?? ??? ??? ??? ?= 1;
?? ?private static final int?? ??? ??? ??? ?NOTE_ID?? ??? ??? ??? ?= 2;
?? ?private static final UriMatcher?? ??? ??? ?sUriMatcher;
?? ?private DatabaseHelper?? ?mOpenHelper;
?? ?//創(chuàng)建表SQL語句
?? ?private static final String?? ??? ??? ??? ?CREATE_TABLE="CREATE TABLE "?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ NOTES_TABLE_NAME?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ " (" + Notes._ID?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ " INTEGER PRIMARY KEY,"?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ Notes.TITLE?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ " TEXT,"?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ Notes.NOTE?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ " TEXT,"
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ Notes.CREATEDDATE?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ " INTEGER,"?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ Notes.MODIFIEDDATE?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?+ " INTEGER" + ");";
?? ?
?? ?static
?? ?{
?? ??? ?sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
?? ??? ?sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);
?? ??? ?sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);
?? ??? ?sNotesProjectionMap = new HashMap<String, String>();
?? ??? ?sNotesProjectionMap.put(Notes._ID, Notes._ID);
?? ??? ?sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE);
?? ??? ?sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE);
?? ??? ?sNotesProjectionMap.put(Notes.CREATEDDATE, Notes.CREATEDDATE);
?? ??? ?sNotesProjectionMap.put(Notes.MODIFIEDDATE, Notes.MODIFIEDDATE);
?? ?}
?? ?private static class DatabaseHelper extends SQLiteOpenHelper
?? ?{
?? ??? ?//構(gòu)造函數(shù)-創(chuàng)建數(shù)據(jù)庫
?? ??? ?DatabaseHelper(Context context)
?? ??? ?{
?? ??? ??? ?super(context, DATABASE_NAME, null, DATABASE_VERSION);
?? ??? ?}
?? ??? ?//創(chuàng)建表
?? ??? ?@Override
?? ??? ?public void onCreate(SQLiteDatabase db)
?? ??? ?{
?? ??? ??? ?db.execSQL(CREATE_TABLE);
?? ??? ?}
?? ??? ?//更新數(shù)據(jù)庫
?? ??? ?@Override
?? ??? ?public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
?? ??? ?{
?? ??? ??? ?db.execSQL("DROP TABLE IF EXISTS notes");
?? ??? ??? ?onCreate(db);
?? ??? ?}
?? ?}
?? ?@Override
?? ?public boolean onCreate()
?? ?{
?? ??? ?mOpenHelper = new DatabaseHelper(getContext());
?? ??? ?return true;
?? ?}
?? ?@Override
?? ?//查詢操作
?? ?public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
?? ?{
?? ??? ?SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
?? ??? ?switch (sUriMatcher.match(uri))
?? ??? ?{
?? ??? ??? ?case NOTES:
?? ??? ??? ??? ?qb.setTables(NOTES_TABLE_NAME);
?? ??? ??? ??? ?qb.setProjectionMap(sNotesProjectionMap);
?? ??? ??? ??? ?break;
?? ??? ??? ?case NOTE_ID:
?? ??? ??? ??? ?qb.setTables(NOTES_TABLE_NAME);
?? ??? ??? ??? ?qb.setProjectionMap(sNotesProjectionMap);
?? ??? ??? ??? ?qb.appendWhere(Notes._ID + "=" + uri.getPathSegments().get(1));
?? ??? ??? ??? ?break;
?? ??? ??? ?default:
?? ??? ??? ??? ?throw new IllegalArgumentException("Unknown URI " + uri);
?? ??? ?}
?? ??? ?String orderBy;
?? ??? ?if (TextUtils.isEmpty(sortOrder))
?? ??? ?{
?? ??? ??? ?orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?orderBy = sortOrder;
?? ??? ?}
?? ??? ?SQLiteDatabase db = mOpenHelper.getReadableDatabase();
?? ??? ?Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
?? ??? ?c.setNotificationUri(getContext().getContentResolver(), uri);
?? ??? ?return c;
?? ?}
?? ?@Override
?? ?// 如果有自定義類型,必須實現(xiàn)該方法
?? ?public String getType(Uri uri)
?? ?{
?? ??? ?switch (sUriMatcher.match(uri))
?? ??? ?{
?? ??? ??? ?case NOTES:
?? ??? ??? ??? ?return Notes.CONTENT_TYPE;
?? ??? ??? ?case NOTE_ID:
?? ??? ??? ??? ?return Notes.CONTENT_ITEM_TYPE;
?? ??? ??? ?default:
?? ??? ??? ??? ?throw new IllegalArgumentException("Unknown URI " + uri);
?? ??? ?}
?? ?}
?? ?@Override
?? ?//插入數(shù)據(jù)庫
?? ?public Uri insert(Uri uri, ContentValues initialValues)
?? ?{
?? ??? ?if (sUriMatcher.match(uri) != NOTES)
?? ??? ?{
?? ??? ??? ?throw new IllegalArgumentException("Unknown URI " + uri);
?? ??? ?}
?? ??? ?ContentValues values;
?? ??? ?if (initialValues != null)
?? ??? ?{
?? ??? ??? ?values = new ContentValues(initialValues);
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?values = new ContentValues();
?? ??? ?}
?? ??? ?Long now = Long.valueOf(System.currentTimeMillis());
?? ??? ?if (values.containsKey(NotePad.Notes.CREATEDDATE) == false)
?? ??? ?{
?? ??? ??? ?values.put(NotePad.Notes.CREATEDDATE, now);
?? ??? ?}
?? ??? ?if (values.containsKey(NotePad.Notes.MODIFIEDDATE) == false)
?? ??? ?{
?? ??? ??? ?values.put(NotePad.Notes.MODIFIEDDATE, now);
?? ??? ?}
?? ??? ?if (values.containsKey(NotePad.Notes.TITLE) == false)
?? ??? ?{
?? ??? ??? ?Resources r = Resources.getSystem();
?? ??? ??? ?values.put(NotePad.Notes.TITLE, r.getString(android.R.string.untitled));
?? ??? ?}
?? ??? ?if (values.containsKey(NotePad.Notes.NOTE) == false)
?? ??? ?{
?? ??? ??? ?values.put(NotePad.Notes.NOTE, "");
?? ??? ?}
?? ??? ?SQLiteDatabase db = mOpenHelper.getWritableDatabase();
?? ??? ?long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, values);
?? ??? ?if (rowId > 0)
?? ??? ?{
?? ??? ??? ?Uri noteUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);
?? ??? ??? ?getContext().getContentResolver().notifyChange(noteUri, null);
?? ??? ??? ?return noteUri;
?? ??? ?}
?? ??? ?throw new SQLException("Failed to insert row into " + uri);
?? ?}
?? ?@Override
?? ?//刪除數(shù)據(jù)
?? ?public int delete(Uri uri, String where, String[] whereArgs)
?? ?{
?? ??? ?SQLiteDatabase db = mOpenHelper.getWritableDatabase();
?? ??? ?int count;
?? ??? ?switch (sUriMatcher.match(uri))
?? ??? ?{
?? ??? ??? ?case NOTES:
?? ??? ??? ??? ?count = db.delete(NOTES_TABLE_NAME, where, whereArgs);
?? ??? ??? ??? ?break;
?? ??? ??? ?case NOTE_ID:
?? ??? ??? ??? ?String noteId = uri.getPathSegments().get(1);
?? ??? ??? ??? ?count = db.delete(NOTES_TABLE_NAME, Notes._ID + "=" + noteId + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
?? ??? ??? ??? ?break;
?? ??? ??? ?default:
?? ??? ??? ??? ?throw new IllegalArgumentException("Unknown URI " + uri);
?? ??? ?}
?? ??? ?getContext().getContentResolver().notifyChange(uri, null);
?? ??? ?return count;
?? ?}
?? ?@Override
?? ?//更新數(shù)據(jù)
?? ?public int update(Uri uri, ContentValues values, String where, String[] whereArgs)
?? ?{
?? ??? ?SQLiteDatabase db = mOpenHelper.getWritableDatabase();
?? ??? ?int count;
?? ??? ?switch (sUriMatcher.match(uri))
?? ??? ?{
?? ??? ??? ?case NOTES:
?? ??? ??? ??? ?count = db.update(NOTES_TABLE_NAME, values, where, whereArgs);
?? ??? ??? ??? ?break;
?? ??? ??? ?case NOTE_ID:
?? ??? ??? ??? ?String noteId = uri.getPathSegments().get(1);
?? ??? ??? ??? ?count = db.update(NOTES_TABLE_NAME, values, Notes._ID + "=" + noteId + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
?? ??? ??? ??? ?break;
?? ??? ??? ?default:
?? ??? ??? ??? ?throw new IllegalArgumentException("Unknown URI " + uri);
?? ??? ?}
?? ??? ?getContext().getContentResolver().notifyChange(uri, null);
?? ??? ?return count;
?? ?}
}
這樣我們就實現(xiàn)了一個自定義的ContentProvider,檔然最后不要忘記一件事情了,在AndroidMinifest.xml中聲明我們定義好的ContentProvider
??? <provider android:name="NotePadProvider"?
??? android:authorities="com.google.provider.NotePad"/>
?? ?
好了,一切OK!
總結(jié)
以上是生活随笔為你收集整理的Android之自定义ContentProvider详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android之URI简介
- 下一篇: Android之监测database的改