内容提供者是安卓四大组件之一。
如果a应用想把自己的数据库暴露给别的应用程序使用,就必须实现contentprovider 。
创建一个类 继承系统的ContentProvider一定要在清单文件里面配置 放入application结点下。(作为一个组件)指定uri的主机名com.example.provider.personprovider。
<provider android:name="com.example.provider.PersonProvider"
android:authorities="com.example.provider.personprovider"
>
<!-- 通过一个地址来暴露内容 -->
</provider>
下面给出PersonProvider代码。
第一步,定义macher工具 public static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
第二步,定义一些常量
public static final int ALL_PERSONS = 1;
public static final int PERSON = 2;
public static final int HAHA = 3;
public static final int INSERT = 4;
public static final int DELETE = 5;
public static final int UPDATE = 6;
第三步,定义此程序将要暴露的路径,在静态代码块中定义。
static {
/**
* com.example.provider.personprovider 清单文件中的主机名
* */
matcher.addURI("com.example.provider.personprovider", "persons",
ALL_PERSONS);
// 指定一个路径的匹配规则
// 如果路径 满足 content://com.example.provider.personprovider/persons 返回值就是(
// ALL_PERSONS) 1
matcher.addURI("com.example.provider.personprovider", "person/#",
PERSON);
// 如果路径 满足 content://com.example.provider.personprovider/person/10
// 返回值就是( PERSON) 2
matcher.addURI("com.example.provider.personprovider", "haha", HAHA);
matcher.addURI("com.example.provider.personprovider", "insert", INSERT);
matcher.addURI("com.example.provider.personprovider", "delete", DELETE);
matcher.addURI("com.example.provider.personprovider", "update", UPDATE);
}
第四步,实现重写的方法。
package com.example.provider;
import com.example.db1.DBHelper;
import com.example.db1.PersonDAO;
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;
public class PersonProvider extends ContentProvider {
public static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
public static final int ALL_PERSONS = 1;
public static final int PERSON = 2;
public static final int HAHA = 3;
public static final int INSERT = 4;
public static final int DELETE = 5;
public static final int UPDATE = 6;
private DBHelper helper;
Uri baseuri = Uri.parse("content://cn.itcast.db.personprovider");
static {
/**
* com.example.provider.personprovider 清单文件中的主机名
* */
matcher.addURI("com.example.provider.personprovider", "persons",
ALL_PERSONS);
// 指定一个路径的匹配规则
// 如果路径 满足 content://com.example.provider.personprovider/persons 返回值就是(
// ALL_PERSONS) 1
matcher.addURI("com.example.provider.personprovider", "person/#",
PERSON);
// 如果路径 满足 content://com.example.provider.personprovider/person/10
// 返回值就是( PERSON) 2
matcher.addURI("com.example.provider.personprovider", "haha", HAHA);
matcher.addURI("com.example.provider.personprovider", "insert", INSERT);
matcher.addURI("com.example.provider.personprovider", "delete", DELETE);
matcher.addURI("com.example.provider.personprovider", "update", UPDATE);
}
/**
* PeronProvder 内容提供者第一次被创建的时候 调用的方法 这里给一个得到和数据库的变量
*/
@Override
public boolean onCreate() {
helper = new DBHelper(getContext());
return false;
}
/**
* 有的时候 我们需要知道内容提供者返回的数据类型 知道返回的数据 是一个集合呀 还是一个单独的条目
*
* 有的时候 告诉调用者 返回的数据是什么样的类型 mime的数据类型
*/
@Override
public String getType(Uri uri) {
int result = matcher.match(uri);
switch (result) {
// 符合 content://com.example.provider.personprovider/persons 代表的返回所有的数据
case ALL_PERSONS:
return "vnd.android.cursor.dir/people";
// content://com.example.provider.personprovider/person/10
case PERSON:
return "vnd.android.cursor.item/people";
default:
return null;
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int result = matcher.match(uri);
switch (result) {
case DELETE:
SQLiteDatabase db = helper.getWritableDatabase();
getContext().getContentResolver().notifyChange(baseuri, null);
return db.delete("person", selection, selectionArgs);
default:
throw new IllegalArgumentException("uri 不能被识别 ");
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// content://com.example.provider.personprovider/insert
int result = matcher.match(uri);
switch (result) {
case INSERT:
SQLiteDatabase db = helper.getWritableDatabase();
db.insert("person", "personid", values);
// 当数据发生改变的时候
getContext().getContentResolver().notifyChange(baseuri, null);
return uri;
default:
throw new IllegalArgumentException("uri 不能被识别 ");
}
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int result = matcher.match(uri);
switch (result) {
// 符合content://com.example.provider.personprovider/persons 代表返回所有数据
case ALL_PERSONS:
PersonDAO dao = new PersonDAO(getContext());
return dao.findAllbyCursor();
case PERSON:
long id = ContentUris.parseId(uri);
helper = new DBHelper(getContext());
SQLiteDatabase sb = helper.getReadableDatabase();
if (sb.isOpen()) {
Cursor cursor = sb.query("person", null, "personid=?",
new String[] { id + "" }, null, null, null);
return cursor;
}
case HAHA:
android.util.Log.i("TAG", "我是haha对应的路径");
break;
default:
throw new IllegalArgumentException("uri不能被识别");
}
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int result = matcher.match(uri);
switch (result) {
case UPDATE:
SQLiteDatabase db = helper.getWritableDatabase();
getContext().getContentResolver().notifyChange(baseuri, null);
return db.update("person", values, selection, selectionArgs);
default:
throw new IllegalArgumentException("uri 不能被识别 ");
}
}
}
</pre><p></p><pre>
这样,此程序就暴露了自己的数据。别的程序就可以访问它提供的方法来操作它的数据了。
比如在另一个项目中,可以这样写
必须先得到ContentReolver。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ContentResolver resolver=getContentResolver();
Uri uri=Uri.parse("content://com.example.provider.personprovider/haha");//定义uri
Cursor cursor=resolver.query(uri, null, null, null, null);//null为查询条件 可以不关心
while(cursor!=null&&cursor.moveToNext()){
String name=cursor.getString(cursor.getColumnIndex("name"));
System.out.println("姓名"+name);
}
}
}
在程序中添加这行代码getContext().getContentResolver().notifyChange(baseuri, null);
当数据发生变化时会通知baseuri数据的变化。
在另一个应用中,可以监听到其他程序的数据变化。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Uri uri=Uri.parse("content://com.example.provider.personprovider/");//定义uri
//content://com.example.provider.personprovider
//注册了内容观察者
getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()));
}
/**
* 当内容观察者发现了数据发生改变的时候调用的方法
* */
public class MyObserver extends ContentObserver{
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
System.out.println("数据发生了改变");
}
}
}