参考:
http://www.cnblogs.com/linjiqin/archive/2011/05/28/2061396.html
http://aijiawang-126-com.iteye.com/blog/655268
http://blog.csdn.net/imyfriend/article/details/6589917
public class Book { public static final String DATABASE_NAME="books.db"; public static final String TABLE_NAME="book"; public static final int VERSION=1; public static final String ID="_id"; public static final String TITLE="title"; public static final String PRICE ="price"; public static final String AUTHORITY="com.android.provider.book"; public static final int ITEM=1; public static final int ITEM_ID=2; public static final String CONTENT_TYPE="vnd.android.cursor.dir/vnd.com.android.book"; public static final String CONTENT_ITEM_TYPE="vnd.android.cursor.item/vnd.com.android.book"; public static final Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/item");}
package com.android.bookgallery;import android.app.Activity;import android.content.ContentResolver;import android.content.ContentUris;import android.content.ContentValues;import android.database.ContentObserver;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.os.Handler;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.CursorAdapter;import android.widget.EditText;import android.widget.ListView;import android.widget.SimpleCursorAdapter;public class BookGallery extends Activity { private class MyrContentObserver extends ContentObserver { public MyrContentObserver() { super(new Handler()); } public void onChange(final boolean selfChange) { Log.v("test", "Service ContentObserver received notification"); } } MyrContentObserver mObserver; private void registMyContentObserver(){ mObserver = new MyrContentObserver(); getContentResolver().registerContentObserver(Book.CONTENT_URI, true, mObserver); } private void unregistMyContentObserver(){ getContentResolver().unregisterContentObserver(mObserver); } /** Called when the activity is first created. */ EditText etTitle; EditText etPrice; Button btnAdd; Button btnDelete; ListView lvBooks; ContentResolver resolver; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); System.out.println("BookGallery: onCreate.... "); setContentView(R.layout.main); etTitle = (EditText) findViewById(R.id.ettitle); etPrice = (EditText) findViewById(R.id.etprice); btnAdd = (Button) findViewById(R.id.add); btnDelete = (Button) findViewById(R.id.delete); lvBooks = (ListView) findViewById(R.id.booklist); resolver = getContentResolver(); registMyContentObserver(); Cursor cs = resolver.query(Book.CONTENT_URI, null, null, null, Book.ID + " ASC"); CursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, cs, new String[] { Book.TITLE, Book.PRICE }, new int[] { android.R.id.text1, android.R.id.text2 }); lvBooks.setAdapter(adapter); btnAdd.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub ContentValues contentValues; try { String countryText = String.valueOf(etTitle.getText()); String codeNum = String.valueOf(etPrice.getText()); contentValues = new ContentValues(); contentValues.put(Book.TITLE, countryText); contentValues.put(Book.PRICE, codeNum); } catch (Exception e) { contentValues = new ContentValues(); } resolver.insert(Book.CONTENT_URI, contentValues); } }); btnDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub Uri uri = ContentUris.withAppendedId(Book.CONTENT_URI, 2); System.out.println("btnDelete.setOnClickListener...." + uri.toString()); resolver.delete(uri, null, null); } }); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unregistMyContentObserver(); }}
provider类
package com.android.provider.book;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.Context;import android.content.UriMatcher;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.net.Uri;import android.text.TextUtils;import android.util.Log;public class BookProvider extends ContentProvider { public class BookDatabasehelper extends SQLiteOpenHelper { public BookDatabasehelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub System.out.println("BookDatabasehelper onCreate... "); db.execSQL("CREATE TABLE " + Book.TABLE_NAME + " (" + Book.ID + " INTEGER PRIMARY KEY," + Book.TITLE + " TEXT," + Book.PRICE + " TEXT" + ");"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub System.out.println("BookDatabasehelper onUpgrade... "); Log.w("BookDatabasehelper", "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS notes"); onCreate(db); } } public BookDatabasehelper databasehelper; public static final UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(Book.AUTHORITY, "item", Book.ITEM); uriMatcher.addURI(Book.AUTHORITY, "item/#", Book.ITEM_ID); } @Override public int delete(Uri uri, String where, String[] args) { // TODO Auto-generated method stub System.out.println("BookProvider delete...."); SQLiteDatabase db = databasehelper.getWritableDatabase(); int count; switch (uriMatcher.match(uri)) { case Book.ITEM: count = db.delete(Book.TABLE_NAME, where, args); System.out.println("BookProvider delete....count" + count); break; case Book.ITEM_ID: String id = uri.getPathSegments().get(1); count = db.delete(Book.TABLE_NAME, Book.ID + "=" + id + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), args); System.out.println("BookProvider delete....count" + count + "id=" + id); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub System.out.println(" BookProvider getType..."); int code = uriMatcher.match(uri); switch (code) { case Book.ITEM: System.out.println(" BookProvider getType..." + Book.CONTENT_TYPE); return Book.CONTENT_TYPE; case Book.ITEM_ID: System.out.println(" BookProvider getType..." + Book.CONTENT_ITEM_TYPE); return Book.CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("Unknown URI " + uri); } } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub System.out.println("BookProvider insert..."); SQLiteDatabase db = databasehelper.getWritableDatabase(); long rowId; if (uriMatcher.match(uri) != Book.ITEM) { throw new IllegalArgumentException("Unknown URI " + uri); } rowId = db.insert(Book.TABLE_NAME, Book.ID, values); if (rowId > 0) { Uri noteUri = ContentUris.withAppendedId(Book.CONTENT_URI, rowId); System.out.println("BookProvider insert notifyChange"); getContext().getContentResolver().notifyChange(noteUri, null); return noteUri; } throw new SQLException("Failed to insert row into " + uri); } @Override public boolean onCreate() { // TODO Auto-generated method stub System.out.println("BookProvider onCreate:"); databasehelper = new BookDatabasehelper(getContext(), Book.DATABASE_NAME, null, Book.VERSION); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub System.out.println("BookProvider query:"); SQLiteDatabase db = databasehelper.getReadableDatabase(); Cursor c; switch (uriMatcher.match(uri)) { case Book.ITEM: c = db.query(Book.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); System.out.println("BookProvider query:" + Book.CONTENT_TYPE); break; case Book.ITEM_ID: String id = uri.getPathSegments().get(1); c = db.query(Book.TABLE_NAME, projection, Book.ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs, null, null, sortOrder); System.out.println("BookProvider query:" + Book.CONTENT_ITEM_TYPE); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public int update(Uri uri, ContentValues values, String where, String[] args) { // TODO Auto-generated method stub System.out.println("BookProviderupdate.... "); SQLiteDatabase db = databasehelper.getWritableDatabase(); int count; switch (uriMatcher.match(uri)) { case Book.ITEM: count = db.update(Book.TABLE_NAME, values, where, args); break; case Book.ITEM_ID: String id = uri.getPathSegments().get(1); count = db.update(Book.TABLE_NAME, values, Book.ID + "=" + id + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), args); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; }}
要点:
getType(Uri uri) :
单item vnd.android.cursor.item
多item vnd.android.cursor.dir/
Implement this to handle requests for the MIME type of the data at the given URI. The returned MIME type should start with vnd.android.cursor.item
for a single record, or vnd.android.cursor.dir/
for multiple items. This method can be called from multiple threads, as described in .
Note that there are no permissions needed for an application to access this information; if your content provider requires read and/or write permissions, or is not exported, all applications can still call this method regardless of their access permissions. This allows them to retrieve the MIME type for a URI when dispatching intents.
getContentResolver().notifyChange(uri, null) contentobserver 观察者