Rumah > Artikel > pangkalan data > ContentProvider数据库共享之读写权限与数据监听
前言:随着工作的时间越来越长,越来越觉得自己学知识的速度太慢,原定的两年,现在已经过了快九个月了,仍然对很多知识懵懵懂懂,对JAVA理解的还是不够彻底,现在终于有点时间能放纵地看一些自己感兴趣的东西了,不知道这样的时间能持续多久,但抓住每一分
前言:随着工作的时间越来越长,越来越觉得自己学知识的速度太慢,原定的两年,现在已经过了快九个月了,仍然对很多知识懵懵懂懂,对JAVA理解的还是不够彻底,现在终于有点时间能放纵地看一些自己感兴趣的东西了,不知道这样的时间能持续多久,但抓住每一分能利用的时间把自己变得强大,终有一天,你会成为你想成为的人。记住,你永远是最棒的!
1、《ContentProvider数据库共享之——概述》
2、《ContentProvider数据库共享之——实例讲解》
3、《ContentProvider数据库共享之——MIME类型与getType()》
4、《ContentProvider数据库共享之——读写权限与数据监听》
经过前面三篇文章,我想大家对ContentProvider已经有了大部分的了解,但在第二篇中,我们提到过一个函数:
getContentResolver().notifyChange(uri, null);这个函数是在数据库中数据有变更我时候用来通知第三方应用的,这篇就带领大家看看有关数据库变更通知与第三方监听有关的东东;
先看下面这段代码:
<provider android:name=".PeopleContentProvider" android:authorities="com.harvic.provider.PeopleContentProvider" android:exported="true" android:permission="com.harvic.contentProviderBlog" android:readpermission="com.harvic.contentProviderBlog.read" android:writepermission="com.harvic.cotentProviderBlog.write"></provider>在这段代码中有几个参数要特别注意一下:
<provider android:name=".PeopleContentProvider" android:authorities="com.harvic.provider.PeopleContentProvider" android:exported="true" android:readpermission="com.harvic.contentProviderBlog.read"></provider>比如,在这里我们定义一个readPermission字符串,单纯写一个字符串是毫无意义的,因为根本系统的任何权限都是要申请的,没有申请过的一串String代表的字符串系统根本无法识别,也就是说谁进来都会被挡在外面!
<permission android:name="com.harvic.contentProviderBlog.read" android:label="provider pomission" android:protectionlevel="normal"></permission>这样,我们的permission才会在系统中注册,在第三方应用中使用
<uses-permission android:name="com.harvic.contentProviderBlog.read"></uses-permission>有关自定义权限的内容,请参考《声明、使用与自定义权限》
首先在ContentProviderBlog中首先向系统申请两个权限:
分别对应读数据库权限和写数据库权限
<permission android:name="com.harvic.contentProviderBlog.read" android:label="provider read pomission" android:protectionlevel="normal"></permission> <permission android:name="com.harvic.contentProviderBlog.write" android:label="provider write pomission" android:protectionlevel="normal"></permission>情况一:使用读写权限
<provider android:name=".PeopleContentProvider" android:authorities="com.harvic.provider.PeopleContentProvider" android:exported="true" android:readpermission="com.harvic.contentProviderBlog.read" android:writepermission="com.harvic.cotentProviderBlog.write"></provider>在这种情况下,使用第三方应用同时申请使用这两个权限才可以对数据库读写,即:
<uses-permission android:name="com.harvic.contentProviderBlog.read"></uses-permission>情况二:仅添加读权限
<provider android:name=".PeopleContentProvider" android:authorities="com.harvic.provider.PeopleContentProvider" android:exported="true" android:readpermission="com.harvic.contentProviderBlog.read"></provider>从上面可以看到,我们只添加了readPermission,那第三方应用在不申请任何权限的情况下是可以写数据库,但当读数据库时就需要权限了;即如果要读数据库需要添加如下使用权限声明:
<uses-permission android:name="com.harvic.contentProviderBlog.read"></uses-permission>
在实例代码中,在provider中添加了读写权限,但在第三方APP:UseProvider中,仅添加了读权限,所以在利用URI来读共享数据库的时候结果是正常的,但在写数据库时,就会抛出permission-denied错误,如果不用try...catch...捕捉,就会造成crash;结果截图如下:
源码在文章底部给出。
要监听指定URI上的数据库变化,在监听方需要两步:
(1)、生成一个类派生自ContentObserver
public class DataBaseObserver extends ContentObserver { public DataBaseObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.d("harvic","received first database changed"); } }注意这里会自动生成一个onChange()方法,当有改变到来时就会跑到onChange()里,所以我们在这里面打一个LOG,注意LOG内容:“received first database changed”,很明显这里我只用DataBaseObserver来监听"content://com.harvic.provider.PeopleContentProvider/frist "所对应的数据库进行监听,至于如何指定URI往下看
在使用URI来操作第三方数据之前,先进行ContentObserver注册,这里我们在MainActivity的OnCreate()函数里注册:
private DataBaseObserver observer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); observer = new DataBaseObserver(new Handler()); //注册指定URI 变动监听 getContentResolver().registerContentObserver(CONTENT_URI_FIRST,true,observer); }这里先完整说完流程,等下再讲registerContentObserver()的参数
@Override protected void onDestroy() { super.onDestroy(); //取消监听 getContentResolver().unregisterContentObserver(observer); }(3)、在ContentProvider中数据库变动通知
getContext().getContentResolver().notifyChange(uri, null);这个函数就是在第二篇中,我们提到的通知函数;
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)功能:为指定的Uri注册一个ContentObserver派生类实例,当**给定**的Uri发生改变时,回调该实例对象去处理。
举例如下:假设UriMatcher 里注册的Uri共有一下类型:
1、content://com.qin.cb/student (学生)
2、content://com.qin.cb/student/#
3、content://com.qin.cb/student/schoolchild(小学生,派生的Uri)
假设我们当前需要观察的Uri为content://com.qin.cb/student,如果发生数据变化的 Uri 为 content://com.qin.cb/student/schoolchild;那么当notifyForDescendents为 false,那么该ContentObserver会监听不到, 但是当notifyForDescendents 为ture,能捕捉该Uri的数据库变化。
在数据库改变时,收到消息如图所示:
好了,这到就结束了,有关ContentProvider的用法也都讲完了;
源码在文章最底部
在上面的实例中,我们对外提供的数据库列名和内部使用的是一样的,但这样很容易被对方知道我们的数据库结构,那要想自己本地使用一套列名,给外部提供另一套对应的列名,这样别人不就猜不出我们的列名了么,针对这个问题,在SQLiteQueryBuilder类中,为我们提供了内外部列名映射函数,以允许我们在外部和内部列名不同时的提供映射功能。
主要使用的函数是setProjectionMap(HashMap map)
使用方法如下:
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); Map projectionMap = new HashMap<string>(); projectionMap.put("out_column_name_1","inside_column_name_1"); projectionMap.put("out_column_name_2","inside_column_name_2"); projectionMap.put("out_column_name_3","inside_column_name_3"); queryBuilder.setTables(DatabaseHelper.TABLE_FIRST_NAME); queryBuilder.setProjectionMap(projectionMap);</string>
由于是事后补充的知识,在这里就再给大家提供例子参考了,大家可以自己尝试下。
感谢下面这些精彩的文章给了我参考的资料和灵感:
1、《android ContentProvider使用详解》(很棒)
2、《android之ContentProvider和Uri详解》
3、《Android突破笔记五:ContentProvider和Uri详解》
4、《自定义ContentProvider的一些细节探究》
5、《android ContentResolver详解》
6、《对android中MIME类型以及contentprovidergetType()方法的理解》
7、《ContentProvider中getType(Uri uri)用法及理解》
8、《是否需要覆盖ContentProvider的getType方法?》
9、《对ContentProvider中getType(Uri uri)和android.intent.category.DEFAULT的理解》 (很棒)
10、《ContentProvider中gettype() 和MIME类型的理解》
11、《监测database的改变--notifyChange》
12、《Android 监听ContentProvider中数据的变化》
13、《Android监听数据库的值改变与否》
14、《Permission Denial: opening provider 隐藏的android:exported属性的含义》
15、《Content Provider的权限 》
源码来了,源码内容:
1、第一部分:数据库读写权限
2、第二部分:数据监听(把读写权限代码删除,只有监听相关的代码)
如果本文有帮到你,记得关注哦;
源码下载地址:http://download.csdn.net/detail/harvic880925/8535963
http://blog.csdn.net/harvic880925/article/details/44651967 谢谢!