如何为ContentProvider添加访问权限

如何为ContentProvider添加访问权限,第1张

第5节 ContentProvider的使用权限

ContentProvider可以被其他应用使用(就像一个公共网站,可以被任何人访问);也可以被设置成只被自己所在的应用使用(就像一个内部网站,只能在公司内部访问)。

这只需要在应用的AndroidManifest.xml文件中,给ContentProvider设置上Android:exported属性,

<provider

android:name=".MyContentProvider"

android:authorities="com.anddle.mycontentprovider"

android:enabled="true"

android:exported="true" />1234512345

android:exported属性设置成true:可被其他应用使用;

android:exported属性设置成false:只能被自己所在的应用使用;

在对其他应用开放ContentProvider的时候,也可以设置上访问权限,只对部分应用开放使用的权限。

5.1 ContentProvider设置权限

在AndroidManifest.xml文件中,对要设置权限的ContentProvider设置上android:permission属性,该属性值可以任意指定一个字符串。通常使用程序的包名作为其中的一部分,这样可以避免和其他应用中的权限声明冲突。例如"com.anddle.provideraccess,

<provider

android:name=".MyContentProvider"

android:authorities="com.anddle.mycontentprovider"

android:enabled="true"

android:exported="true"

android:permission="com.anddle.provideraccess" />

1

2

3

4

5

6

1

2

3

4

5

6

在AndroidManifest.xml文件中,与同级的位置,对外声明前面使用的标签,表示这个应用发布了一个叫做com.anddle.provideraccess的权限,

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.anddle.lifetime">

<permission

android:name="com.anddle.provideraccess"

android:label="provider pomission"

android:protectionLevel="normal" />

<application

....../>

</manifest>

其中android:name属性的值,就是<provider/>标签中设置的android:permission的值。

1

2

3

4

5

6

7

8

9

10

11

12

1

2

3

4

5

6

7

8

9

10

11

12

5.2 使用带权限的ContentProvider

假如应用B要使用应用A中带权限的ContentProvider,需要在应用B的AndroidManifest.xml中加入权限的使用,

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.anddle.calculator">

<uses-permission android:name="com.anddle.provideraccess"/>

<application

....../>

</manifest>123456789123456789

其中,<uses-permission/>标签中设置的android:name的值,就是应用A中对外声明的那个provider的权限值。

5.3 进一步的权限设置

应用A的ContentProvider还可以将访问的权限进一步细化,分成允许读取和允许写入两种。

当ContentProvider设置了读取的权限,那么其他组件想读取到该ContentProvider的内容时,就必须声明使用读的权限。

当ContentProvider设置了写入的权限,那么其他组件想写入该ContentProvider的内容时,就必须声明使用写的权限。

声明“读取”权限,

<provider

android:name=".MyContentProvider"

......

android:readPermission="com.anddle.provideraccess.read" />

发布“读取”权限,

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.anddle.lifetime">

<permission

android:name="com.anddle.provideraccess.read"

android:label="provider pomission"

android:protectionLevel="normal" />

<application

....../>

</manifest>

1

2

3

4

5

6

7

8

9

10

11

12

1

2

3

4

5

6

7

8

9

10

11

12

1

2

3

4

1

2

3

4

声明“写入”权限,

<provider

android:name=".MyContentProvider"

......

android:writePermission="com.anddle.provideraccess.write" />

发布“写入”权限,

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.anddle.lifetime">

<permission

android:name="com.anddle.provideraccess.write"

android:label="provider pomission"

android:protectionLevel="normal" />

<application

....../>

</manifest>

1

2

3

4

5

6

7

8

9

10

11

12

1

2

3

4

5

6

7

8

9

10

11

12

1

2

3

4

1

2

3

4

需要注意的是,android:writePermission与android:readPermission权限的优先级比android:permission的优先级高,只要设置了高优先级的,那么其他应用要使用高优先级的功能,就要声明高优先级的权限。

例如,一个ContentProvider同时设置了android:readPermission和android:permission权限,第三方应用如果只请求了android:permission权限,是没有办法进行读取 *** 作的。

