內容提供者ContentProvider
與前文的界面Activity
、服務Service
、廣播接收者BroadcastReveiver
,並列稱為Android的四大組件,均是需要自定義子類繼承上述組件類,並在清單文件中靜態注冊或邏輯代碼中動態注冊才能正常使用。
android.content.ContentProvider內容提供者類,是用來對其他應用程序提供分享數據內容的組件類,在應用程序間的文件共享一文中,針對Android7.0以上版本所注冊的FileProvider
文件提供者,便是已經定義過的ContentProvider
的使用案例。
分享數據創建
在創建ContentProvider
內容提供者之前,首先要保證有要分享的數據存在。這些數據可能來自用戶交互,也可能來自遠程服務器返回結果。應用程序收到一系列數據后,可以根據不同數據結構,采用前文不同的數據本地保存策略,包括普通鍵值對形式的SharedPreferences
、對象結構的SQLiteDatabase
、或者普通二進制的File
。
之后便可以創建繼承自android.content.ContentProvider的自定義內容提供者類,並在其實現的相關方法中完成對本地保存數據的讀寫。而其他應用程序可以通過訪問內容提供者的相關方法,進而讀寫該應用程序要分享的數據。
分享路徑授權
由於內容提供者ContentProvider
與其他應用類交互是借助路徑定位符Uri
類,所以在創建的內容提供者ContentProvider
中,要先定義並授權允許該類訪問的相關Uri
。
在創建的內容提供者ContentProvider
中需要借助android.content.UriMatcher路徑定位匹配類,可將傳入的Uri
類型轉換為普通的int
類型,以方便在內容提供者內部匹配區分。
通常在內容提供者內部定義為靜態全局變量類型的UriMatcher
對象,其只有一參的構造方法UriMatcher(int code)
,參數值為UriMatcher.NO_MATCH=-1
。
之后可以調用靜態對象的addURI(String authority, String path, int code)
方法,增加一對路徑定位符與int
值的匹配。其中參數 authority 是一串固定的授權字符串,在注冊該內容提供者ContentProvider
時也必須用到改參數值。參數 path 是追加在 authority 參數之后的子路徑,以此區分不同的匹配路徑,最終生成的一條數據Uri格式為content://authority/path/id
。參數 code 是綁定的int
值,與每一種Uri格式為content://authority/path
的路徑Uri相對應。
在需要根據路徑定位符Uri
獲取int
值的地方,通常是下文分享數據操作中,可以調用靜態對象的match(Uri uri)
方法,如果匹配到的Uri
與上文authority+path組合一致時,返回對應code值,否則返回值為UriMatcher.NO_MATCH=-1
。
分享數據操作
在ContentProvider
中必須實現以下方法以操作本地數據。
創建onCreate()
與其他組件類似,只有在該內容提供者被系統首次加載創建時,系統才會調用該方法。可以在該方法中初始化相關全局變量,但是不建議執行耗時操作。
獲取數據類型getType(Uri uri)
由使用該內容提供者的其他應用程序調用。傳入參數 uri 作為路徑定位符指定一條數據位置,返回該數據對應的MIME類型。通常在 uri 指向文件時,根據不同文件類型以返回對應的MIME類型。其他情況返回null
即可。
增加數據insert(Uri uri, ContentValues values)
由使用該內容提供者的其他應用程序調用。在指定的參數 uri 指定的路徑下插入一條數據,其內容格式為content://authority/path
。參數 values 則是要插入的數據內容,其與數據庫中的插入方法類似,以key-value鍵值對形式保存數據。最終在數據插入成功后,需要返回該條數據對應的路徑定位符Uri對象。
刪除數據delete(Uri uri, String selection, String[] selectionArgs)
由使用該內容提供者的其他應用程序調用。參數 uri 指定要刪除數據所在位置,當內容格式為content://authority/path/id
類型時,將刪除其指定位置數據,余下兩個參數無效;當內容格式為content://authority/path
類型時,將刪除該路徑下根據其他參數查找匹配的數據,若余下參數為null,則刪除該路徑下所有數據。參數 selection 為指定刪除條件,其符合sql語句,但變量參數可用符合?代替,在后邊參數中指定具體參數值;參數 selectionArgs 即為參數值數組,長度與參數 selection 中的?符合數量一致。最終返回int
類型的數據標記總共刪除的數據條數。
修改更新數據update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
由使用該內容提供者的其他應用程序調用。參數 uri 指定要修改數據所在位置,與上文刪除數據方法中的參數一類似,當內容格式為content://authority/path/id
類型時,將更新其指定位置數據,最后兩個參數無效;當內容格式為content://authority/path
類型時,將更新該路徑下根據最后兩個參數查找匹配的數據,若最后兩個參數為null,則更新該路徑下所有數據。參數 values 是要插入的數據內容,與增加數據方法中的參數二類似。參數 selection 和參數 selectionArgs 同樣與刪除數據方法匯總的參數二和參數三類似,可以匹配符合要求的數據。最終返回int
類型的數據標記總共修改的數據條數。
查詢數據query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)系列方法
由使用該內容提供者的其他應用程序調用。參數 uri 為指定查詢路徑,與增加數據方法中的參數一類似,格式為content://authority/path
。余下參數與數據庫中的查詢方法中的參數類似,均可根據相關內容匹配數據。最終返回android.database.Cursor游標指針類型的數據,同樣可參考數據庫中的查詢結果使用。
清單文件注冊
最終自定義的內容提供者需要在清單文件中靜態注冊,才能在其他位置使用。在<application></application>
標簽中使用<provider></provider>
標簽指定內容提供者。在該標簽中,android:name
屬性綁定代碼中定義的內容提供者全局類名。屬性android:authorities
指定授權名稱,與代碼中UriMatcher
對象的添加路徑匹配符方法所傳入的 authority 參數一致。屬性android:exported
通過設置boolean
類型值,以決定該內容提供者是否可對其他應用程序提供使用。除此之外還有其他一些屬性值,可參考官方<provider>
介紹。
借助路徑定位符訪問分享數據
在其他應用程序或當前應用程序的其他位置,都可借助上下文環境Context
對象的getContentResolver()
方法,獲得android.content.ContentResolver內容解析類的對象。通過對內容解析類對象的操作,進而影響自定義的內容提供者。內容解析類ContentResolver
中有一系列方法,均與上述實現的自定義內容提供者ContentProvider
中的增刪改查等系列方法相對應,便不再贅述。
通常定義內容提供者的定義場景,是在短信類、通話類應用中將消息或聯系人信息提供給其他應用程序使用。而數據訪問方只需要獲取對應的Uri
即可。