前言:随着工作的时间越来越长,越来越觉得自己学知识的速度太慢,原定的两年,现在已经过了快九个月了,仍然对很多知识懵懵懂懂,对JAVA理解的还是不够彻底,现在终于有点时间能放纵地看一些自己感兴趣的东西了,不知道这样的时间能持续多久,但抓住每一分
前言:随着工作的时间越来越长,越来越觉得自己学知识的速度太慢,原定的两年,现在已经过了快九个月了,仍然对很多知识懵懵懂懂,对JAVA理解的还是不够彻底,现在终于有点时间能放纵地看一些自己感兴趣的东西了,不知道这样的时间能持续多久,但抓住每一分能利用的时间把自己变得强大,终有一天,你会成为你想成为的人。记住,你永远是最棒的!
1、《ContentProvider数据库共享之——概述》
2、《ContentProvider数据库共享之——实例讲解》
3、《ContentProvider数据库共享之——MIME类型与getType()》
4、《ContentProvider数据库共享之——读写权限与数据监听》
经过前面三篇文章,我想大家对ContentProvider已经有了大部分的了解,但在第二篇中,我们提到过一个函数:
getContentResolver().notifyChange(uri, null);这个函数是在数据库中数据有变更我时候用来通知第三方应用的,这篇就带领大家看看有关数据库变更通知与第三方监听有关的东东;
在这之前,还有个ContentProvider共享数据库读写权限的知识 给大家补上;
一、数据库读写权限
1、概述
先看下面这段代码:
<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>在这段代码中有几个参数要特别注意一下:
- exported:这个属性用于指示该服务是否能被其他程序应用组件调用或跟他交互; 取值为(true | false),如果设置成true,则能够被调用或交互,否则不能;设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。具体参见:《Permission Denial: opening provider 隐藏的android:exported属性的含义》
-
readPermission:使用Content Provider的查询功能所必需的权限,即使用ContentProvider里的query()函数的权限;
-
writePermission:使用ContentProvider的修改功能所必须的权限,即使用ContentProvider的insert()、update()、delete()函数的权限;
-
permission:客户端读、写 Content Provider 中的数据所必需的权限名称。 本属性为一次性设置读和写权限提供了快捷途径。 不过,readPermission和writePermission属性优先于本设置。 如果同时设置了readPermission属性,则其将控制对 Content Provider 的读取。 如果设置了writePermission属性,则其也将控制对 Content Provider 数据的修改。也就是说如果只设置permission权限,那么拥有这个权限的应用就可以实现对这里的ContentProvider进行读写;如果同时设置了permission和readPermission那么具有readPermission权限的应用才可以读,拥有permission权限的才能写!也就是说只拥有permission权限是不能读的,因为readPermission的优先级要高于permission;如果同时设置了readPermission、writePermission、permission那么permission就无效了。
2、实例
(1)有关自定义权限
<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>有关自定义权限的内容,请参考《声明、使用与自定义权限》
(2)、带有权限的ContentProvder实例
首先在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中,我们这里同时使用读、写权限:
<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中,仅添加读共享数据库的权限,那第三方应该怎么申请权限才能读写数据库呢?
<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>
(3)、效果:
在实例代码中,在provider中添加了读写权限,但在第三方APP:UseProvider中,仅添加了读权限,所以在利用URI来读共享数据库的时候结果是正常的,但在写数据库时,就会抛出permission-denied错误,如果不用try...catch...捕捉,就会造成crash;结果截图如下:
- query()操作
- insert()、delete() 或 update()操作时,就会抛出异常
源码在文章底部给出。
二、数据监听
1、监听步骤
要监听指定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往下看
(2)、注册和反注册监听
- 注册
在使用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()的参数
- 在OnDestory()时,反注册:
@Override protected void onDestroy() { super.onDestroy(); //取消监听 getContentResolver().unregisterContentObserver(observer); }(3)、在ContentProvider中数据库变动通知
在ContentProvider中指定URI上有数据库数据变动时,及时利用下面的函数来通知
getContext().getContentResolver().notifyChange(uri, null);这个函数就是在第二篇中,我们提到的通知函数;
好了,到这数据库变动通知和监听的过程就讲完了,下面看看registerContentObserver()注册监听函数的用法:
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)功能:为指定的Uri注册一个ContentObserver派生类实例,当**给定**的Uri发生改变时,回调该实例对象去处理。
参数:
- uri : 需要观察的Uri
- notifyForDescendents: 为false 表示精确匹配,即只匹配该Uri; 为true 表示可以同时匹配其派生的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的数据库变化。
- observer: ContentObserver的派生类实例
2、结果
在数据库改变时,收到消息如图所示:
好了,这到就结束了,有关ContentProvider的用法也都讲完了;
源码在文章最底部
三、补充:SetProjectionMap——投影映射
在上面的实例中,我们对外提供的数据库列名和内部使用的是一样的,但这样很容易被对方知道我们的数据库结构,那要想自己本地使用一套列名,给外部提供另一套对应的列名,这样别人不就猜不出我们的列名了么,针对这个问题,在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 谢谢!

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于索引优化器工作原理的相关内容,其中包括了MySQL Server的组成,MySQL优化器选择索引额原理以及SQL成本分析,最后通过 select 查询总结整个查询过程,下面一起来看一下,希望对大家有帮助。