第6节 ContentProvider的监听

当ContentProvider中存储的数据内容发生变化时,是可以被关注了这些消息的查询者监听到的。

如果想公开自己的数据,那么可有两种办法:

1.创建自己的ContentProvider,需要继承ContentProvider类

2.如果你的数据和已存在的ContentProvider数据结构一致,可以将数据写到已存在的ContentProvider中

当然前提是获取写该ContentProvider的权限.比如把OA中的成员通讯信息加入到系统的联系人ContentProvider中

ContentProvider基础

所有ContentProvider都需要实现相同的接口,用于查询ContentProvider并返回数据.也包括增加、修改和删除数据.

步骤:

1.获得一个ContentResolver的实例,可通过Activity的成员方法getContentResovler()方法:

ContentResolver cr = this.getContentResolver()

ContentResolver实例带的方法可实现找到指定的ContentProvider并获取到ContentProvider的数据

ContentResolver的查询过程开始,Android系统将确定查询所需的具体ContentProvider,确认它是否启动并运行它.

android系统负责初始化所有的ContentProvider,不需要用户自己去创建.实际上,ContentProvider的用户都不可能直接访问到ContentProvider实例,只能通过ContentResolver在中间代理.

2.数据模型

ContentProvider展示数据类似一个单个数据库表.

其中:

每行有个带唯一值的数字字段,名为_ID,可用于对表中指定记录的定位.

ContentProvider返回的数据结构,是类似JDBC的ResultSet,在android中,是Cursor对象.

URI,每个ContentProvider定义一个唯一的公开的URI,用于指定到它的数据集.

一个ContentProvider可以包含多个数据集(可以看作多张表),这样,就需要有多个URI与每个数据集对应.

这些URI要以这样的格式开头:

content://

表示这个URI指定一个ContentProvider.

如果你想创建自己的ContentProvider,最好把自定义的URI设置为类的常量,这样简化别人的调用,并且以后如果更新URI也很容易.

android定义了CONTENT_URI常量用于URI,如:android.provider.Contacts.Phones.CONTENT_URI

2.查询ContentProvider

要想使用一个ContentProvider,需要以下信息:

定义这个ContentProvider的URI,返回结果的字段名称,这些字段的数据类型

如果需要查询ContentProvider数据集的特定记录(行),还需要知道该记录的ID的值.

构建查询

查询就是输入URI等参数,其中URI是必须的,其他是可选的,如果系统能找到URI对应的ContentProvider将返回一个Cursor对象.

可以通过ContentResolver.query()或者Activity.managedQuery()方法.

两者的方法参数完全一样,查询过程和返回值也是相同的.

区别是,通过Activity.managedQuery()方法,不但获取到Cursor对象,而且能够管理Cursor对象的生命周期.

比如当Activity暂停(pause)的时候,卸载该Cursor对象,当Activity Restart的时候重新查询.另外,也可以对一个没有处于Activity管理的Cursor对象做成被Activity管理的,通过调用Activity.startManaginCursor()方法.

类似这样:

Cursor cur = managedQuery(myPerson,null,null,null,null)

其中第一个参数myPerson是Uri类型实例.

如果需要查询的是指定行的记录,需要用_ID值,比如ID值为23,URI将是类似:

content://....../23

android提供了方便的方法,让开发者不需要自己拼接上面这样的URI,比如类似:

Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI,23)

或者:

Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI,"23")

二者的区别是一个接收整数类型的ID值,一个接收字符串类型.

其他几个参数:

names,可以为null,表示取数据集的全部列,或者声明一个String数组,数组中存放列名称,比如:People._ID.一般列名都在该ContentProvider中有常量对应

针对返回结果的过滤器,格式类似于SQL中的WHERE子句,区别是不带WHERE关键字,如果返回null表示不过滤,比如name=?

前面过滤器的参数,是String数组,是针对前面条件中?占位符的值

排序参数,类似SQL的ORDER BY字句,不过不需要写ORDER BY部分,比如name desc,如果不排序,可输入null.

