当前位置: 代码迷 >> Android >> Android API Guides-Creating a Content Provider
  详细解决方案

Android API Guides-Creating a Content Provider

热度:243   发布时间:2016-04-24 11:08:30.0
Android API Guides---Creating a Content Provider
创建一个内容提供者
在该文献
设计数据存储
设计内容的URI
实施ContentProvider类
所需的方法
实施query()方法
实施insert()方法
实施delete()方法
实施update()方法
实施onCreate()方法
实施内容提供商MIME类型
MIME类型的表
MIME类型的文件
实施合同类
实施内容提供商权限
在<provider>元素
意图和数据访问
重点班
的ContentProvider
光标
乌里
相关样本
记事本示例应用程序
也可以看看
内容提供商基础
日历提供商
内容提供者管理存取数据的中央存储库。您可以实现供应商为一个或多个类别的Andr??oid应用程序,并在清单文件中的元素一起。你的一个类实现一个ContentProvider的子类,这是你的供应商和其他应用程序之间的接口。尽管内容提供商,目的是使数据提供给其他应用程序,你当然可以在你的应用程序的活动,允许用户查询和修改由服务提供商管理的数据。


本主题的其余部分是用于构建一个内容提供商和API使用列表步骤的基本清单。


开始创建之前


你开始建立一个供应商之前,请执行以下操作:


如果你需要一个内容提供商决定。你需要,如果你想提供以下一项或多项特征构建一个内容提供商:
要复杂的数据或文件提供给其它应用程序。
要允许用户在复杂的数据,从您的应用程序复制到其他应用程序。
你要提供使用搜索架构自定义搜索建议。
你并不需要一个供应商,如果使用完全是你自己的应用程序中使用SQLite数据库。
如果你还没有这样做的话,阅读主题内容提供商基础知识,以了解更多关于供应商。
接下来,请按照下列步骤来建立你的供应商:


设计为您的数据的原始存储。内容提供者通过两种方式提供数据:
文件数据
数据通常进入文件,如照片,音频或视频。存储在应用程序的私人空间中的文件。在响应于来自其他应用程序的文件的请求时,你的提供者可以提供的句柄文件。
“结构化”数据
数据通常进入一个数据库,数组或类似的结构。在形式与行和列的表格兼容的存储数据。中的一行表示一个实体,如一个人或在清单中的项目。列表示实体的一些数据,比如一个人的姓名或项目的价格。一种常见的方式来存储这类数据是在SQLite数据库,但你可以使用任何类型的持久性存储。要了解更多关于存储类型可供选择Android系统,请参见设计数据存储。
定义一个具体实现ContentProvider类及其所需的方法。这个类是你的数据和Android系统的其余部分之间的接口。有关此类的更多信息,请参见实现ContentProvider类。
定义供应商的授权字符串,其内容的URI和列名。如果您希望供应商的应用程序来处理意向,还定义意图的行动,额外的数据和标志。还定义您将需要要访问您的数据应用程序的权限。你应该考虑定义所有这些值作为一个单独的合同类常量;以后,你可以将这个类给其他开发商。有关内容的URI的更多信息,请参见设计内容的URI。关于意图的更多信息,请参见意图和数据访问。
添加其它可选件,如样本数据或AbstractThreadedSyncAdapter的实现,可以同步提供者和基于云的数据之间的数据。
设计数据存储


内容提供商是界面保存在一个结构化的格式的数据。在创建界面之前,你必须决定如何存储数据。可以存储在你喜欢的任何形式的数据,然后设计读取和将数据作为必要写的接口。


这些是一些Android中可用的数据存储技术的:


