采用ContentProvider除了可以让其他应用访问当前的app的数据之外,还有可以实现当app的数据发送变化的时候,通知注册了数据变化通知的调用者
其他所有的代码都和第20讲的一样,不同的地方看下面的代码:
package test.weiyuan.sqllite1; 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.util.Log; import dB.DbOpenHelper; /** * Created by wei.yuan on 2015/6/3. * 一定要在清单文件中对内容提供者进行注册 */ public class PersonProvider extends ContentProvider { private DbOpenHelper dbOpenHelper; //该类用于检测的外部应用输入的URL是否正确,如果正确返回码就是codePerson,不正确返回UriMatcher.NO_MATCH private static final int codePerson = 1; private static final int codePerson1 = 2; //该类用于检测的外部应用输入的URL是否正确,如果不正确返回码就是new UriMatcher(UriMatcher.NO_MATCH)构造函数中的参数,这里是UriMatcher.NO_MATCH private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { //这个url表示对整个person表进行操作 uriMatcher.addURI("test.weiyuan.sqllite1.PersonProvider","person",codePerson); //这个url表示对person表中的某个记录进行操作,#表示的是数字,就是对应的person表中的某个记录 uriMatcher.addURI("test.weiyuan.sqllite1.PersonProvider","person/#",codePerson1); } //onCreate()之后被调用一次,在调用的时候创建数据库,记得返回值为true @Override public boolean onCreate() { dbOpenHelper = new DbOpenHelper(getContext()); return true; } //查询数据表的数据 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); switch (uriMatcher.match(uri)) { //更新整个表 case codePerson: return database.query("person",projection,selection,selectionArgs,null,null,sortOrder); //更新表中的某条记录 case codePerson1: long row_id = ContentUris.parseId(uri); String where = " personid="+row_id; Log.i("weiyuan",""+row_id); if (selection!=null&&!"".equals(selection.trim())) { where += "and "+selection; } return database.query("person",null,where,selectionArgs,null,null,sortOrder); default: //如果传人的url不正确,抛出一个异常提示用户 throw new IllegalArgumentException("this is a unkown url-->"+uri); } } //返回要操作数据的内容类型,如txt文本就是plain/text类型 @Override public String getType(Uri uri) { return null; } //可以让外面的应用向内容提供者插入数据 @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); switch (uriMatcher.match(uri)) { case codePerson: //这里如果values为空,就必须需要第二个参数有值这里为"name",如果values有值,第二个参数默认为空值 long rowid = database.insert("person",null,values); // Uri insertUri = Uri.parse("context://test.weiyuan.providers.PersonProvider/person/"+rowid);可以使用下面的方法http://blog.csdn.net/feng88724/article/details/6331396 Uri insertUri = ContentUris.withAppendedId(uri,rowid); //当数据添加之后,发送通知提供给其他内容提供者 getContext().getContentResolver().notifyChange(uri,null);//发出数据变化的通知 if(database!=null) { database.close(); } return insertUri; default: //如果传人的url不正确,抛出一个异常提示用户 if(database!=null) { database.close(); } throw new IllegalArgumentException("this is a unkown url-->"+uri); } } //返回值int表示你删除了多少条记录 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); switch (uriMatcher.match(uri)) { //删除整个表 case codePerson: database.delete("preson",selection,selectionArgs); if(database!=null) { database.close(); } break; //删除表中的某条记录 case codePerson1: long row_id = ContentUris.parseId(uri); String where = " personid="+ row_id; Log.i("weiyuan",""+row_id); if (selection!=null&&!"".equals(selection.trim())) { where += "and "+selection; } database.delete("person",where,selectionArgs); if(database!=null) { database.close(); } break; default: //如果传人的url不正确,抛出一个异常提示用户 throw new IllegalArgumentException("this is a unkown url-->"+uri); } return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); switch (uriMatcher.match(uri)) { //更新整个表 case codePerson: database.update("preson",values,selection,selectionArgs); if(database!=null) { database.close(); } break; //更新表中的某条记录 case codePerson1: long row_id = ContentUris.parseId(uri); String where = " personid="+row_id; Log.i("weiyuan",""+row_id); if (selection!=null&&!"".equals(selection.trim())) { where += "and "+selection; } database.update("person",values,where,selectionArgs); if(database!=null) { database.close(); } break; default: if(database!=null) { database.close(); } //如果传人的url不正确,抛出一个异常提示用户 throw new IllegalArgumentException("this is a unkown url-->"+uri); } return 0; } }
当有其他应用通过provider想数据库插入数据的时候就会发出 getContext().getContentResolver().notifyChange(uri,null);这个数据变化的广播
其他第三方应该如果注册了这个广播就会收到这个数据库变化的广播
我们来看下面的代码,第三方监听者的代码:
package com.example.weiyuan.myapplication; import android.app.ActivityManager; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Handler; import android.provider.Contacts; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ImageView; import android.widget.TextView; import java.util.List; public class MainActivity extends ActionBarActivity { private ImageView imageView; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView)findViewById(R.id.show); //注册内容提供者变化的监听器 Uri uri = Uri.parse("content://test.weiyuan.sqllite1.PersonProvider/person"); /* //第二个参数很关键true表示只要是以"content://test.weiyuan.sqllite1.PersonProvider/person"开头的url都可以监听 比如"content://test.weiyuan.sqllite1.PersonProvider/person/123",是以"content://test.weiyuan.sqllite1.PersonProvider/person"开头的,也可以监听 但是是false的话,如果要监听"content://test.weiyuan.sqllite1.PersonProvider/person/123"就必须写出 "content://test.weiyuan.sqllite1.PersonProvider/person/123"*/ getContentResolver().registerContentObserver(uri,true,new Observer(new Handler())); } //得到数据变化的通知 public class Observer extends ContentObserver { /** * Creates a content observer. * * @param handler The handler to run {@link #onChange} on, or null if none. */ public Observer(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { //获得最新的插入数据的内容 Uri uri = Uri.parse("content://test.weiyuan.sqllite1.PersonProvider/person"); ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(uri, null, null, null, "personid desc "); if(cursor.moveToFirst()) { textView.setText(cursor.getString(cursor.getColumnIndex("name"))+"...."+cursor.getString(cursor.getColumnIndex("phone"))); } super.onChange(selfChange); } @Override public boolean deliverSelfNotifications() { return super.deliverSelfNotifications(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
上面的代码或者最新插入到数据库中的最新的一条数据。对应系统的通讯录我们也可以监听系统通讯录发送变化的广播,获得最新的通讯录数据。