自定义ContentProvider以及ContentObserver的使用完整详细示例
来源:互联网 发布:无网络聊天软件 编辑:程序博客网 时间:2024/05/17 04:48
示例说明:
该示例中一共包含两个工程。其中一个工程完成了自定义ContentProvider,另外一个工程用于测试该自定义ContentProvider且在该工程中使用了ContentObserver监听自定义ContentProvider的数据变化
以下代码为工程TestContentProvider
ContentProviderTest如下:
package cn.testcontentprovider;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;/** * Demo描述: * 自定义ContentProvider的实现 * ContentProvider主要用于在不同的应用程序之间共享数据,这也是官方推荐的方式. * * 注意事项: * 1 在AndroidManifest.xml中注册ContentProvider时的属性 * android:exported=true表示允许其他应用访问. * 2 注意*和#这两个符号在Uri中的作用 * 其中*表示匹配任意长度的字符 * 其中#表示匹配任意长度的数据 * 所以: * 一个能匹配所有表的Uri可以写成: * content://cn.bs.testcontentprovider/* * 一个能匹配person表中任意一行的Uri可以写成: * content://cn.bs.testcontentprovider/person/# * */public class ContentProviderTest extends ContentProvider { private SQLiteDatabaseOpenHelper mSQLiteDatabaseOpenHelper; private final static String AUTHORITY=cn.bs.testcontentprovider; private static UriMatcher mUriMatcher; private static final int PERSON_DIR = 0; private static final int PERSON = 1; /** * 利用静态代码块初始化UriMatcher * 在UriMatcher中包含了多个Uri,每个Uri代表一种操作 * 当调用UriMatcher.match(Uri uri)方法时就会返回该uri对应的code; * 比如此处的PERSONS和PERSON */ static { mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // 该URI表示返回所有的person,其中PERSONS为该特定Uri的标识码 mUriMatcher.addURI(AUTHORITY, person, PERSON_DIR); // 该URI表示返回某一个person,其中PERSON为该特定Uri的标识码 mUriMatcher.addURI(AUTHORITY, person/#, PERSON); } /** * 在自定义ContentProvider中必须覆写getType(Uri uri)方法. * 该方法用于获取Uri对象所对应的MIME类型. * * 一个Uri对应的MIME字符串遵守以下三点: * 1 必须以vnd开头 * 2 如果该Uri对应的数据可能包含多条记录,那么返回字符串应该以vnd.android.cursor.dir/开头 * 3 如果该Uri对应的数据只包含一条记录,那么返回字符串应该以vnd.android.cursor.item/开头 */ @Override public String getType(Uri uri) { switch (mUriMatcher.match(uri)) { case PERSON_DIR: return vnd.android.cursor.dir/+AUTHORITY+.persons; case PERSON: return vnd.android.cursor.item/+AUTHORITY+.person; default: throw new IllegalArgumentException(unknown uri+uri.toString()); } } @Override public boolean onCreate() { mSQLiteDatabaseOpenHelper=new SQLiteDatabaseOpenHelper(getContext()); return true; } /** * 插入操作: * 插入操作只有一种可能:向一张表中插入 * 返回结果为新增记录对应的Uri * 方法db.insert()返回结果为新增记录对应的主键值 */ @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase(); switch (mUriMatcher.match(uri)) { case PERSON_DIR: long newId = db.insert(person, name,phone,salary, values); //向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应 getContext().getContentResolver().notifyChange(uri, null); return ContentUris.withAppendedId(uri, newId); default: throw new IllegalArgumentException(unknown uri + uri.toString()); } } /** * 更新操作: * 更新操作有两种可能:更新一张表或者更新某条数据 * 在更新某条数据时原理类似于查询某条数据,见下. */ @Override public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) { SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase(); int updatedNum = 0; switch (mUriMatcher.match(uri)) { // 更新表 case PERSON_DIR: updatedNum = db.update(person, values, selection, selectionArgs); break; // 按照id更新某条数据 case PERSON: long id = ContentUris.parseId(uri); String where = personid= + id; if (selection != null && !.equals(selection.trim())) { where = selection + and + where; } updatedNum = db.update(person, values, where, selectionArgs); break; default: throw new IllegalArgumentException(unknown uri + uri.toString()); } //向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应 getContext().getContentResolver().notifyChange(uri, null); return updatedNum; } /** * 删除操作: * 删除操作有两种可能:删除一张表或者删除某条数据 * 在删除某条数据时原理类似于查询某条数据,见下. */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase(); int deletedNum = 0; switch (mUriMatcher.match(uri)) { // 删除表 case PERSON_DIR: deletedNum = db.delete(person, selection, selectionArgs); break; // 按照id删除某条数据 case PERSON: long id = ContentUris.parseId(uri); String where = personid= + id; if (selection != null && !.equals(selection.trim())) { where = selection + and + where; } deletedNum = db.delete(person, where, selectionArgs); break; default: throw new IllegalArgumentException(unknown uri + uri.toString()); } //向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应 getContext().getContentResolver().notifyChange(uri, null); return deletedNum; } /** * 查询操作: * 查询操作有两种可能:查询一张表或者查询某条数据 * * 注意事项: * 在查询某条数据时要注意--因为此处是按照personid来查询 * 某条数据,但是同时可能还有其他限制.例如: * 要求personid为2且name为xiaoming1 * 所以在查询时分为两步: * 第一步: * 解析出personid放入where查询条件 * 第二步: * 判断是否有其他限制(如name),若有则将其组拼到where查询条件. * * 详细代码见下. */ @Override public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) { SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase(); Cursor cursor =null; switch (mUriMatcher.match(uri)) { // 查询表 case PERSON_DIR: cursor = db.query(person, projection, selection, selectionArgs,null, null, sortOrder); break; // 按照id查询某条数据 case PERSON: // 第一步: long id = ContentUris.parseId(uri); String where = personid= + id; // 第二步: if (selection != null && !.equals(selection.trim())) { where = selection + and + where; } cursor = db.query(person, projection, where, selectionArgs, null, null, sortOrder); break; default: throw new IllegalArgumentException(unknown uri + uri.toString()); } return cursor; } }
SQLiteDatabaseOpenHelper如下:
package cn.testcontentprovider;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;public class SQLiteDatabaseOpenHelper extends SQLiteOpenHelper { public SQLiteDatabaseOpenHelper(Context context) { super(context, contentprovidertest.db, null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(create table person(personid integer primary key autoincrement,name varchar(20),phone varchar(12),salary Integer(12))); } //当数据库版本号发生变化时调用该方法 @Override public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) { //db.execSQL(ALTER TABLE person ADD phone varchar(12) NULL); //db.execSQL(ALTER TABLE person ADD salary Integer NULL); } }
MainActivity如下:
package cn.testcontentprovider;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
AndroidManifest.xml如下:
<!--?xml version=1.0 encoding=utf-8?--><manifest android:versioncode="1" android:versionname="1.0" package="cn.testcontentprovider" xmlns:android="http://schemas.android.com/apk/res/android"> <uses-sdk android:minsdkversion="8" android:targetsdkversion="8"> <uses-permission android:name="android.permission.INTERNET"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"> <intent-filter> <category android:name="android.intent.category.LAUNCHER"> </category></action></intent-filter> </activity> <provider android:authorities="cn.bs.testcontentprovider" android:exported="true" android:name="cn.testcontentprovider.ContentProviderTest"> </provider></application> </uses-permission></uses-permission></uses-permission></uses-permission></uses-sdk></manifest>
main.xml如下:
<relativelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"><button android:layout_centerinparent="true" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="该应用包含一个自定义的ContentProvider" android:textsize="15sp"></button></relativelayout>
以下代码为工程TestBaidu
MainActivity如下:
package cn.testbaidu;import android.net.Uri;import android.os.Bundle;import android.os.Handler;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.app.Activity;import android.content.ContentResolver;import android.content.ContentValues;import android.database.ContentObserver;import android.database.Cursor;/** * Demo描述: * 应用A(TestBaidu)调用另外一个应用(TestContentProvider)中的自定义ContentProvider,即: * 1 自定义ContentProvider的使用 * 2 其它应用调用该ContentProvider * 3 ContentObserver的使用 * * 备注说明: * 1 该例子在以前版本的基础上整理了代码 * 2 该例子在以前版本的基础上融合了ContentObserver的使用 * 利用ContentObserver随时监听ContentProvider的数据变化. * 为实现该功能需要在自定义的ContentProvider的insert(),update(),delete() * 方法中调用getContext().getContentResolver().notifyChange(uri, null); * 向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应 * * 测试方法: * 1 依次测试ContentProvider的增查删改(注意该顺序)!! * 2 其它应用查询该ContentProvider的数据 * */public class MainActivity extends Activity { private Button mAddButton; private Button mDeleteButton; private Button mUpdateButton; private Button mQueryButton; private Button mTypeButton; private long lastTime=0; private ContentResolver mContentResolver; private ContentObserverSubClass mContentObserverSubClass; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); initContentObserver(); } private void init() { mContentResolver=this.getContentResolver(); mAddButton=(Button) findViewById(R.id.addButton); mAddButton.setOnClickListener(new ClickListenerImpl()); mDeleteButton=(Button) findViewById(R.id.deleteButton); mDeleteButton.setOnClickListener(new ClickListenerImpl()); mUpdateButton=(Button) findViewById(R.id.updateButton); mUpdateButton.setOnClickListener(new ClickListenerImpl()); mQueryButton=(Button) findViewById(R.id.queryButton); mQueryButton.setOnClickListener(new ClickListenerImpl()); mTypeButton=(Button) findViewById(R.id.typeButton); mTypeButton.setOnClickListener(new ClickListenerImpl()); } // 注册一个针对ContentProvider的ContentObserver用来观察内容提供者的数据变化 private void initContentObserver() { Uri uri = Uri.parse(content://cn.bs.testcontentprovider/person); mContentObserverSubClass=new ContentObserverSubClass(new Handler()); this.getContentResolver().registerContentObserver(uri, true,mContentObserverSubClass); } @Override protected void onDestroy() { super.onDestroy(); if (mContentObserverSubClass!=null) { this.getContentResolver().unregisterContentObserver(mContentObserverSubClass); } } // 自定义一个内容观察者ContentObserver private class ContentObserverSubClass extends ContentObserver { public ContentObserverSubClass(Handler handler) { super(handler); } //采用时间戳避免多次调用onChange( ) @Override public void onChange(boolean selfChange) { super.onChange(selfChange); System.out.println(ContentObserver onChange() selfChange=+ selfChange); if (System.currentTimeMillis()-lastTime>2000) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse(content://cn.bs.testcontentprovider/person); // 获取最新的一条数据 Cursor cursor = resolver.query(uri, null, null, null,personid desc limit 1); while (cursor.moveToNext()) { int personid = cursor.getInt(cursor.getColumnIndex(personid)); System.out.println(内容提供者中的数据发生变化,现数据中第一条数据的personid=+ personid); } cursor.close(); lastTime=System.currentTimeMillis(); }else{ System.out.println(时间间隔过短,忽略此次更新); } } @Override public boolean deliverSelfNotifications() { return true; } } private class ClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.addButton: Person person = null; for (int i = 0; i < 5; i++) { person = new Person(xiaoming + i, 9527 + i, (8888 + i)); testInsert(person); } break; case R.id.deleteButton: testDelete(1); break; case R.id.updateButton: testUpdate(3); break; case R.id.queryButton: // 查询表 // queryFromContentProvider(-1); // 查询personid=2的数据 testQuery(2); break; case R.id.typeButton: testType(); break; default: break; } } } private void testInsert(Person person) { ContentValues contentValues=new ContentValues(); contentValues.put(name, person.getName()); contentValues.put(phone, person.getPhone()); contentValues.put(salary,person.getSalary()); Uri insertUri=Uri.parse(content://cn.bs.testcontentprovider/person); Uri returnUri=mContentResolver.insert(insertUri, contentValues); System.out.println(新增数据:returnUri=+returnUri); } private void testDelete(int index){ Uri uri=Uri.parse(content://cn.bs.testcontentprovider/person/+String.valueOf(index)); mContentResolver.delete(uri, null, null); } private void testUpdate(int index){ Uri uri=Uri.parse(content://cn.bs.testcontentprovider/person/+String.valueOf(index)); ContentValues values=new ContentValues(); values.put(name, hanmeimei); values.put(phone, 1234); values.put(salary, 333); mContentResolver.update(uri, values, null, null); } private void testQuery(int index) { Uri uri=null; if (index<=0) { //查询表 uri=Uri.parse(content://cn.bs.testcontentprovider/person); } else { //按照id查询某条数据 uri=Uri.parse(content://cn.bs.testcontentprovider/person/+String.valueOf(index)); } //对应上面的:查询表 //Cursor cursor= mContentResolver.query(uri, null, null, null, null); //对应上面的:查询personid=2的数据 //注意:因为name是varchar字段的,所以应该写作name='xiaoming1' // 若写成name=xiaoming1查询时会报错 Cursor cursor= mContentResolver.query(uri, null, name='xiaoming1', null, null); while(cursor.moveToNext()){ int personid=cursor.getInt(cursor.getColumnIndex(personid)); String name=cursor.getString(cursor.getColumnIndex(name)); String phone=cursor.getString(cursor.getColumnIndex(phone)); int salary=cursor.getInt(cursor.getColumnIndex(salary)); System.out.println(查询得到:personid= + personid+,name=+name+,phone=+phone+,salary=+salary); } cursor.close(); } private void testType(){ Uri dirUri=Uri.parse(content://cn.bs.testcontentprovider/person); String dirType=mContentResolver.getType(dirUri); System.out.println(dirType:+dirType); Uri itemUri=Uri.parse(content://cn.bs.testcontentprovider/person/3); String itemType=mContentResolver.getType(itemUri); System.out.println(itemType:+itemType); } }
Person如下:
package cn.testbaidu; public class Person { private Integer id; private String name; private String phone; private Integer salary; public Person(String name, String phone,Integer salary) { this.name = name; this.phone = phone; this.salary=salary; } public Person(Integer id, String name, String phone,Integer salary) { this.id = id; this.name = name; this.phone = phone; this.salary=salary; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public Integer getSalary() { return salary; } public void setSalary(Integer salary) { this.salary = salary; } @Override public String toString() { return Person [id= + id + , name= + name + , phone= + phone+ , salary= + salary + ]; } }
0 0
- 自定义ContentProvider以及ContentObserver的使用完整详细示例
- 自定义ContentProvider以及ContentObserver的使用完整详细示例
- Android 自定义ContentProvider和ContentObserver的完整使用
- Android ContentProvider、ContentResolver和ContentObserver的使用
- android之contentProvider的使用以及为其添加观察者(ContentObserver)
- 使用ContentObserver监听ContentProvider中数据的变化
- 内容提供者ContentProvider和内容观察者ContentObserver的使用
- 自定义ContentProvider的使用
- 自定义数据库中使用 contentObserver
- ContentObserver的使用
- ContentObserver的基本使用
- CountDownTimer完整详细示例
- 自定义ContentProvider及使用ContentResolver解析详细步骤
- 4.3使用ContentObserver监听ContentProvider中的数据变化
- ContentProvider、ContentValues、ContentResolver、ContentObserver
- ContentProvider & ContentResolver & ContentObserver
- ContentProvider ,ContentObserver 和ContentResolver
- ContentProvider(内容提供者)以及自定义ContentProvider
- USB to RS232 PL2303驱动在Win7 64位旗舰版无法安装问题解决
- saml
- golang中tcp socket粘包问题和处理
- Cordova指令
- the catalina_home environment variable is not defined correctly
- 自定义ContentProvider以及ContentObserver的使用完整详细示例
- 只有高中学历的我是怎样加入谷歌的?
- WWDC2014之App Extensions学习笔记
- [LeetCode]64. Minimum Path Sum
- SVN服务器搭建和使用和Visual Studio插件AnkhSvn的使用(网上整理的)
- iOS动画
- qt 嵌入式下 运行 client 问题
- L2TP VPN应用场景
- Android 短信监听