Android系统,包括Android的自身提供商使用存储面向表的数据的SQLite数据库API。该SQLiteOpenHelper类帮助您创建数据库以及SQLiteDatabase类是访问数据库的基类。
请记住,你不必使用数据库来实现你的资料库。一个提供外部显示为一组表,类似于一个关系数据库,但是这不是对提供者的内部实现的要求。
为了存储文件数据,Android有多种面向文件的的API。要了解更多有关文件存储,阅读主题数据存储。如果你正在设计一个供应商,提供媒体相关数据,如音乐或视频,你可以结合表数据和文件的供应商。
对于基于网络的数据时,使用java.net和android.net类。还可以同步基于网络的数据到本地数据存储,例如数据库,然后提供该数据作为表或文件。样本同步适配器示例应用程序演示了这种类型的同步。
数据设计注意事项


这里有一些提示设计提供商的数据结构:


表中的数据应该始终有一个供应商保持为每个行的唯一数值的“主键”一栏。您可以使用此值的行链接到其他表中相关行(使用它作为“外键”)。尽管可以为此列以任何名义,使用BaseColumns._ID是最好的选择,因为连接提供商查询到ListView结果需要检索的一列有姓名_ID。
如果你想提供的位图图像或其他非常大块面向文件的数据,数据存储在一个文件,然后为其提供间接而不是直接在表中存储它。如果你这样做,你需要告诉您的供应商的用户,他们需要使用ContentResolver的文件的方法来访问数据。
使用二进制大对象(BLOB)数据类型来存储在尺寸变化或具有变化的结构的数据。例如,你可以使用一个BLOB列来存储协议缓冲区或JSON结构。
你也可以使用一个BLOB实现架构的独立表。在这种类型的表,可以定义主键列,MIME类型列,以及一个或多个通用列作为BLOB。在BLOB列中的数据的含义是由MIME类型列中的值表示。这使您可以存储不同行类型在同一个表。联系人提供商的“数据”表ContactsContract.Data是一个模式独立表的一个例子。
设计内容的URI


A含量URI是一个URI,在供应商标识数据。内容的URI包括整个提供商(其权威)的符号名和一个指向表或文件(路径)的名称。可选的ID部分指向表中的一个单独的行。的ContentProvider的每个数据访问方法有一个内容URI作为参数;这使您可以确定表,行或文件来访问。


内容URI的基础知识中的主题内容提供商基础知识进行了描述。


设计一个权威


提供者通常有一个单一的机构,作为其Android平台的内部名称。为了避免与其他供应商的冲突,你应该使用互联网域名所有权(反向)作为您的供应商权力的基础。因为这个建议也为Android包名真的,你可以定义你的供应商权威包含提供包的名称的扩展。例如,如果你的Andr??oid包名称是com。示例。<应用程序名称>,你应该给你的供应商的授权com。示例。<APPNAME> .provider。


设计路径结构


开发人员通常通过追加指向单个表的路径创建从权威内容的URI。例如,如果你有两个表Table 1和Table,你从前面的例子相结合的权力产生的URI com。示例的内容。<应用程序名称> .provider /表1和com。示例。<应用程序名称> .provider /表2。路径不局限于单一的段,并有不必须为路径中的每个级别的表。


处理内容URI标识


按照惯例,提供者通过接受内容的URI与在URI的末尾行的ID值提供访问单个行中的一个表。同样按照约定,供应商ID值表中的列_ID匹配,并执行对符合该行的请求的访问。


该公约为便于访问的应用程序供应商共同设计模式。该应用程序确实对供应商的查询和使用的CursorAdapter显示最终光标在ListView。 CursorAdapter的定义要求将_id在光标的一列


用户然后拾取为了看或修改数据从UI的显示的行中的一个。该应用程序从游标得到相应的支持排在ListView,获取_ID值此行,就追加内容URI,并发送访问请求提供商。然后,供应商可以做对的确切行的用户选择了查询或修改。


内容URI模式


为了帮助您选择乘坐传入内容URI该动作,提供API包括方便的类UriMatcher,它映射内容URI“模式”为整数值。您可以在选择的内容一个或多个URI匹配特定模式所需的操作开关语句中使用的整数值。


A含量URI模式匹配使用通配符内容的URI:


*:匹配任意长度的任何有效字符的字符串。
#:匹配任意长度的数字字符的字符串。
由于设计和编码内容URI处理的一个例子,考虑与识别指向表以下内容的URI权威com.example.app.provider提供商:


