1、使用 ContentProvider(内容提供者)共享数据ContentProvider 在 android 中的作用是对外共享数据,也就是说你可以通过 ContentProvider 把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider 对你应用中的数据进行添删改查。关于数据共享,以前我们学习过文件操作模式,知道通过指定文件的操作模式为Context.MODE_WORLD_READABLE 或 Context.MODE_WORLD_WRITEABLE 同样也可以对外共享数据。那么,这里为何要使用 ContentProvider 对外共享数据呢?是这样的,如果采用文
2、件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用 xml 文件对外共享数据,需要进行 xml 解析才能读取数据;采用 sharedpreferences 共享数据,需要使用 sharedpreferences API 读取数据。使用 ContentProvider 对外共享数据的好处是统一了数据的访问方式。当应用需要通过 ContentProvider 对外共享数据时,第一步需要继承 ContentProvider 并重写下面方法:public class PersonContentProvider extends ContentProvid
3、erpublic boolean onCreate()public Uri insert(Uri uri, ContentValues values)public int delete(Uri uri, String selection, String selectionArgs)public int update(Uri uri, ContentValues values, String selection, String selectionArgs)public Cursor query(Uri uri, String projection, String selection, Strin
4、g selectionArgs, String sortOrder)public String getType(Uri uri)第二步需要在 AndroidManifest.xml 使用对该 ContentProvider 进行配置,为了能让其他应用找到该 ContentProvider , ContentProvider 采用了authorities(主机名/域名)对它进行唯一标识,你可以把 ContentProvider 看作是一个网站(想想,网站也是提供数据者) ,authorities 就是他的域名:Uri 介绍ContentProvider(内容提供者)的 scheme 已经由 An
5、droid 所规定, scheme 为:content:/主机名(或叫 Authority)用于唯一标识这个 ContentProvider,外部调用者可以根据这个标识来找到它。路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:要操作 person 表中 id 为 10 的记录,可以构建这样的路径:/person/10要操作 person 表中 id 为 10 的记录的 name 字段, person/10/name要操作 person 表中的所有记录,可以构建这样的路径:/person要操作 xxx 表中的记录,可以构建这样的路径:/xxx当然要操作的数据不一定来
6、自数据库,也可以是文件、xml 或网络等其他存储方式,如下:要操作 xml 文件中 person 节点下的 name 节点,可以构建这样的路径:/person/name如果要把一个字符串转换成 Uri,可以使用 Uri 类中的 parse()方法,如下:Uri uri = Uri.parse(“content:/cn.itcast.provider.personprovider/person“)UriMatcher 类使用介绍因为 Uri 代表了要操作的数据,所以我们经常需要解析 Uri,并从 Uri 中获取数据。Android 系统提供了两个用于操作 Uri 的工具类,分别为 UriMatc
7、her 和 ContentUris 。掌握它们的使用,会便于我们的开发工作。UriMatcher 类用于匹配 Uri,它的用法如下:首先第一步把你需要匹配 Uri 路径全部给注册上,如下:/常量 UriMatcher.NO_MATCH 表示不匹配任何路径的返回码UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);/如果 match()方法匹配 content:/cn.itcast.provider.personprovider/person 路径,返回匹配码为 1sMatcher.addURI(“cn.itcast.provide
8、r.personprovider”, “person”, 1);/添加需要匹配 uri,如果匹配就会返回匹配码/如果 match()方法匹配 content:/cn.itcast.provider.personprovider/person/230 路径,返回匹配码为 2sMatcher.addURI(“cn.itcast.provider.personprovider”, “person/#”, 2);/#号为通配符switch (sMatcher.match(Uri.parse(“content:/cn.itcast.provider.personprovider/person/10“)
9、case 1break;case 2break;default:/不匹配break;注册完需要匹配的 Uri 后,就可以使用 sMatcher.match(uri)方法对输入的 Uri 进行匹配,如果匹配就返回匹配码,匹配码是调用 addURI()方法传入的第三个参数,假设匹配 content:/cn.itcast.provider.personprovider/person 路径,返回的匹配码为 1ContentUris 类使用介绍ContentUris 类用于获取 Uri 路径后面的 ID 部分,它有两个比较实用的方法:withAppendedId(uri, id)用于为路径加上 ID 部
10、分:Uri uri = Uri.parse(“content:/cn.itcast.provider.personprovider/person“)Uri resultUri = ContentUris.withAppendedId(uri, 10); /生成后的 Uri 为:content:/cn.itcast.provider.personprovider/person/10parseId(uri)方法用于从路径中获取 ID 部分:Uri uri = Uri.parse(“content:/cn.itcast.provider.personprovider/person/10“)long
11、personid = ContentUris.parseId(uri);/获取的结果为:10使用 ContentProvider 共享数据ContentProvider 类主要方法的作用:public boolean onCreate()该方法在 ContentProvider 创建后就会被调用, Android 开机后, ContentProvider 在其它应用第一次访问它时才会被创建。public Uri insert(Uri uri, ContentValues values)该方法用于供外部应用往 ContentProvider 添加数据。public int delete(Uri
12、uri, String selection, String selectionArgs)该方法用于供外部应用从 ContentProvider 删除数据。public int update(Uri uri, ContentValues values, String selection, String selectionArgs)该方法用于供外部应用更新 ContentProvider 中的数据。public Cursor query(Uri uri, String projection, String selection, String selectionArgs, String sortOr
13、der)该方法用于供外部应用从 ContentProvider 中获取数据。public String getType(Uri uri)该方法用于返回当前 Url 所代表数据的 MIME 类型。如果操作的数据属于集合类型,那么 MIME 类型字符串应该以 vnd.android.cursor.dir/开头,例如:要得到所有 person 记录的 Uri 为 content:/cn.itcast.provider.personprovider/person,那么返回的 MIME 类型字符串应该为:“vnd.android.cursor.dir/person” 。如果要操作的数据属于非集合类型数据
14、,那么 MIME 类型字符串应该以 vnd.android.cursor.item/开头,例如:得到 id 为 10 的 person 记录,Uri 为content:/cn.itcast.provider.personprovider/person/10,那么返回的 MIME 类型字符串应该为:“vnd.android.cursor.item/person” 。使用 ContentResolver 操作 ContentProvider 中的数据当外部应用需要对 ContentProvider 中的数据进行添加、删除、修改和查询操作时,可以使用 ContentResolver 类来完成,要获取
15、 ContentResolver 对象,可以使用 Activity 提供的 getContentResolver()方法。 ContentResolver 类提供了与 ContentProvider 类相同签名的四个方法:public Uri insert(Uri uri, ContentValues values)该方法用于往 ContentProvider 添加数据。public int delete(Uri uri, String selection, String selectionArgs)该方法用于从 ContentProvider 删除数据。public int update(U
16、ri uri, ContentValues values, String selection, String selectionArgs)该方法用于更新 ContentProvider 中的数据。public Cursor query(Uri uri, String projection, String selection, String selectionArgs, String sortOrder)该方法用于从 ContentProvider 中获取数据。这些方法的第一个参数为 Uri,代表要操作的 ContentProvider 和对其中的什么数据进行操作,假设给定的是: Uri.par
17、se(“content:/cn.itcast.providers.personprovider/person/10”),那么将会对主机名为 cn.itcast.providers.personprovider 的 ContentProvider 进行操作,操作的数据为 person 表中 id 为 10 的记录。使用 ContentResolver 操作 ContentProvider 中的数据使用 ContentResolver 对 ContentProvider 中的数据进行添加、删除、修改和查询操作:ContentResolver resolver = getContentResolve
18、r();Uri uri = Uri.parse(“content:/cn.itcast.provider.personprovider/person“);/添加一条记录ContentValues values = new ContentValues();values.put(“name“, “itcast“);values.put(“age“, 25);resolver.insert(uri, values);/获取 person 表中所有记录Cursor cursor = resolver.query(uri, null, null, null, “personid desc“);while
19、(cursor.moveToNext()Log.i(“ContentTest“, “personid=“+ cursor.getInt(0)+ “,name=“+ cursor.getString(1);/把 id 为 2 的记录的 name 字段值更改新为 limingContentValues updateValues = new ContentValues();updateValues.put(“name“, “liming“);Uri updateIdUri = ContentUris.withAppendedId(uri, 2);resolver.update(updateIdUri
20、, updateValues, null, null);/删除 id 为 2 的记录Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);resolver.delete(deleteIdUri, null, null);例:在 db 应用创建一个内容提供者,在 other 应用对内容提供者进行访问(db 应用) cn.itcast.db.PersonProvider/* 内容提供者* * 内容提供者的作用就是对外共享数据,所以其它应用需要找到内容提供者才能从它里面获得数据并操作里面的数据* * 这个 组件创 建好需要在项目清单文件中注册一下:
21、在activity 下面,为了便于其它应用能够找到内容提供者,需要为它指定唯一标识 * */public class PersonProvider extends ContentProvider /* 因为Uri代表了要操作的数据,所以我们经常需要解析 Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris*/private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);private static final int P
22、ERSONS=1; /匹配码private static final int PERSON=2; /匹配码/在静态 代码块里面对 常量进行初始化static/往 对象中添加要匹配的路径 1、主机名 2、路径 3、如果匹配person(person/#)这个路径格式就返回相应匹配码MATCHER.addURI(“cn.itcast.providers.personprovider“, “person“, PERSONS);MATCHER.addURI(“cn.itcast.providers.personprovider“, “person/#“, PERSON); /#代表数字id priva
23、te DBOpenHelper dbOpenHelper=null;Override/这个方法是当内容提供者被实例化后被调用public boolean onCreate() /对 它进行初始化拿到数据 库的对象,传一个上下文过去dbOpenHelper=new DBOpenHelper(getContext(); return false;/* 下面每个方法参数都有一个Uri,Uri在android系统中代表数据。 */*/Override/供其它应用往内容提供者添加数据public Uri insert(Uri uri, ContentValues values) /通 过dbOpenHe
24、lper 这个对象取得数据库的操作实例SQLiteDatabase db=dbOpenHelper.getWritableDatabase();/对 用户传进来的 uri进行匹配switch (MATCHER.match(uri) case PERSONS:/把用 户传进来的数据添加到 person表中long rowid=db.insert(“person“, “name“, values);/该记录的行号,如果主键是自成增长的,那么行号会等于主键id/ContentUris类用于获取Uri路径后面的ID部分 content:/cn.itcast.providers.personprovid
25、er/person/10Uri insertUri = ContentUris.withAppendedId(uri, rowid); return insertUri;default:throw new IllegalArgumentException(“Unknow Uri:“+uri);/*/* delete方法允许处 理两种业务* 1、删除person表中的所有数据 (为它定义业务 路径 /person)* 2、删除person表中的指定id的数据(为它定义业务路径 /person/40)* */Override/供其它应用从内容提供者删除数据 String selection(条件部
26、分) 、 String selectionArgs(条件中出现的占位符的参数值)public int delete(Uri uri, String selection, String selectionArgs) SQLiteDatabase db=dbOpenHelper.getWritableDatabase();/num存放已经被删除的数量int num=0;switch (MATCHER.match(uri) /处理 这两种路径/删 除person表中的所有数据 /personcase PERSONS:/1、person表 2、条件 3、条件中出现的占位符的参数值num=db.dele
27、te(“person“, selection, selectionArgs);break;/删 除person表中的指定 id的数据/person/40case PERSON:/从uri上 提取数字 40 然后得到idlong id=ContentUris.parseId(uri);/组拼成一个条件String where=“personid=“+id;/判断外面是否 传条件进来,如果伟进来就要和上面的这个条件组成一起if(selection!=null /执行从person 删除数据db.delete(“person“, where, selectionArgs);break;default
28、:throw new IllegalArgumentException(“Unknow Uri:“+uri);return num;/*/* update方法允许处 理两种业务* 1、更新person表中的所有数据 (为它定义业务 路径 /person)* 2、更新person表中的指定id的数据(为它定义业务路径 /person/40)* */Override/供其它应用更新内容提供者数据public int update(Uri uri, ContentValues values, String selection,String selectionArgs) SQLiteDatabase db=dbOpenHelper.getWritableDatabase();/num存放已经被更新的数量int num=0;switch (MATCHER.match(uri) /处理 这两种路径/更新 person表中的所有数据 /personcase PERSONS:/1、person表 2、更新person表中哪些字段的 值 3、条件 4、条件中出现的占位符的参数 值