內容提供者、內容解析者和內容觀察者
一、Linux文件權限
Linxu下的用戶分
- u所有者
- g所屬組
- o其他用戶
Linux下文件權限
- r讀
- w寫
- x執行
文件權限表示
文件類型(1位)+所有者權限(3位)+所屬組權限(3位)+其他用戶權限(3位),如圖:
文件 權限 說明 d lrwxrwxrwx l表示是鏈接,鏈接到sys/kernel/debug,所有者、所屬組和其他用戶都有讀寫執行權限 data drwxrwx–x d表示是一個文件夾,rwx表示所有者具有讀寫執行權限,第二個rwx表示所屬組具有讀寫執行權限,第三個–x表示其他用戶只有執行權限 default.prop -rw-r–r– -表示是一個文件,rw-表示所有者具有讀寫權限,r–表示所屬組和其他用戶都只具備讀權限
默認地,每一個應用程序被分配一個唯一的Linux用戶ID和組ID。通過設置權限許可,應用程序的文件只對該用戶可見,只對應用程序本身可見。
文件權限的存在,保證了數據的安全性。當我們要讀取數據時就需要具備相應的讀寫權限。比如當另一個應用想要獲取短信應用的就需要在清單文件裏添加相應的權限。底層是使用了Binder機制和匿名共享內存。
- 文件權限的存在,保證了數據的安全性。當我們要讀取數據時就需要具備相應的讀寫權限。比如當另一個應用想要獲取短信應用的就需要在清單文件裏添加相應的權限。
二、內容提供者(ContentProvider)
1. 作用
暴露本應用的私有數據,供其它應用使用。通過繼承ContentProvider,有選擇地暴露插入、刪除、修改和查詢本應用數據的接口。
2. 使用
繼承ContentProvider抽象類,並選擇性地重新增刪改查方法
需要在清單文件中配置
<application ...> <provider android:name="com.example.provider.SMSProvider" android:authorities="mysms"></provider> ... </application>
設置Uri(資源索引)並靜態初始化UriMatcher幫助進行Uri匹配
- Uri格式
- Uri=schema://authorites/path/id
- content://包名.數據庫/表名/字段id
- UriMatcher 的方法
/** * 功能:Creates the root node of the URI tree.(創建URI樹的根節點) * 參數code: the code to match for the root URI(匹配根URI的碼) */ UriMatcher(int code); /** *功能:Add a URI to match, and the code to return when this URI is matched.(添加一個uri用於匹配,並當匹配時返回設置的code) * 參數authority: 要匹配的authority * 參數path: 要匹配的path。*表示匹配任意文本,#表示匹配數字 * 參數code: 當uri與給定的匹配時的返回值,必須是正數 */ addURI(String authority, String path, int code) ; /** *功能:Try to match against the path in a url.(嘗試去匹配url中的路徑) * uri:要進行匹配的uri * 返回值:int,匹配時返回預設的code;不匹配時返回-1 */ match(Uri uri);
- Uri格式
重寫增刪查改方法(以查詢爲例)
/** * 功能:處理客戶端的請求 * 參數uri:要查詢的uri * 參數projection:要查詢的字段集合 * 參數selection:from語句 * 參數selectionArgs:from語句的參數 * 參數sortOrder:orderby語句 * 返回值:Cursor,結果集的遊標 */ query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
在方法中進行Uri匹配,匹配時才執行增刪查改
三、內容解析者(ContentResolver)
1. 作用
訪問內容提供者,並解析返回的數據
2. 使用
通過上下文對象獲取內容解析者
ContentResolver resolver = this.getContentResolver();
發出增刪查改請求
Cursor cursor = resolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
解析cursor獲取數據
- 當uri不匹配時,cursor會爲null,需要捕獲異常;
- 當
cursor.getCount() > 0
時纔有必要進一步獲取數據; - 在finally中關閉cursor,並注意進行cursor非空判斷。
3. 實例:讀取系統短信
短信數據庫
/data/data/com.android.providers.telephony/database/mmssms.dbsms表中常用字段說明
- type:表示發送還是接收,2表示發送,1表示接收,6表示正在發送中
- data:時間的毫秒值
- person:聯繫人姓名(陌生人爲null)
- address:發送或接收到號碼
- body:發送或接收的內容
- read:是否閱讀
相關協議
- content://sms/inbox 收件箱
- content://sms/sent 已發送
- content://sms/draft 草稿
- content://sms/outbox 發件箱
- content://sms/failed 發送失敗
- content://sms/queued 待發送列表
四、內容觀察者(ContentObserver)
1. 作用
配合內容解析者,實時監聽內容提供者共享的數據是否發生變化
通知機制:handler機制
2. 使用
2.1 內容提供者方
獲取內容解析器並通過觀察者的url通知觀察者改變的發生
ContentResolver cr = getContext().getContentResolver(); cr.notifyChange(uri, null);//注意:即使觀察者不在運行狀態,通過這個方法可以喚醒觀察者
實例:系統自帶的短信提供者(SmsProvider)
public class SmsProvider extends ContentProvider{ ... @Override public Uri insert(Uri url, ContentValues initialValues) { if (rowID > 0) { Uri uri = Uri.parse("content://" + table + "/" + rowID); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.d(TAG, "insert " + uri + " succeeded"); } notifyChange(uri); return uri; } else { Log.e(TAG,"insert: failed! " + values.toString()); } return null; } ... private void notifyChange(Uri uri) { ContentResolver cr = getContext().getContentResolver(); cr.notifyChange(uri, null); cr.notifyChange(MmsSms.CONTENT_URI, null); cr.notifyChange(Uri.parse("content://mms-sms/conversations/"), null); } ... }
2.2 內容觀察者方
獲取內容解析器並註冊觀察者
/** * 功能:ContentResolver的方法,註冊一個ContentObserver,當指定uri數據改變時會回調給observer * 參數uri:要監聽的uri * 參數notifyForDescendents:爲false 表示精確匹配,即只匹配該Uri,爲true 表示可以同時匹配其派生的Uri * 參數observer:ContentObserver派生的監聽器實例 */ public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)
ContentResolver resovler = getContentResolver(); Uri uri = Uri.parse("content://com.example.db/table"); resovler.registerContentObserver(uri, false, new MyObserver(new Handler()));
寫ContentObserver派生的監聽器實例並重寫onChange方法,當得知改變將執行裏面的代碼
private class MyObserver extends ContentObserver { public MyObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { System.out.println("我是觀察者,我觀察到了內容的變化...."); super.onChange(selfChange); } }
練習:
- 做一個短信監控器
- 做一個相對完整的短信應用