當前位置:
首頁 > 最新 > Android開發學習-Day16 內容提供器

Android開發學習-Day16 內容提供器

我們在前面初步學習了Android的Activity和BroadcastReceiver組件,接下來要繼續學習下一個組件內容提供器 -- Content Provider。


一、內容提供器簡介

內容提供器(ContentProvider)主要用於在不同的應用程序之間實現數據共享的功能,它提供了一套完整的機制,允許一個程序訪問另一個程序中的數據,同時還能保證被訪數據的安全性。目前, 使用內容提供器是 Android實現跨程序共享數據的標準方式。

不同於文件存儲和 SharedPreferences存儲中的兩種全局可讀寫操作模式,內容提供器可以選擇只對哪一部分數據進行共享,從而保證我們程序中的隱私數據不會有泄漏的風險。

不過在正式開始學習內容提供器之前,我們需要先掌握另外一個非常重要的知識Android 運行時許可權,因為待會的內容提供器示例中會使用到運行時許可權的功能。


Android開發團隊在Android 6.0系統中引入了運行時許可權這個功能,用以加強保護用戶的安全隱私。

1、Android許可權機制

在學習廣播的時候,當時為了要訪問系統的網路狀態,我們在AndroidManifest中添加過如下的聲明:

這是因為訪問系統的網路狀態涉及到了用戶設備的安全性,因此必須在AndroidManifest中添加聲明,否則程序就會出現大問題。再添加過相應的聲明後,用戶安裝該app時,就會在安裝界面提示用戶該app申請使用了哪些許可權。如果用戶不認可某些許可權,就可以選擇不安裝。

但是市場上有很多我們常用的軟體存在著濫用許可權的情況,但是我們又不得不用,一瞬間有種店大欺客的感覺。Android團隊也認識到這個問題,於是在6.0系統中加入了運行時許可權。用戶不需要在安裝軟體的時候一次性授權所有的申請許可權,可以在使用過程中再對某一項全項進行授權。比如一款拍照軟體,要訪問通訊錄許可權,就算用戶拒絕了這個許可權,該應用的其他功能還是能正常使用,不會說不給通訊錄許可權就拍不了照了。

Android將現有的許可權分成了兩類,一類是普通許可權,一類是危險許可權。普通許可權指的是那些不會直接威脅到用戶的安全和隱私的許可權,這部分許可權系統自動幫我們進行授權。危險許可權則表示非常有可能會觸及用戶隱私或對設備造成安全影響,對於這部分許可權申請,必須要由用戶手動點擊授權才可以,否則程序無法使用相應的功能。

圖中所示的為Android的危險許可權,涉及9組24個許可權。每一個危險許可權都屬於一個許可權組,當用戶授權了許可權組中任意一個許可權是,改組的其他許可權也會同時被授權。

2、在程序運行時申請許可權

簡單的介紹完Android的許可權機制後,下面我們用打電話的例子來體驗一下。我們從上面的表中看到PHONE許可權組是危險許可權,因為撥打電話會設計用戶的手機資費問題,因為被列入了危險許可權。新建一個Activity,增加一個Button用來撥打電話:

首先我們定義了一個call()方法,把撥打電話的邏輯寫在了裡面。構建一個隱式Intent,Intent的action指定為Intent.ACTION_CALL,這是系統內置的打電話動作,然後在data部分指定了協議是tel,號碼為10086。為了防止應用程序的崩潰,我們把操作都放在異常捕獲代碼塊中。

回到onCreate()方法,我們在執行call()方法撥打電話前,需要先確認用戶是不是已經給過授權。這裡用的是ContextCompat.checkSelfPermission()方法,該方法接收兩個參數,第一個參數是Context,第二個是具體的許可權名,例如撥打電話就是Manifest.permission.CALLPHONE。然後我們把返回值和PackageManager.PERMISSIONGRANTED做比較,相等說明用戶已經授權,可以調用call()方法進行撥打電話操作;不等表示沒有授權,則需要進一步調用ActivityCompat.requestPermissions()方法來向用戶申請授權。requestPermissions()方法接收3個參數,第一個參數是Context,第二個參數是一個String數組,把許可權名放在數組中即可,第三個參數是requestCode,只要是唯一值就行。

調用完requestPermissions()方法後,會在界面上彈出一個授權彈窗,無論用戶點擊授權或拒絕,最終都會回調onRequestPermissionsResult()方法,並將結果封裝在grantResults中。這裡,我們只需要根據對應的requestCode,判斷下grantResults結果。如果授權了,就調用call()方法撥打電話, 如果沒有授權就算了。

GIF


如果一個應用程序通過內容提供器對其數據提供了外部訪問介面,那麼任何其他的應用程序都可以對這部分數據進行訪問。Android系統中自帶的電話簿、簡訊、媒體庫等程序都提供了類似的訪問介面。我們接下來就看看,如何讀取聯繫人信息。在設備中添加一些測試的電話號碼,一會兒我們會讀取這些信息。

我們準備了一個ListView用於存放聯繫人信息,然後使用ArrayAdapter適配器,這裡因為讀取聯繫人是危險許可權,因此需要添加處理運行時許可權的邏輯,在上面一節中已經掌握了。下面重點看一下readContacts()方法。

這裡我們用了ContentResolver的query()方法來查詢系統的聯繫人數據。對於每個應用程序來說,如果想要訪問內容提供器中共享的數據,就一定要藉助ContentResolver類,我們可以通過Context中的getContentResolver()方法獲取到該類的實例。ContentResolver中提供了一系列的方法用於對數據進行CRUD操作。其中insert()方法用於添加數據,update()方法用於更新數據,delete()方法用於刪除數據,query()方法用於查詢數據。是不是跟SQLite的操作感覺很類似,但不同的地方在於ContentResolver中的CRUD操作都不接收表名參數,而是使用了一個Uri參數代替,這個參數被稱為內容URI。內容URI給Content Provider中的數據建立了唯一標識符,主要由兩部分組成:authority和path。authority用於對不同的應用程序做區分,通常以包名的形式命名。path則用於對同一個應用程序中不同的表做區分。通過內容URI,可以非常清晰的表達出我們想要訪問那個程序的哪張表的數據。

這裡我們使用的是ContactsContract.CommonDataKinds.Phone封裝好的CONTENT_URI常量,這個常量就是使用Uri.parse()方法解析出來的結果。接著就遍歷Cursor對象,將聯繫人的姓名和電話取出,並添加到List數據中,然後通知刷新一下ListView,一定不能忘記的事情是將Cursor關掉。

最後,在AndroidManifest中添加讀取聯繫人的許可權聲明。重新運行一下程序:

GIF

關於Content Provider,還有些分知識沒有學習,例如如何創建自己的內容提供器,大家可以自學一下。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 TesterJohn 的精彩文章:

TAG:TesterJohn |