学习笔记(补):通过ContentProvider底层实现来讲解应用程序

非常抱歉,由于昨天晚上难得在腾讯公开课上了一节UI的课,导致我后来整理笔记到凌晨,因为太晚了就没有公开Evernote的学习笔记,今天上午在公司暂时没事,就补上。
       在笔记前,先说点题外话,我的笔记是同时分享在开源中国,CSDN,ITEYE还有QQ空间的,目的也是为了和有兴趣并且志同道合的朋友一起进行Android开发的学习,在CSDN上有朋友看了我上传的手写的笔记代码图片问我为什么开发还要把源码记录在本子上,还要这样写笔记?所以我也先分享下我的学习经验,至少目前我觉得自己的学习方式对自己技能的掌握是比较深刻的。我学习开发的时候是通过一些帮助视频和买的一本美版翻译的<<Android权威指南>>进行学习的,因为已经有了三年的J2EE开发经验,所以入门也比较快,拿笔记录源代码的好处有两点,清晰的笔记代码在本子上你可以随时拿出来翻阅,因为是自己记的,所以一看到这些代码,大脑里很快就会联想到当时记录的一些情景,并且能较好的回忆出代码的具体实现,必须也基于这些代码同时你曾经已经在电脑上敲出并调试成功过。这样当你在以后的开发中遇到知识点的一些问题,回过头翻阅笔记时就能迅速的解决问题。至于在公开的社区和空间博客记录笔记的目的有三点:开源社区是国内最大的程序员平台,包括CSDN,ITEYE都是比较好的技术交流平台,在这里发表学习日志可以和一些正在学习的人分享学习心得,也可以让牛人帮助指出技术缺陷。在前天学习Adapter的时候有一个数据适配器帮助类:SimpleAdapter,在使用时遇到了无法解决的BUG,后来也是通过开源社区的朋友才了解了这个数据适配器本身存在的问题,所以笔记中也未提及这个数据适配器,因为不推荐使用。再者是为了训练自己的语言组织能力,一直以来都感觉自己的不太擅长交际,在与不熟的人聊天时也发现语言组织能力薄弱,所以通过整理分享自己的学习笔记,再结合平时多与人打交道来磨练自己。最后一点就是对于学习,我自身在学习时发现有这么一个现象:我跟着帮助书籍和资料完成了一个技术的攻破,但是如果我不能自己表达出来是怎么解决的?为什么要这样解决?那么到时遇到同样的问题时我还是不能独立去解决,还是一筹莫展(主要是对于一些很难得用到和很底层的技术)所以我想通过笔记的整理和分析讲解来试着消化这些知识。OK!就讲这么些。
        今天的笔记内容是来讲解下列如一些什么360手机助手啊,各种通讯录应用啊,还有短信备份助手等等是如何去访问我们手机中的这些私密信息从而操作我们的这些内容(短信,联系人信息)。----因为今天笔记的内容涉及到安卓开发的一个很重要的组件:ContentProvider,所以这里我会详细介绍。
        还记得我的笔记开篇讲的SQLite移动嵌入式数据库么?在我们的手机中不同的应用程序都有很多这种数据库db文件,像在手机的telephor应用程序数据目录下就有很多db文件:
学习笔记(补):通过ContentProvider底层实现来讲解应用程序_第1张图片在我们的应用程序中这些文件都是私有的,可以在Permissions权限节点下可以看到这些文件的权限为-rw-rw----(这里给不熟或者忘记了Linux技术的人补一下Linux的小知识-安卓系统本身就是一个Linux系统:这个代码代表的是linux下的文件权限格式,用十位字符来标识,第一位代表是文件还是目录,-代表文件,1-3位代表当前用户的权限,r(read)代表可读,w(write)代表可写,4-6位代表当前用户所在的组(一般情况下,安卓下的每个应用程序都是一个独立的组),7-9位代表其它用户)所以我们从这个权限代码可以看到,只有本应用程序自己才能访问进行操作,别的程序是无法对其进行任何操作的。但是Google工程师为了给其它应用程序提供方便,所以开发了这么一个方法去允许其它应用程序通过一定途径去对这些信息进行访问。这玩意就是我们今天的笔记内容:内容提供者(ContentProvider),我举一个形象的比喻(自己瞎掰的,不形象的话勿喷啊!为此我还特地百度了一些股票内容的名词解释,多有诚意啊!...):有一个人叫小明,他是买股票的,我们假设这支股票的公司就是一个应用程序。小明想去知道这支股票的内幕消息,当然股票公司肯定不可能直接告诉小明,所以股票公司就把信息(这些信息就代表这个应用程序的私有文件)透露给这家公司高层的大姨妈,然后给大姨妈一个暗号,小明就通过找到大姨妈对暗号,对上了,大姨妈就把股票公司高层提供的信息透露给小明。嗯!就是这个原理!
    内容提供者 
ContentProvider的作用就是用来把应用程序本身的私有的数据给暴露出来,原理在上面讲完了,现在讲程序是怎么创建自己的内容提供者的:
    要想创建这个应用程序的内容提供者,在里面定义一些外部程序可以进行的操作,那么首先我们需要创建这个类并且必须继承这个 