content://com.example.app.provider/table1:叫table1的表。
content://com.example.app.provider/table2/dataset1:所谓的数据集1的表。
content://com.example.app.provider/table2/dataset2:所谓dataset2的表。
content://com.example.app.provider/table3:表3名为表。
//com.example.app.provider/table3/1由1表3中标识的行:如果他们有一个行ID追加到他们,例如内容提供者也认识到这些内容的URI。
content://com.example.app.provider/table3/1 for the row identified by 1 in table3.

下面的内容URI模式是可能的:
content://com.example.app.provider/*
匹配供应商的任何内??容URI。
content://com.example.app.provider/table2/*:
相匹配数据集1和dataset2表内容URI,但不匹配的表1和表3的内容的URI。
content://com.example.app.provider/table3/#: Matches a content URI for single rows in table3, such ascontent://com.example.app.provider/table3/6 for the row identified by 6.
下面的代码片段显示UriMatcher如何工作的方法。此代码的URI处理的URI整个表为不同的单排,用内容URI模式的内容:// <授权> / <路径>为表,内容:// <授权> / <路径> / < ID>单行。


该方法addURI()映射的权威和路径的整数值。该方法匹配()返回一个URI整数值。查询整个表,和查询单条记录之间的switch语句选择:


public class ExampleProvider extends ContentProvider {...    // Creates a UriMatcher object.    private static final UriMatcher sUriMatcher;...    /*     * The calls to addURI() go here, for all of the content URI patterns that the provider     * should recognize. For this snippet, only the calls for table 3 are shown.     */...    /*     * Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used     * in the path     */    sUriMatcher.addURI("com.example.app.provider", "table3", 1);    /*     * Sets the code for a single row to 2. In this case, the "#" wildcard is     * used. "content://com.example.app.provider/table3/3" matches, but     * "content://com.example.app.provider/table3 doesn't.     */    sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);...    // Implements ContentProvider.query()    public Cursor query(        Uri uri,        String[] projection,        String selection,        String[] selectionArgs,        String sortOrder) {...        /*         * Choose the table to query and a sort order based on the code returned for the incoming         * URI. Here, too, only the statements for table 3 are shown.         */        switch (sUriMatcher.match(uri)) {            // If the incoming URI was for all of table3            case 1:                if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";                break;            // If the incoming URI was for a single row            case 2:                /*                 * Because this URI was for a single row, the _ID value part is                 * present. Get the last path segment from the URI; this is the _ID value.                 * Then, append the value to the WHERE clause for the query                 */                selection = selection + "_ID = " uri.getLastPathSegment();                break;            default:            ...                // If the URI is not recognized, you should do some error handling here.        }        // call the code to actually do the query    }

    }
另一类,ContentUris,提供与内容的URI的ID部分工作方便的方法。类URI和Uri.Builder包括解析现有的URI对象和建设新的便捷方法。


实施ContentProvider类


该ContentProvider的实例管理通过处理从其他应用程序请求访问结构化的数据集。访问的所有形式的最终调用ContentResolver的,然后调用的ContentProvider的具体方法来获取访问权限。


所需的方法


抽象类定义的ContentProvider,你必须实现作为自己的具体子类的第六部分抽象方法。所有这些方法除的onCreate()是由正试图访问您的内容提供商的客户端应用程序调用:


query()
从您的提供商获取数据。使用参数选择表进行查询,行和列返回,结果的排序顺序。返回的数据作为光标对象。
insert()
插入新行到您的供应商。使用参数选择目标表,并获取列值使用。返回内容URI为新插入的行。
update()
在您的供应商更新现有行。使用参数选择表和行更新,并获得更新的列值。返回更新的行数。
delete()
从您的提供商删除行。使用参数选择表和要删除的行。返回删除的行数。
getType()
返回对应于内容的URI的MIME类型。这种方法更详细地在部分实施内容提供商MIME类型描述。
onCreate()
初始化您的供应商。 Android系统调用这个方法后立即创建您的供应商。请注意,不会创建你的供应商,直到ContentResolver的对象试图访问它。
请注意,这些方法具有相同签名的同名的ContentResolver的方法。


