第5节 ContentProvider的使用权限
ContentProvider
可以被其他应用使用(就像一个公共网站,可以被任何人访问);也可以被设置成只被自己所在的应用使用(就像一个内部网站,只能在公司内部访问)。
这只需要在应用的AndroidManifest.xml
文件中,给ContentProvider
设置上android:exported
属性,
<provider
android:name=".MyContentProvider"
android:authorities="com.anddle.mycontentprovider"
android:enabled="true"
android:exported="true" />
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" />
- 在
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
的值。
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>
其中,<uses-permission/>
标签中设置的android:name
的值,就是应用A中对外声明的那个provider
的权限值。
5.3 进一步的权限设置
应用A的ContentProvider
还可以将访问的权限进一步细化,分成允许读取和允许写入两种。
如果应用B只需要读取数据,就单独申请读取的权限;如果应用C只需要写入数据,就单独申请写入的权限;
- 声明“只能读取”权限,
<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>
- 声明“只能写入”权限,
<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>
需要注意的是,android:writePermission
与android:readPermission
权限的优先级比android:permission
的优先级高,只要设置了高优先级的,那么其他应用要使用高优先级的功能,就要声明高优先级的权限。
例如,一个ContentProvider
同时设置了android:readPermission
和android:permission
权限,第三方应用如果只请求了android:permission
权限,是没有办法进行读取操作的。
/*******************************************************************/
* 版权声明
* 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。
/*******************************************************************/
第6节 ContentProvider的监听
当ContentProvider
中存储的数据内容发生变化时,是可以被关注了这些消息的查询者监听到的。
6.1 调用者监听的方法
- 继承
ContentObserver
,创建监听器类,public class MyObserver extends ContentObserver { public MyObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); //添加变化的处理逻辑 } }
- 注册对指定Uri的监听函数,一旦该Uri指向的内容发生改变,将通知到
MyObserver
,mContentObserver = new MyObserver(new Handler()); ContentResolver cr = getContentResolver(); cr.registerContentObserver(MyContentProvider.CONTENT_BOOKS_URI, true, mContentObserver);
- 当程序退出或者不需要再监听Uri的变化时,要主动取消对Uri的监听,
ContentResolver cr = getContentResolver(); cr.unregisterContentObserver(mContentObserver);
6.2 ContentProvider的配合
在ContentProvider
里,每当特定Uri上的数据发生变化,要触发对调用者对通知。通知使用ContentResolver
的notifyChange()
方法触发,
@Override
public Uri insert(Uri uri, ContentValues values) {
Uri result = null;?
switch (sUriMatcher.match(uri)) {
case BOOKS: {
SQLiteDatabase db = mDBHelper.getWritableDatabase();
long id = db.insert(DBHelper.TABLE_NAME, null, values);
if(id > 0) {
result = ContentUris.withAppendedId(CONTENT_BOOKS_URI, id);
getContext().getContentResolver().notifyChange(uri, null);
}
}
break;
......
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return result;
}