返回值是Cursor对象,游标位置在第一条记录之前.

下面实例适用于android 2.0及以上版本,从android通讯录中得到姓名字段:

java代码:

Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null)

读取返回的数据

如果在查询的时候使用到ID,那么返回的数据只有一条记录.在其他情况下,一般会有多条记录.和JDBC的ResultSet类似,需要 *** 作游标遍历结果集,在每行,再通过列名获取到列的值,可以通过getString()、getInt()、getFloat()等方法获取值.

比如类似下面:

java代码:

while(cursor.moveToNext()) {

builder.append(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))).append("-")

}

和JDBC中不同,没有直接通过列名获取列值的方法,只能先列名获取到列的整型索引值,然后再通过该索引值定位获取列的值.

编辑数据

可以通过ContentProvider实现以下编辑功能:

增加新的记录:

在已经存在的记录中增加新的值、批量更新已经存在的多个记录、删除记录.

所有的编辑功能都是通过ContentResolver的方法实现.一些ContentProvider对权限要求更严格一些,需要写的权限,如果没有会报错.

增加记录

要想增加记录到ContentProvider,首先,要在ContentValues对象中设置类似map的键值对,在这里,键的值对应ContentProvider中的列的名字,键值对的值,是对应列希望的类型.

然后,调用ContentResolver.insert()方法,传入这个ContentValues对象,和对应ContentProvider的URI即可.返回值是这个新记录的URI对象.这样你可以通过这个URI获得包含这条记录的Cursor对象.

比如:

java代码:

ContentValues values = new ContentValues()

values.put(People.NAME,"Abraham Lincoln")

Uri uri = getContentResolver().insert(People.CONTENT_URI, values)

在原有记录上增加值

如果记录已经存在,可在记录上增加新的值,或者编辑已经存在的值.

首先要找到原来的值对象,然后要清除原有的值,然后像上面增加记录一样即可:

java代码:

Uri uri = Uri.withAppendedPath(People.CONTENT_URI, "23")

Uri phoneUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY)

values.clear()

values.put(People.Phones.TYPE, People.Phones.TYPE_MOBILE)

values.put(People.Phones.NUMBER, "1233214567")

getContentResolver().insert(phoneUri, values)

批量更新值

批量更新一组记录的值,比如NY改名为Eew York.可调用ContentResolver.update()方法.

删除记录

如果是删除单个记录,调用ContentResolver.delete()方法,URI参数,指定到具体行即可.

如果是删除多个记录,调用ContentResolver.delete()方法,URI参数指定Contentprovider即可,并带一个类似SQL的WHERE子句条件.这里和上面类似,不带WHERE关键字.

创建自己的ContentProvider

创建contentprovider,需要设置存储系统.大多数ContentProvider使用文件或者SQLite数据库,不过你可以用任何方式存储数据.android提供SQLiteOpenHelper帮助开发者创建和管理SQLiteDatabase.

继承ContentProvider,提供对数据的访问.在manifest文件中声明ContentProvider.继承ContentProvider类

必须定义ContentProvider类的子类,需要实现如下方法:

java代码:

query()

insert()

update()

delete()

getType()

onCreate()

在实现子类的时候,还有一些步骤可以简化ContentProvider客户端的使用:

定义public static final Uri常量,名称为CONTENT_URI:

java代码:

public static final Uri CONTENT_URI = Uri.parse("content://com.example.codelab.transportationprovider")

如果有多个表,它们也是使用相同的CONTENT_URI,只是它们的路径部分不同.

声明ContentProvider

创建ContentProvider后,需要在manifest文件中声明,android系统才能知道它,当其他应用需要调用该ContentProvider时才能创建或者调用它.

语法类似:

<provider android:name="com.easymorse.cp.MyContentProvider"

android:authorities="com.easymorse.cp.mycp">

</provider>

android:name要写ContentProvider继承类的全名.

android:authorities要写和CONTENT_URI常量的B部分

转载,仅供参考,祝你愉快,满意请采纳。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11195392.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存