你的实现这些方法应该考虑以下几点:


所有这些方法除的onCreate()可以由多个线程同时被调用,所以它们必须是线程安全的。要了解更多关于多线程,请参阅进程和线程。
避免的onCreate做冗长的操作()。延迟初始化任务,直到他们真正需要。实施onCreate()方法的部分更加详细地讨论这一点。
尽管必须实现这些方法,你的代码没有做,除了返回预期的数据类型什么。例如,您可能要防止其他应用程序将数据插入到一些表。要做到这一点,你可以忽略调用insert(),并返回0。
实施query()方法


该ContentProvider.query()方法必须返回一个游标对象,如果失败,抛出异常。如果您正在使用的SQLite数据库作为数据存储,您可以简单地返回该查询中的一个()的SQLiteDatabase类的方法返回的光标。如果查询不匹配任何行,你应该返回游标实例,其getCount将()方法返回0。您应该只返回null如果在查询过程中发生内部错误返回。


如果不使用的SQLite数据库作为数据存储,使用光标的具体子类之一。例如,MatrixCursor类实现一个光标,其中每一行是对象的阵列。有了这个类,使用addRow()来添加一个新行。


请记住,Android系统必须能够跨越进程边界通信的例外。 Android版可以为以下例外情况,可能是在处理查询错误有用做到这一点:


抛出:IllegalArgumentException(您可以选择抛出此,如果你的供应商接收到一个非法的内容URI)
空指针异常
实施insert()方法


插入()方法添加一个新行到相应的表,可以使用在ContentValues??参数的值。如果列名是不是在ContentValues??说法,您可能希望无论是在你的供应商代码或数据库模式为它提供一个默认值。


此方法应返回内容的URI新行。构造此,追加新行的_ID(或其他主键)值表中的内容URI,使用withAppendedId()。


实施delete()方法


删除()方法没有实际从您的数据存储中删除行。如果您使用的是与你的供应商同步适配器,你应该考虑标记删除的行以“删除”标志,而不是删除的行。同步适配器可以检查删除的行,并从供应商删除之前从服务器上删除它们。


实施update()方法


