前言:随着工作的时间越来越长,越来越觉得自己学知识的速度太慢,原定的两年,现在已经过了快九个月了,仍然对很多知识懵懵懂懂,对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在Web應用中的主要作用是存儲和管理數據。 1.MySQL高效處理用戶信息、產品目錄和交易記錄等數據。 2.通過SQL查詢,開發者能從數據庫提取信息生成動態內容。 3.MySQL基於客戶端-服務器模型工作,確保查詢速度可接受。

構建MySQL數據庫的步驟包括:1.創建數據庫和表,2.插入數據,3.進行查詢。首先,使用CREATEDATABASE和CREATETABLE語句創建數據庫和表,然後用INSERTINTO語句插入數據,最後用SELECT語句查詢數據。

MySQL適合初學者,因為它易用且功能強大。 1.MySQL是關係型數據庫,使用SQL進行CRUD操作。 2.安裝簡單,需配置root用戶密碼。 3.使用INSERT、UPDATE、DELETE、SELECT進行數據操作。 4.複雜查詢可使用ORDERBY、WHERE和JOIN。 5.調試需檢查語法,使用EXPLAIN分析查詢。 6.優化建議包括使用索引、選擇合適數據類型和良好編程習慣。

MySQL適合初學者,因為:1)易於安裝和配置,2)有豐富的學習資源,3)SQL語法直觀,4)工具支持強大。儘管如此,初學者需克服數據庫設計、查詢優化、安全管理和數據備份等挑戰。

是的,sqlisaprogramminglanguges pecialized fordatamanage.1)它具有焦點,focusingonwhattoachieveratherthanhow.2)sqlisessential forquerying forquerying,插入,更新,更新,和detletingdatainrelationalDatabases.3)

ACID屬性包括原子性、一致性、隔離性和持久性,是數據庫設計的基石。 1.原子性確保事務要么完全成功,要么完全失敗。 2.一致性保證數據庫在事務前後保持一致狀態。 3.隔離性確保事務之間互不干擾。 4.持久性確保事務提交後數據永久保存。

MySQL既是數據庫管理系統(DBMS),也與編程語言緊密相關。 1)作為DBMS,MySQL用於存儲、組織和檢索數據,優化索引可提高查詢性能。 2)通過SQL與編程語言結合,嵌入在如Python中,使用ORM工具如SQLAlchemy可簡化操作。 3)性能優化包括索引、查詢、緩存、分庫分錶和事務管理。

MySQL使用SQL命令管理數據。 1.基本命令包括SELECT、INSERT、UPDATE和DELETE。 2.高級用法涉及JOIN、子查詢和聚合函數。 3.常見錯誤有語法、邏輯和性能問題。 4.優化技巧包括使用索引、避免SELECT*和使用LIMIT。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

禪工作室 13.0.1
強大的PHP整合開發環境

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

WebStorm Mac版
好用的JavaScript開發工具