一、ContentProvider 的基本概念
1、ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider接口,
同时android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)。
2、Uri 类简介
Uri uri = Uri.parse("content://com.derong.provider.contactprovider/contact")
Contentprovider 中使用的查询字符串有别于标准的SQL查询。很多如Select, add, delete 等操作我们使用一种特殊的URI ,这种URI是由3个部分组成,
“content://” 代表数据路径,和一个可选的标识数据的ID。(如:content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录))
同时Android也提供了一些帮助类,可以使我们比较有一个直观的认识。以上这种方式也可写成Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 45);然后在执行数据查询
Cursor cur = managedQuery(preson,null,null,null)
二、我们来研究如何创建Contentprovide ,以及执行增加,删除等
首先要创建自己的Contentprovider ,我们要做一下几步
2.1创建一个继承了ContentProvider父类的类
2.2 定义一个名字为CONTENT_URI 常量,你必须为其指定一个唯一的字符串值,最好的方案是以类的全名称,比如
public static final Uri CONTENT_URI = Uri.parse( “content://com.google.android.MyContentProvider”);
2.3 定义要返回给客户端的数据列表,如果使用的是sqlite 数据库,还必须为其定义一个叫_id的字段,保证每条数据的唯一性
2.4 通过使用sqlite 或者其他方式定义数据存储系统。如果要存储字节型数据,处理这种数据类型的Content Provider需要实现一个名为_data的字段
2.5 声明游标返回的数据列类型变量
2.6 这不也是重点, 查询返回一个Cursor类型的对象 。所有执行写操作的方法如insert(), update() 以及delete()都将被监听。
而且我们需要事实更新数据,所以这里我们可以通过使用ContentResover().notifyChange()方法来通知监听器关于数据更新的信息
2.7 在AndroidMenifest.xml中使用 <provider>标签来设置Content provider 否则将前功尽弃
2.8 这步为拓展,因为在数据处理中很可能使用的不是基本类型,因此在使用一些新的类型时,我们就要定义一个新的MIME类型,供ContentProvider.getType(url)来返
回。
MIME 类型有两种形式:
a.指定的单个记录的
vnd.android.cursor.item/vnd.yourcompanyname.contenttype (单个记录的MIME类型)
比如, 一个请求列车信息的URI如content://com.example.transportationprovider/trains/122 可能就会返回typevnd.android.cursor.item/vnd.example.rail这样一个MIME类型。
b.多条记录的
vnd.android.cursor.dir/vnd.yourcompanyname.contenttype (多个记录的MIME类型)
比如, 一个请求所有列车信息的URI如content://com.example.transportationprovider/trains 可能就会返回vnd.android.cursor.dir/vnd.example.rail这样一个MIME 类型
下面看下具体代码实现,定义一个Content provider 需要的Content_uri ,以及数据列
<pre name="code" class="html">public class Users {
public static final String AUTHORITY = “com.derong.MyContentProvider”;
// BaseColums类中已经包含了 _id字段
public static final class User implements BaseColumns {
public static final Uri CONTENT_URI = Uri.parse(”content://com.derong.MyContentProvider”);
// 表数据列
public static final String USER_NAME = “USER_NAME”;
}
}
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">下面我们具体实现Content provider 类,</span><span style="color: rgb(75, 75, 75); font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19.5px; background-color: rgb(255, 255, 255);">它用于从Sqlite数据库中添加和读取记录</span>
<pre name="code" class="html"><span style="background-color: rgb(255, 255, 255);">public class MyContentProvider extends ContentProvider {
private SQLiteDatabase sdb;
private DatabaseHelper dbHelper;
private static final String DATABASE_NAME = “DataUser.db”;
private static final int DATABASE_VERSION= 1;
private static final String TABLE_NAME= “User”;
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//创建用于存储数据的表
db.execSQL(”Create table ” + TABLE_NAME + “( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);”);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(”DROP TABLE IF EXISTS ” + TABLE_NAME);
onCreate(db);
}
}
@Override
public int delete(Uri uri, String s, String[] as) {
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues contentvalues) {
sdb = dbHelper.getWritableDatabase();
long rowId = sqlDB.insert(TABLE_NAME, “”, contentvalues);
if (rowId > 0) {
Uri rowUri = ContentUris.appendId(Users.User.CONTENT_URI.buildUpon(), rowId).build();
getContext().getContentResolver().notifyChange(rowUri, null);
return rowUri;
}
throw new SQLException(”Failed to insert row into ” + uri);
}
@Override
public boolean onCreate() {
dbHelper = new DatabaseHelper(getContext());
return (dbHelper == null) ? false : true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
SQLiteDatabase db = dbHelper.getReadableDatabase();
qb.setTables(TABLE_NAME);
Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
return 0;
}
}</span>
Content Provider 的入口需要在AndroidManifext.xml中配置
<provider android:name=”MyContentProvider” android:authorities=”com.derong.MyContentProvider” />
三、到此为止我们就可以使用我们定义的Content Provider
a. 为应用增加ContentProver 访问权限
b. 通过getContentResolver() 得到ContentResolver对象
c. 对返回的Cursor 对象进行分析,得到需要的数据
d. 关闭Cursor
public class MyDemo extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
insertRecord(”zhangsan”);
displayRecords();
}
private void insertRecord(String userName) {
ContentValues values = new ContentValues();
values.put(Users.User.USER_NAME, userName);
getContentResolver().insert(Users.User.CONTENT_URI, values);
}
private void displayRecords() {
String columns[] = new String[] { Users.User._ID, Users.User.USER_NAME };
Uri myUri = Users.User.CONTENT_URI;
Cursor cur = managedQuery(myUri, columns,null, null, null );
if (cur.moveToFirst()) {
String id = null;
String userName = null;
do {
id = cur.getString(cur.getColumnIndex(MyUsers.User._ID));
userName = cur.getString(cur.getColumnIndex(Users.User.USER_NAME));
Toast.makeText(this, id + ” ” + userName, Toast.LENGTH_LONG).show();
} while (cur.moveToNext());
}
}
}