更新()方法)插入(使用相同的ContentValues??参数,()通过删除(),ContentProvider.query使用相同的选择和selectionArgs两个参数。这可能让你重新使用这些方法之间的代码。


实施onCreate()方法


Android系统调用的onCreate(),当它启动时提供。应该在此方法仅执行快速运转的初始化任务,并推迟数据库创建和数据加载,直到提供实际接收的数据的请求。如果你做的onCreate冗长的任务(),您会减慢你的供应商的启动。反过来,这会减慢从提供给其他应用程序的响应。


例如,如果您使用的是SQLite数据库您可以创建ContentProvider.onCreate()一个新的SQLiteOpenHelper对象,然后创建SQL表你第一次打开数据库。为了推动这项工作,你第一次调用getWritableDatabase(),它会自动调用SQLiteOpenHelper.onCreate()方法。


下面的两个片段演示ContentProvider.onCreate()和SQLiteOpenHelper.onCreate()之间的相互作用。第一个片段是ContentProvider.onCreate()的实现:


public class ExampleProvider extends ContentProvider    /*     * Defines a handle to the database helper object. The MainDatabaseHelper class is defined     * in a following snippet.     */    private MainDatabaseHelper mOpenHelper;    // Defines the database name    private static final String DBNAME = "mydb";    // Holds the database object    private SQLiteDatabase db;    public boolean onCreate() {        /*         * Creates a new helper object. This method always returns quickly.         * Notice that the database itself isn't created or opened         * until SQLiteOpenHelper.getWritableDatabase is called         */        mOpenHelper = new MainDatabaseHelper(            getContext(),        // the application context            DBNAME,              // the name of the database)            null,                // uses the default SQLite cursor            1                    // the version number        );        return true;    }    ...    // Implements the provider's insert method    public Cursor insert(Uri uri, ContentValues values) {        // Insert code here to determine which table to open, handle error-checking, and so forth        ...        /*         * Gets a writeable database. This will trigger its creation if it doesn't already exist.         *         */        db = mOpenHelper.getWritableDatabase();    }}

接下来的片段是SQLiteOpenHelper.onCreate的实现()在内的辅助类:


...// A string that defines the SQL statement for creating a tableprivate static final String SQL_CREATE_MAIN = "CREATE TABLE " +    "main " +                       // Table's name    "(" +                           // The columns in the table    " _ID INTEGER PRIMARY KEY, " +    " WORD TEXT"    " FREQUENCY INTEGER " +    " LOCALE TEXT )";.../** * Helper class that actually creates and manages the provider's underlying data repository. */protected static final class MainDatabaseHelper extends SQLiteOpenHelper {    /*     * Instantiates an open helper for the provider's SQLite data repository     * Do not do database creation and upgrade here.     */    MainDatabaseHelper(Context context) {        super(context, DBNAME, null, 1);    }    /*     * Creates the data repository. This is called when the provider attempts to open the     * repository and SQLite reports that it doesn't exist.     */    public void onCreate(SQLiteDatabase db) {        // Creates the main table        db.execSQL(SQL_CREATE_MAIN);    }}

实现ContentProvider的MIME类型


ContentProvider类拥有返回MIME类型的两种方法:


getType()
对,你必须为所有供应商实施所需的方法。
getStreamTypes()
您所期望实现,如果你的供应商提供文件的方法。
MIME类型的表


对GetType()方法返回MIME格式的字符串描述由内容URI参数返回的数据类型。该URI参数可以是一个模式,而不是特定的URI;在这种情况下,你应该返回与该模式匹配的内容的URI相关的数据类型。


对于常见的类型,如文本,HTML,或JPEG的getType(数据)应返回的标准MIME类型的数据。这些标准类型的完整列表,请访问IANA MIME媒体类型网站。


对于指向一个行或表数据行内容的URI,的getType()应该返回在Android的特定供应商的MIME格式的MIME类型:


一部分:VND
亚型部分:
如果URI模式是单行:android.cursor.item /
如果URI图案为多个行:android.cursor.dir /
提供特定的部分:越南盾<名> <类型>
您提供的<name>和<类型>。的<name>值应该是全球唯一的,并且<类型>值应该是唯一的,以相应的URI图案。对于一个很好的选择<name>是您的公司名称或您的应用程序的Andr??oid包名的某些部分。为<类型>一个很好的选择是标识与URI关联的表中的字符串。
例如,如果一个供应商的权威com.example.app.provider,它暴露了一个表名为table1,MIME类型多行表1中的是:


vnd.android.cursor.dir/vnd.com.example.provider.table1

对于表1的单排中,MIME类型是:


vnd.android.cursor.item/vnd.com.example.provider.table1

MIME类型的文件


如果您的供应商提供的文件,实施getStreamTypes()。该方法返回的MIME类型为您提供者可以返回给定内容的URI文件的字符串数组。你应该过滤你的MIME类型过滤器参数报价MIME类型,让你只返回客户端要处理这些MIME类型。


例如,考虑一个供应商,提供的照片图像,文件为.jpg,.png和.gif格式。如果应用程序调用与过滤字符串ContentResolver.getStreamTypes()图像/ *(东西是一个“形象”),那么ContentProvider.getStreamTypes()方法应该返回数组:


{ "image/jpeg", "image/png", "image/gif"}

如果应用程序仅在.jpg文件感兴趣,那么它可以调用与过滤字符串* \ / JPEG和ContentProvider.getStreamTypes()应该返回ContentResolver.getStreamTypes():


{"image/jpeg"}

如果您的供应商不提供任何过滤字符串中所要求的MIME类型,getStreamTypes()应该返回null。


实施合同类


合同类是包含的URI,涉及到供应商常量定义,列名,MIME类型和其他元数据有public final类。类建立通过确保提供商可正确访问即使有变化的URI的实际值,列名等等的提供者和其他应用之间的契约。


合同类还可以帮助开发人员,因为它通常具有其常量记忆的名字,所以开发商不太可能使用不正确的值列名或URI的。因为它是一个类,它可以包含Javadoc文档。集成开发环境如Eclipse可以从合同类和显示Javadoc文档的常量自动完成常量名。


开发商不能从您的应用程序访问合同类的类文件,但他们可以将其静态编译成自己的应用程序,从您提供的.jar文件。


该ContactsContract类及其嵌套类合同的类的实例。


实施内容提供商权限


权限和Android系统的各个方面都获得了详细的专题安全和权限描述。主题数据存储还介绍了安全性和权限,对各种类型的存储效果。简而言之,重要的点是:


默认情况下,存储在设备的内部存储数据文??件仅对您的应用程序和供应商。
创建SQLiteDatabase数据库是私有的应用程序和供应商。
默认情况下,您保存到外部存储数据文??件是公开的,所有人可读。不能使用内容提供商,以限制访问外部存储的文件,因为其他应用程序可以使用其他的API调用来读,写他们。
该方法要求打开或对你的设备的内部存储创建文件或SQLite数据库有可能给读写访问所有其他应用程序。如果你使用一个内部文件或数据库作为供应商的资料库,你给它的“世界可读”或“世界可写”的访问,您对在其清单提供商不会保护你的数据设置的权限。在内部存储的文件和数据库的默认访问是“私人”,并为您的供应商的资料库,你不应该改变这一点。
如果您想使用内容提供商权限来控制访问您的数据,那么你应该存储你的数据在内部文件,SQLite数据库,或者“云”(例如,在远程服务器上),你应该保持文件和数据库私有应用程序。


实施权限


所有的应用程序都可以读取或写入到您的供应商,即使基础数据是私有的,因为默认情况下你的供应商没有设置权限。要改变这种情况,为您的供应商的权限在你的清单文件,使用属性或<provider>元素的子元素。可以设置适用于整个提供商,或者某些表,或甚至特定的记录,或所有三种的权限。


你定义在你的清单文件中的一个或多个<许可>元素你的供应商的权限。为了使权限独特的提供商,使用Java风格的范围界定为Android:name属性。例如,命名读取权限com.example.app.provider.permission.READ_PROVIDER。


下面的列表说明提供者的权限范围,从应用到整个提供商,然后变得更加细粒度的权限。更细粒度的权限优先于那些具有较大的适用范围:


单个读写提供商级别权限
一个权限同时控制读写访问到整个供应商,android的规定:在<provider>元素的权限属性。
单独的读写提供商级别权限
读权限和整个提供商写权限。你用android指定它们:readPermission和android:在<provider>元素的writePermission属性。他们优先于由Android所需的权限:许可。
路径级别权限
读,写或读/写权限在你的提供者的内容URI。您可以指定希望与<provider>元素的<路径许可>子元素来控制每个URI。对于每个指定的内容URI,可以指定一个读/写权限,读权限或写权限,或所有三种。在读取和写入权限优先于读/写权限。此外,道路级别权限接管供应商级别的权限优先。
临时许可
权限级别授予给应用程序的临时访问,即使该应用程序不具有通常所需的权限。临时访问功能减少权限的应用程序在其清单,要求的数量。当您打开临时权限,需要为您提供“永久”权限的唯一的应用程序是那些不断地访问所有数据。
想想你需要实现电子邮件提供商和应用程序的权限,当你希望允许外部图像浏览器应用程序从您的供应商显示照片附件。为了让图像浏览器,而无需权限必要的访问,内容的URI照片设立临时权限。设计你的电子邮件应用程序,以便当用户想要显示的照片,应用程序发送包含照片的内容URI和权限标志的图像浏览器的意图。然后,图像浏览器可以查询您的电子邮件提供商来获取照片,即使观众没有为您提供正常的读取权限。


要打开临时权限,无论是设置了android:在<provider>元素的grantUriPermissions属性,或添加一个或多个<赠款URI的权限>子元素,在<provider>元素。如果您使用临时权限,则必须调用Context.revokeUriPermission()每当你删除从您的提供者的内容URI的支持,以及内容URI与临时许可有关。


属性值的多少决定你的供应商是进行访问。如果该属性设置为true,那么系统会给予临时许可,您的整个供应商,覆盖由您的提供商级或路径级别权限所需的任何其他权限。


如果此标志设置为false,那么你必须<赠款URI的权限>子元素添加到您的<provider>元素。每个子元素指定内容的一个或多个URI为其临时访问是理所当然的。


委托给一个应用程序的临时访问,意图必须包含FLAG_GRANT_READ_URI_PERMISSION或FLAG_GRANT_WRITE_URI_PERMISSION标志,或两者。这些设置与setFlags()方法。


如果机器人:grantUriPermissions属性不存在,它的假设是错误的。


在<provider>元素
样活性和服务组件,ContentProvider的子类必须在其应用程序清单文件中定义,使用<provider>元素。 Android系统会从该元素的以下信息:
管理局(机器人:当局)
符号名标识系统内的整个提供商。此属性在更详细的部分设计内容的URI描述。
提供类名(安卓名)
实现ContentProvider的类。这个类中有更详细的部分实施ContentProvider类描述。
权限
属性指定的权限的其他应用程序必须有为了访问提供者的数据:
android:grantUriPermssions:临时许可标志。
android:permission:单一的供应商范围内的读/写权限。
android:readPermission::运营商级读取权限。
android:writePermission:提供全写权限。
权限和它们的相应的属性进行更详细的部分实施内容提供商权限说明。
启动和控制属性
这些属性决定当Android系统启动供应商,供应商的工艺特点,以及其他运行时设置和如何:
android:enabled::标志使系统启动供应商。
android:exported标志,允许其他应用程序使用此提供程序。
android:initOrder其中该提供应开始的顺序,相对于在相同的过程中的其他供应商。
android:multiProcess::标志使系统启动供应商在同一个进程中调用客户端。
android:process:在供应商应该运行的进程的名称。
android:syncable标志表明该供应商的数据与服务器上的数据进行sync'ed。
该属性的<provider>元素开发指南主题完全记录。
信息属性
可选的图标和标签的供应商:
android:icon::包含供应商图标的绘制资源。旁边的提供商的标签出现在设置>应用程序>所有应用程序列表中的图标。
android:label:信息性标签说明提供者或它的数据,或两者兼而有之。该标签将出现在设置>应用程序>所有应用程序的列表。
该属性的<provider>元素开发指南主题完全记录。
意图和数据访问
应用程序可以用一个Intent间接访问内容提供商。应用程序不调用任何ContentResolver的或ContentProvider的方法。相反,它发送一个启动活动,这往往是提供者的自己的应用程序的一部分的意图。目的地活性负责检索和在其UI显示数据。取决于意图的动作,在目标的活动也可提示用户进行修改,以提供者的数据。意图也可能含有“额外”的数据,在UI目标的活动显示;然后用户具有使用它来修改在提供数据之前,改变该数据的选项。
您可能需要使用意图取用,以帮助确保数据的完整性。您的供应商可能会依赖于数据的插入,更新和删除按照严格定义的业务逻辑有。如果是这种情况,允许其他应用程序直接修改您的数据可能会导致无效的数据。如果你想开发者使用意向访问,一定要彻底将其记录下来。使用自己的应用程序的用户界面是不是试图用自己的代码来修改数据更好地解释他们为什么意图取用。
处理传入的意图希望修改您的供应商的数据无异于处理其他的意图不同。您可以通过阅读题目意图和意图过滤器了解有关使用意图。
  相关解决方案