当应用程序的数据需要被别的应用程序使用时,就必须将应用程序的数据抛出,通常要继承contentprovider类,并且覆写它的方法。下面通过将数据库的数据抛出例子学习一下:
1首先我们必须在应用程序的清单文件里配置provider:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <uses-library android:name="android.test.runner" /> <activity android:name="com.example.database.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="com.mydatabase.provider.Personprovider" android:authorities="com.mydatabase.personprovider" > </provider> </application>
其中name属性是provider的包名下具体类名,authorities是主机名,是标识这个应用程序的provider的,通常以功能命名(没有具体规范),在uri的匹配时会用到(后面会讲到)。
2实现一个继承contentprovider的类,为了抛出数据和操作数据的方法,android提供了Urimather来实现uri的匹配。contentprovider抛出的数据在别的应用程序里利用contentresolver绑定这唯一的uri来对数据操作的:
public class Personprovider extends ContentProvider { public static final UriMatcher matcher =new UriMatcher(UriMatcher.NO_MATCH); Mydatebase dbhelper; public static final Uri baseuri=Uri.parse("com.mydatabase.personprovider");//被监听的uri public static final int ALL_PERSON=1; static { matcher.addURI("com.mydatabase.personprovider", "query", ALL_PERSON);//红色部分是主机名,后面的是路径,在后面query/#or*,#表示数字,*表示任意字符 } @Override public boolean onCreate() { // TODO Auto-generated method stub dbhelper=new Mydatebase(getContext()); // SQLiteDatabase db=dbhelper.getReadableDatabase(); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub int result=matcher.match(uri); Cursor cur=null; if(result==ALL_PERSON)//匹配成功时返回的是ALL_PERSON的值 { SQLiteDatabase db=dbhelper.getWritableDatabase(); cur=db.query("person", projection, selection, selectionArgs, null, null, null); return cur; } else { throw new IllegalArgumentException("无法找到匹配对象!"); } }
public Uri insert(Uri uri, ContentValues values) {
int result =matcher.match(uri);
if(result==ADD)
{
SQLiteDatabase db=dbhelper.getWritableDatabase();
db.insert("person", null, values);
getContext().getContentResolver().notifyChange(baseuri, null);//发生插入时候告诉baseuri,第二个参数是监听器,为空则只有在外面设置监听器通过uri获取信息,不为空则向指定的观察者发出通知
}
return null;
}
public String getType(Uri uri) {
// TODO Auto-generated method stub
int result=matcher.match(uri);
if(result==ALL_PERSON)
return "vnd.android.cursor.dir/Person";//一条数据,如果是多条数据vnd.android.cursor.item/person
return null;
}
3、在别的应用里只需要获取contentresolver,然后带入相应的uri来对数据进行操作:(下面代码是通过一个button按钮获取数据库内person表的数据)
public void click(View View) { Uri uri=Uri.parse("content://com.mydatabase.personprovider/query"); ContentResolver rs=getContentResolver(); // rs.query(uri, null, selection, selectionArgs, sortOrder) Cursor cur=rs.query(uri, null, null, null, null); while(cur.moveToNext()) { System.out.println(cur.getString(0)); } }
4、我们可以为数据库设定内容监听者,或者说监听器,在实现provider时当数据库内数据发生改变时就调用getContext().getContentResolver().notifyChange(uri, observer);他会将改变信息告诉相对应的uri,然后再别的程序里设定监听器只要监听该uri就可以知道数据库发生了改变。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Uri uri=Uri.parse("com.mydatabase.personprovider"); getContentResolver().registerContentObserver(uri, true, new obs(new Handler()));//第二个参数为true时候表示只要是baseuri这个目录发生改变都会监听到//,false时必须uri必须是baseuri后的具体改变的uri,第三个是监听器,需要实现下面是简单的实现方式 } public class obs extends ContentObserver { public obs(Handler handler) { super(handler); // TODO Auto-generated constructor stub } public void onChange(boolean selfChange) { // Do nothing. Subclass should override. System.out.println("数据发生改变了!");//数据发生改变后的操作 } }