适用场景1)ContentProvider提供统一的存储和读取数据的接口2)使用ContentProvider,应用程序可以共享数据3)android中很多内置的数据都使用ContentProvider的形式供开发者调用(如视频、音频、图片、通讯录等)二、相关概念介绍1)ContentProvider简介当一个应用继承ContentProvider类并重写用于提供数据和存储数据的方法时,可以将其共享给其他应用数据。虽然也可以通过其他方式对外共享数据,但数据的访问方式会因数据存储方式的不同而有所差异。例如,文件用于对外共享数据,需要进行文件操作来读写数据;如果使用sharedpreferences来共享数据,则需要使用sharedpreferencesAPI来读写数据。使用ContentProvider共享数据的好处是统一了数据的访问方式。2)Uri类介绍Uriuri=Uri.parse("content://com.changcheng.provider.contactprovider/contact")ContentProvider中使用的querystring不同于标准的SQL查询。选择、添加、删除、修改等很多操作我们都使用一个特殊的URI。这个URI由3部分组成,“content://”,代表数据的路径,和一个可选的标识数据ID。以下是一些URI示例:content://media/internal/images此URI将返回设备上存储的所有图像content://contacts/people/此URI将返回设备上的所有联系人信息content://contacts/people/45这个URI返回一个结果(联系人信息中ID为45的联系人记录) 虽然这种查询字符串格式很常见,但看起来有点混乱。为此,Android提供了一系列的helper类(在android.provider包下),其中包含了很多以类变量的形式给出的查询字符串,更便于我们理解,所以,如上内容:URI//contacts/people/45可以这样写: Uriperson=ContentUris.withAppendedId(People.CONTENT_URI,45);然后执行数据查询:Cursorcur=managedQuery(person,null,null,null);这个查询返回一个包含所有数据字段的游标,我们可以通过遍历游标包com.wissen.testApp;publicclassContentProviderDemoextendsActivity{@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);displayRecords();}privatevoiddisplayRecords(){//数组包含所有要返回的字段Stringcolumns[]=newString[]{People.NAME,People.NUMBER};UrimContacts=People.CONTENT_URI;Cursorcur=managedQuery(mContacts,columns,//要返回的数据字段 null,//WHERE子句 null,//WHERE子句参数 null//Order-by子句);if(cur.moveToFirst()){Stringname=null;StringphoneNo=null;do{//获取字段的值 name=cur.getString(cur.getColumnIndex(People.NAME));phoneNo=cur.getString(cur.getColumnIndex(People.NUMBER));Toast.makeText(this,name+””+phoneNo,Toast.LENGTH_LONG).show();}while(cur.moveToNext());}}} 上面的例子演示了如何顺序读取指定数据列名和编号修改记录:我们可以使用ContentResolver.update()方法修改数据。让我们写一个修改数据的方法:rivatevoidupdateRecord(intrecNo,Stringname){Uriuri=ContentUris.withAppendedId(People.CONTENT_URI,recNo);ContentValuesvalues=newContentValues();values.put(People.NAME,name);getContentResolver()。update(uri,values,null,null);}现在你可以调用上面的方法来更新指定的记录:updateRecord(10,"XYZ");//将第10条记录的name字段值改为“XYZ”添加记录:要添加记录,我们可以调用ContentResolver.insert()方法,该方法接受要添加的记录的目标URI,以及一条新记录包含一个Map对象的值,调用后的返回值是新记录的URI,包括记录号。在上面的例子中,我们都是基于联系信息簿的标准ContentProvider。现在我们继续创建一个insertRecord()方法来向联系人信息簿中添加数据:.insert(People.CONTENT_URI,values);Log.d("ANDROID",uri.toString());UrinumberUri=Uri.withAppendedPath(uri,People.Phones.CONTENT_DIRECTORY);values.clear();values.put(Contacts.Phones.TYPE,People.Phones.TYPE_MOBILE);values.put(People.NUMBER,phoneNo);getContentResolver().insert(numberUri,values);}这样我们就可以调用insertRecords(name,phoneNo)添加联系信息簿中的联系人姓名和电话号码。删除记录:ContentProvider中的getContextResolver.delete()方法可以用来删除记录。以下记录用于删除设备上的所有联系人信息。privatevoiddeleteRecords(){Uriuri=People.CONTENT_URI;getContentResolver().delete(uri,null,null);}也可以指定WHERE条件语句删除特定记录:getContentResolver().delete(uri,“NAME=”+“'XYZXYZ'”,空);这将删除名称为“XYZXYZ”的记录。3.创建ContentProvider要创建我们自己的ContentProvider,我们需要按照以下步骤进行:创建一个类继承ContentProvider的父类b。定义一个名为CONTENT_URI的类变量publicstaticfinalUri类型,必须为其指定一个唯一的字符串值,最好的方案是类的全名,如:publicstaticfinalUriCONTENT_URI=Uri.parse("content//com.google.android.MyContentProvider");c.定义要返回给客户端的数据列名称。如果你使用的是Android数据库,你必须为其定义一个名为_id的列,用于表示每条记录的唯一性。d.创建您的数据存储系统。大多数内容提供商使用Android文件系统或SQLite数据库来保存数据,但您可以以任何您想要的方式存储数据。e.如果要存储字节类型的数据,比如位图文件等,数据列其实就是一个代表实际保存文件的URI字符串,通过它可以读取到对应的文件数据。处理此类数据的ContentProvider需要实现一个名为_data的字段,该字段列出文件在Android文件系统上的确切路径。该字段不仅供客户端使用,也供ContentResolver使用。客户端可以调用ContentResolver.openOutputStream()方法处理URI指向的文件资源;如果是ContentResolver本身,由于它拥有比客户端更高的权限,它可以直接访问数据文件。F。声明一个publicstaticString类型的变量,用于指定游标要返回的数据列。G。该查询返回一个Cursor类型的对象。所有执行写操作的方法,如insert()、update()和delete()都将被监视。我们可以使用ContentResover().notifyChange()方法通知监听器数据更新。H。使用AndroidMenifest.xml中的