sybase是基于客户/服务器体系结构的数据库,是一个开放的、高性能的、可编程的数据库,可使用事件驱动的触发器、多线索化等来提高性能。

visual foxpro数据库文件是管理数据库对象的系统文件。在VFP中,用户数据是存放在“.DBF”表文件中;VFP的数据库文件(“.DBC”)中不存放用户数据,它只起将属于某一数据库的 数据库表与视图、连接、存储过程等关联起来的作用。

数据库系统由4个部分构成:1、数据库,是指长期存储在计算机内的,有组织,可共享的数据的集合;2、硬件,是指构成计算机系统的各种物理设备,包括存储所需的外部设备;3、软件,包括操作系统、数据库管理系统及应用程序;4、人员,包括系统分析员和数据库设计人员、应用程序员(负责编写使用数据库的应用程序)、最终用户(利用接口或查询语言访问数据库)、数据库管理员(负责数据库的总体信息控制)。

microsoft sql server是Microsoft公司推出的关系型数据库管理系统,是一个全面的数据库平台,使用集成的商业智能(BI)工具提供了企业级的数据管理,具有使用方便可伸缩性好与相关软件集成程度高等优点。SQL Server数据库引擎为关系型数据和结构化数据提供了更安全可靠的存储功能,使用户可以构建和管理用于业务的高可用和高性能的数据应用程序。

go语言可以写数据库。Go语言和其他语言不同的地方是,Go官方没有提供数据库驱动,而是编写了开发数据库驱动的标准接口,开发者可以根据定义的接口来开发相应的数据库驱动;这样做的好处在于,只要是按照标准接口开发的代码,以后迁移数据库时,不需要做任何修改,极大方便了后期的架构调整。

数据库的“完整性”是指数据的正确性和相容性。完整性是指数据库中数据在逻辑上的一致性、正确性、有效性和相容性。完整性对于数据库系统的重要性:1、数据库完整性约束能够防止合法用户使用数据库时向数据库中添加不合语义的数据;2、合理的数据库完整性设计,能够同时兼顾数据库的完整性和系统的效能;3、完善的数据库完整性有助于尽早发现应用软件的错误。

mysql查询为什么会慢,关于这个问题,在实际开发经常会遇到,而面试中,也是个高频题。遇到这种问题,我们一般也会想到是因为索引。那除开索引之外,还有哪些因素会导致数据库查询变慢呢?


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver CS6
Visual web development tools

SublimeText3 Linux new version
SublimeText3 Linux latest version

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),