ContentProvider类,继承这个类后,我们可以看到他需要重写继承类的几个方法,包括:onCreate(),query(...),getType(...),insert(...),delete(...),update(...),从这些方法名字我们可以明显的看出这些方法应该是进行CRUD操作的,在创建完这个类后我们还需要在AndroidManifest.xml清单文件中配置这个组件<provider>,这个标签是用了申请那些继承了ContentProvider的类,在<provider>中有两个属性需要必填:一个是name,这个代表我们自己创建的内容提供者类的全路径地址;第二个是authorities,这个是我们自定义的这个内容提供者的主机名(相当与一个请求路径,其它程序的方法格式就是content://主机名/匹配规则 (匹配规则下面会将)),这两个属性是必填的,还有一个属性<permission>,这个是用来配置需要访问这个内容提供者需要给哪些权限,只有其它应用程序获得手机给予的这些权限才能进行访问:所以我们在安装完一个应用程序后,开启时,应用程序同城会请求获得联系人信息啊,GPS信息啊,手机短信信息的权限,有些流氓软件就会不经过我们的授权,自己就后台去授权了这些权限,获取了手机的私密信息.配置完清单文件后,我们就需要在内容提供者类中去自己写匹配规则和操作逻辑了:
首先我们需要定义一个uri的匹配器,然后添加一组匹配规则:
private static UriMatcher matcher = new  
UriMatcher (UriMatcher.NO_MATCH);后面的参数代表如果没有匹配到,返回一个 -1
static{
    matcher.addURI("清单文件中定义的主机名","query",1);为了方便解释,代码就不规范写了,其实最后一个参数的规范写法应该去定义一个静态int常量,然后再这里写常量名的.里面这些参数中第一个参数为你在清单文件<
provider>节点中对应该类名起的那个主机名,第二个参数是就是之前提到过的匹配规则,来知道其它应用程序访问这个主机名需要做什么,其它应用程序访问匹配这个操作的请求就是content://主机名/query,第三个参数就是访问这个请求匹配成功后返回的值为1.下面的匹配规则同理.
    
matcher.addURI("清单文件中定义的主机名","insert",2);
    matcher.addURI("清单文件中定义的主机名","update",3);
    matcher.addURI("清单文件中定义的主机名","insert",4);
 


定义完这个匹配器和匹配规则后,我们就需要在方法中去解析其它应用程序访问这个内容提供者的uri是否匹配,并进行什么操作了:
先讲一下onCreate()这个方法,这个方法是在内容提供者被开启时就执行的方法,一般我们要操作SQLite数据库进行数据的读取的话,就把SQLite数据库帮助类,比如我们在前面笔记中创建的PersonSQLiteOpenHelper给进行初始化.
得到了helper后我们就可以在
CRUD 的其它方法中直接进行SQLite的操作了,我们就拿query查询方法举例了,其它的方法操作同理
在query方法中,我们需要传其它应用程序的访问uri,还有一些查询的字段条件等,我们首先判断下传进来的uri是否和我们上面定义的query匹配规则中成功的返回值1相同,,可以使用匹配器提供的这个方法进行匹配:
if(matcher.match(uri)  == 1){
    以上条件中的方法就是判断传进来的uri是否成功的和我们定义的匹配规则匹配,我们之前定义了如果query的uri匹配成功的话返回值为1,所以满足这个条件即可执行这边代码
}else{
    不满足就提示匹配失败,无法进行操作!
}
 以上就完成了一个应用程序的内容提供者的创建过程,是不是很简单啊!
       接下来讲一下其它应用程序是怎么访问这个应用程序的内容提供者的:
    Google工程师既然提供了应用程序的内容提供器的创建,必定也提供了其它程序访问这个内容提供器的类,在其它应用程序中,我们通过:
ContentResolver resolver = getContentResolver()去得到内容提供者的,
    我们知道了应用程序的uri匹配规则后就可以进行访问了,比如上面应用程序创建的内容提供者,我们要去读取他的一些数据:
Uri uri = Uri,parse("content://上个应用程序定义的主机名/query");
然后执行resolver.query(uri,....);即可调用该内容提供者的query方法,并将我们给的uri和查询字段条件穿传进去,如果uri和内容提供者中的匹配,即可返回数据.
    OK内容提供者的创建和别的应用程序通过内容提供者获取数据的方式已经全部操作完成.
    从而我们可以得知,其它应用程序获得系统短信,获得联系人,就是获得授权后访问了手机电话程序中的内容提供者的方法才取到的这些私有信息.这个方法同样在我们在GITHUB中的远程团队现阶段开发的开源APP,追踪者中有实际运用,就是通过授权运用GPS的内容追踪者获取手机本机上传的GPS信息当前坐标位置,然后上传到云数据库,然后其它人通过读取云数据库的内容获得你的当前位置,非常简单
    OK,今天的笔记写完了,写了上午小半天...中午可以睡一下了....多谢阅读,也授权大家复制转载!


你可能感兴趣的:(学习笔记(补):通过ContentProvider底层实现来讲解应用程序)