创建一个新的Content Provider
通过扩展ContentProvider类来创建一个新的Content Provider。重写onCreate方法来打开或初始化你要通过这个Provider提供的底层数据源。新的Content Provider的框架代码如下所示:
import android.content.*;
import android.database.Cursor;
import android.net.Uri;
import android.database.SQLException;
public class MyProvider extends ContentProvider
{
@Override
public boolean onCreate()
{
// TODO: Construct the underlying database.
return true;
}
}
你还应该暴露一个公共的静态变量CONTENT_URI,来返回这个Provider的URI。
Content URI在Provider间必须是独一无二的,所以,一个好的习惯是:URI路径值使用包名。定义一个Content Provider URI的通用格式是:
content://com.<CompanyName>.provider.<ApplicationName>/<DataPath>
例如:
content://com.paad.provider.myapp/items
Content URI可以表示为两种形式。上面的URI表示请求某类型的全部值(例如,所有项目)。
在其后追加/<rownumber>,如下所示,表示请求单一记录(例如,第5个项目)。
content://com.paad.provider.myapp/items/5
支持这两种方式来访问你的Provider是个很好的形式。
做到这样最简单的方式是使用一个UriMatcher。当通过ContentResolver来访问一个Provider时,配置UriMatcher解析URI来决定它们的形式。下面的代码显示了这一样式的框架代码:
public class MyProvider extends ContentProvider
{
private static final String myURI =“content://com.paad.provider.myapp/items”;
public static final Uri CONTENT_URI = Uri.parse(myURI);
@Override
public boolean onCreate()
{
// TODO: Construct the underlying database.
return true;
}
// Create the constants used to differentiate between the different
// URI requests.
private static final int ALLROWS = 1;
private static final int SINGLE_ROW = 2;
private static final UriMatcher uriMatcher;
// Populate the UriMatcher object, where a URI ending in ‘items’ will
// correspond to a request for all items, and ‘items/[rowID]’
// represents a single row.
static
{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(“com.paad.provider.myApp”, “items”, ALLROWS);
uriMatcher.addURI(“com.paad.provider.myApp”, “items/#”,SINGLE_ROW);
}
}
你可以使用相同的技巧来暴露数据中不同子集的URI或数据库中不同的表的URI。
一个好的习惯是:在Provider中保留列的名称和索引,来简化通过Cursor提取信息。
暴露数据源的访问
你可以实现delete、insert、update和query方法来暴露与你的Content Provider的查询和交互功能。
这些方法作为底层数据源的通用接口,允许Android应用程序跨越程序边界来共享数据,而不需要为每个程序公布不同的接口。
最常见的场景是使用一个Content Provider来访问一个私有的 SQLite数据库,但使用这些方法,你可以访问任何数据源(包括文件或应用程序实例的变量)。
接下来的框架代码显示了一个Content Provider的查询和交互功能。注意:UriMatcher对象用于精炼交互和查询请求。
@Override
public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sort)
{
// If this is a row query, limit the result set to the passed in row.
switch (uriMatcher.match(uri))
{
case SINGLE_ROW :
// TODO: Modify selection based on row id, where:
// rowNumber = uri.getPathSegments().get(1));
}
return null;
}
@Override
public Uri insert(Uri _uri, ContentValues _initialValues) {
long rowID = [ ... Add a new item ... ]
// Return a URI to the newly added item.
if (rowID > 0)
{
return ContentUris.withAppendedId(CONTENT_URI, rowID);
}
throw new SQLException(“Failed to add new item into “ + _uri);
}
@Override
public int delete(Uri uri, String where, String[] whereArgs)
{
switch (uriMatcher.match(uri))
{
case ALLROWS:
case SINGLE_ROW:
default: throw new IllegalArgumentException(“Unsupported URI:” + uri);
}
}
@Override
public int update(Uri uri, ContentValues values, String where,String[] whereArgs)
{
switch (uriMatcher.match(uri))
{
case ALLROWS:
case SINGLE_ROW:
default: throw new IllegalArgumentException(“Unsupported URI:” + uri);
}
}
创建Content Provider最后一步是定义标识Provider返回数据的MIME类型。
重写getType方法,返回一个独一无二的字符串来描述你的数据类型。返回的类型必须包含两种形式,一种是单一项目,另一种是所有的项目,如下所示:
❑ 单一项目
vnd.<companyname>.cursor.item/<contenttype>
❑ 所有的项目
vnd.<companyName>.cursor.dir/<contenttype>
接下来的代码片段显示了如何重写getType方法来一句传入的URI来返回正确的MIME类型:
@Override
public String getType(Uri _uri)
{
switch (uriMatcher.match(_uri))
{
case ALLROWS: return “vnd.paad.cursor.dir/myprovidercontent”;
case SINGLE_ROW: return “vnd.paad.cursor.item/myprovidercontent”;
default: throw new IllegalArgumentException(“Unsupported URI: “ + _uri);
}
}
注册Provider
一旦完成了Content Provider,你必须将其添加到应用程序的manifest中。使用authorities标签来指定它的路径,如下面的XML片段所示:
<provider android:name=”MyProvider” android:authorities=”com.paad.provider.myapp”/>