Android復習(四)權限—>概覽
權限概述
許可 的目的是保護Android用戶的隱私。Android應用必須獲得訪問敏感用戶數據(例如聯系人和SMS)以及某些系統功能(例如相機和互聯網)的權限。根據功能的不同,系統可能會自動授予權限,或者可能提示用戶批準請求。
Android安全體系結構的中心設計要點是,默認情況下,沒有任何應用程序有權執行任何會對其他應用程序,操作系統或用戶產生不利影響的操作。這包括讀取或寫入用戶的私人數據(例如聯系人或電子郵件),讀取或寫入其他應用程序的文件,執行網絡訪問,使設備保持喚醒狀態等等。
本頁概述了Android權限的工作方式,包括:如何向用戶顯示權限,安裝時和運行時權限請求之間的區別,權限的執行方式以及權限的類型及其組。如果您只是想要使用應用程序權限的使用指南,請參閱“ 請求應用程序權限”。
權限批準
應用程序必須通過 <uses-permission>在應用程序清單中包含標簽 來公開其所需的權限 。例如,需要發送SMS消息的應用程序清單中應包含以下行:
<manifest xmlns:android =“ http://schemas.android.com/apk/res/android”
package =“ com.example.snazzyapp”>
<uses-permission android:name =“ android.permission.SEND_SMS” />
<應用程序...>
...
</ application>
</ manifest>
如果您的應用在其清單中列出了正常權限(即,不會對用戶的隱私或設備的操作造成太大風險的權限),則系統會自動將這些權限授予您的應用。
如果您的應用在清單中列出了危險的權限(即可能會影響用戶隱私或設備正常操作的SEND_SMS權限),例如上述 權限,則用戶必須明確同意授予這些權限。
有關正常和危險權限的更多信息,請參閱保護級別。
請求提示危險權限
只有危險的權限需要用戶同意。Android要求用戶授予危險權限的方式取決于在用戶設備上運行的Android版本以及您的應用定位的系統版本。
運行時請求(Android 6.0及更高版本)
如果設備運行的是Android 6.0(API級別23)或更高版本, 并且應用程序的版本targetSdkVersion 為23或更高版本,則在安裝時不會通知用戶任何應用程序權限。您的應用程序必須要求用戶在運行時授予危險權限。當您的應用請求權限時,用戶會看到一個系統對話框(如圖1左側所示),告訴用戶您的應用正在嘗試訪問哪個權限組。該對話框包括“拒絕”和“ 允許”按鈕。
如果用戶拒絕許可請求,則下次您的應用程序請求許可時,對話框將包含一個復選框,選中該復選框后,該復選框指示用戶不想再次被提示輸入許可(請參見圖1,右)。

圖1.初始許可對話框(左)和輔助許可請求,帶有關閉其他請求的選項(右)
如果用戶選中“ 不再詢問”框并點擊 “拒絕”,則系統不再提示用戶是否以后再嘗試請求相同的權限。
即使用戶向您的應用授予了它所請求的權限,您也不能總是依靠它。用戶還可以選擇在系統設置中一對一啟用和禁用權限。您應該始終在運行時檢查并請求權限,以防止運行時錯誤(SecurityException)。
有關如何處理運行時權限請求的詳細信息,請參閱“ 請求應用程序權限”。
安裝時間請求(Android 5.1.1及更低版本)
如果設備運行的是Android 5.1.1(API級別22)或更低版本,或者targetSdkVersion 在任何版本的Android上運行時 該應用程序為22或更低版本,則系統會在安裝時自動要求用戶授予您的應用程序所有危險的權限(見圖2)。

圖2.安裝時權限對話框
如果用戶單擊“ 接受”,則將授予應用程序請求的所有權限。如果用戶拒絕權限請求,則系統將取消應用程序的安裝。
如果應用程序更新包含對其他權限的需求,則會提示用戶在更新應用程序之前接受這些新權限。
有關建議的請求權限的用戶體驗模式的概述,請參閱“ 應用程序權限最佳實踐”。
要了解如何檢查用戶的權限并向其請求權限,請參閱“ 請求應用程序權限”。
請求提示以訪問敏感的用戶信息
某些應用程序依賴對與呼叫日志和SMS消息相關的敏感用戶信息的訪問。如果要請求特定于呼叫日志和SMS消息的權限并將應用程序發布到Play商店,則必須提示用戶將應用程序設置為核心系統功能的默認處理程序,然后再請求這些運行時權限。
有關默認處理程序的更多信息,包括有關向用戶顯示默認處理程序提示的指南,請參閱僅在默認處理程序中使用的權限指南。
可選硬件功能的權限
要訪問某些硬件功能(例如藍牙或攝像頭),必須獲得應用程序許可。但是,并非所有的Android設備實際上都具有這些硬件功能。因此,如果您的應用請求該 CAMERA許可,則還必須<uses-feature>在清單中包括標記,以聲明是否確實需要此功能,這一點很重要 。例如:
<uses-feature android:name="android.hardware.camera" android:required="false" />
如果您聲明android:required="false"使用該功能,則Google Play允許將您的應用安裝在不具有該功能的設備上。然后,您必須通過調用來檢查當前設備在運行時是否具有該功能 PackageManager.hasSystemFeature(),并在該功能不可用時優雅地禁用該功能。
如果您未提供 <uses-feature>標簽,則當Google Play看到您的應用請求相應的權限時,即表示您的應用需要此功能。因此,它會從沒有功能的設備中過濾您的應用,就像您android:required="true"在<uses-feature>標記中聲明 的一樣 。
有關更多信息,請參閱 Google Play和基于功能的過濾
權限執行
權限不僅用于請求系統功能。應用程序提供的服務可以強制執行自定義權限,以限制誰可以使用它們。有關聲明自定義權限的更多信息,請參見定義自定義應用程序權限。
活動許可執行
使用android:permission屬性對清單中的標簽應用的權限會限制誰可以啟動該標簽。在和中 檢查權限 。如果呼叫者沒有所需的權限,則會 從呼叫中拋出。 <activity>ActivityContext.startActivity()Activity.startActivityForResult()SecurityException
服務許可執行
使用android:permission屬性應用于清單中標簽的權限限制了誰可以啟動或綁定到相關的權限。在權限檢查 , 和 。如果呼叫者沒有所需的權限,則會從呼叫中拋出。 <service>ServiceContext.startService()Context.stopService()Context.bindService()SecurityException
廣播許可執行
使用android:permission屬性對標簽應用的權限會限制誰可以將廣播發送到關聯的。返回后會檢查權限,因為系統會嘗試將提交的廣播交付給給定的接收者。結果,權限失敗不會導致異常被拋出給調用者。它只是不提供。 <receiver>BroadcastReceiver Context.sendBroadcast()Intent
以相同的方式,可以提供權限Context.registerReceiver()來控制誰可以廣播到以編程方式注冊的接收器。反之,當呼叫Context.sendBroadcast()以限制允許哪些廣播接收者接收廣播時,可以提供許可。
請注意,接收方和廣播方都可能需要許可。發生這種情況時,必須通過兩個權限檢查,才能將意圖傳遞給關聯的目標。有關更多信息,請參閱“ 使用權限限制廣播”。
內容提供者權限執行
使用android:permission屬性對標記應用的權限限制了誰可以訪問中的數據 。(內容提供者有一個重要的附加安全工具可供使用,稱為 URI權限,下面將對其進行介紹。)與其他組件不同,可以設置兩個單獨的許可屬性: 限制可以從提供者讀取的用戶,以及 限制可以寫入的用戶。它。請注意,如果提供者同時受到讀和寫權限的保護,則僅持有寫許可并不意味著您可以從提供者中進行讀取。 <provider>ContentProvider android:readPermission android:writePermission
首次檢索提供程序時會檢查權限(如果您既沒有權限,SecurityException 則拋出a),并且在對提供程序執行操作時會進行檢查。使用 ContentResolver.query()需要擁有讀取權限;使用 ContentResolver.insert(), ContentResolver.update(), ContentResolver.delete() 需要寫權限。在所有這些情況下,未持有所需的許可權將導致SecurityException呼叫被拋出。
URI權限
到目前為止,與內容提供者一起使用時,到目前為止描述的標準許可系統通常還不夠。內容提供商可能希望通過讀寫權限來保護自己,而其直接客戶端還需要將特定的URI交給其他應用程序才能進行操作。
一個典型的示例是電子郵件應用程序中的附件。對電子郵件的訪問應受權限保護,因為這是敏感的用戶數據。但是,如果將圖像附件的URI提供給圖像查看器,則該圖像查看器不再具有打開附件的權限,因為它沒有理由持有訪問所有電子郵件的權限。
解決此問題的方法是按URI權限:啟動活動或將結果返回活動時,調用者可以設置 Intent.FLAG_GRANT_READ_URI_PERMISSION和/或 Intent.FLAG_GRANT_WRITE_URI_PERMISSION。這授予接收活動權限訪問該意圖中的特定數據URI,而不管它是否有權訪問與該意圖相對應的內容提供程序中的數據。
此機制允許使用通用的能力樣式模型,其中用戶交互(例如打開附件或從列表中選擇聯系人)驅動細化權限的臨時授予。這可能是一種關鍵功能,用于將應用程序所需的權限減少到僅與行為直接相關的權限。
為了構建最安全的實現,使其他應用對您在應用中的行為負責,您應該以這種方式使用細粒度的權限,并使用屬性或 標記聲明應用對其的支持 。 android:grantUriPermissions<grant-uri-permissions>
更多信息可在發現 Context.grantUriPermission(), Context.revokeUriPermission()和 Context.checkUriPermission()方法。
其他權限執行
可以在每次調用服務時強制執行任意細粒度的權限。這是通過該Context.checkCallingPermission()方法完成的。使用所需的權限字符串進行調用,并返回一個整數,該整數指示是否已將權限授予當前調用進程。請注意,僅當您正在執行從另一個進程傳入的調用時才可以使用此功能,通常是通過從服務發布的IDL接口或以其他方式賦予另一個進程的方式來執行此調用。
還有許多其他有用的方法來檢查權限。如果您具有另一個進程的進程ID(PID),則可以使用該Context.checkPermission()方法檢查對該PID的權限。如果您具有另一個應用程序的程序包名稱,則可以使用該PackageManager.checkPermission()方法來確定該特定程序包是否已被授予特定權限。
自動權限調整
隨著時間的流逝,可能會向平臺添加新的限制,以便使用某些API,您的應用必須請求以前不需要的權限。由于現有應用假定可以免費訪問這些API,因此Android可以將新的權限請求應用于該應用的清單,以避免在新的平臺版本上破壞該應用(從而“祖父”獲得該許可)。Android根據為 targetSdkVersion屬性提供的值來決定應用程序是否需要權限。如果該值低于添加權限的版本,則Android會添加權限。
例如,READ_EXTERNAL_STORAGE 從API級別19開始強制執行該權限,以限制對共享存儲空間的訪問。如果您 targetSdkVersion未滿18歲,則此權限會添加到較新版本的Android上的您的應用中。
警告:如果將權限自動添加到您的應用,即使您的應用實際上可能不需要這些附加權限,您在Google Play上的應用列表也會列出這些附加權限。為了避免這種情況并刪除不需要的默認權限,請始終將其更新 targetSdkVersion為盡可能高的級別。您可以在Build.VERSION_CODES文檔中查看每個發行版中添加了哪些權限。
防護等級
權限分為幾個保護級別。保護級別會影響是否需要運行時權限請求。
有三種影響第三方應用程序的保護級別: 正常,簽名和危險權限。要查看特定權限具有的保護級別,請訪問 權限API參考頁。
普通權限
普通權限涵蓋了您的應用需要訪問其沙盒之外的數據或資源的區域,但這些區域對用戶的隱私或其他應用的操作幾乎沒有風險。例如,設置時區的權限是普通權限。
如果應用程序在其清單中聲明需要正常權限,則系統會在安裝時自動向該應用程序授予該權限。系統不會提示用戶授予普通權限,并且用戶無法撤消這些權限。
簽名權限
系統會在安裝時授予這些應用程序權限,但僅在嘗試使用權限的應用程序與定義該權限的應用程序使用相同的證書簽名時。
注意:某些簽名權限不適用于第三方應用程序。危險權限
危險權限涵蓋應用程序需要涉及用戶私人信息的數據或資源的區域,或可能影響用戶存儲的數據或其他應用程序的操作的區域。例如,讀取用戶聯系人的功能是危險的權限。如果應用程序聲明需要危險的權限,則用戶必須向該應用程序明確授予該權限。在用戶批準許可之前,您的應用無法提供依賴于該許可的功能。
要使用危險權限,您的應用必須提示用戶在運行時授予權限。有關如何提示用戶的更多詳細信息,請參閱 請求危險權限提示。
特殊權限
有一些權限的行為與正常和危險的權限不同。SYSTEM_ALERT_WINDOW并且WRITE_SETTINGS特別敏感,因此大多數應用都不應使用它們。如果應用程序需要這些權限之一,則它必須在清單中聲明該權限,并發送請求用戶授權的意圖。系統通過向用戶顯示詳細的管理屏幕來響應此意圖。
有關如何請求這些權限的詳細信息,請參見SYSTEM_ALERT_WINDOW和 WRITE_SETTINGS參考條目。
Android系統提供的所有權限都可以在找到 Manifest.permission。
權限組
權限分為與設備功能或功能相關的組。在此系統下,權限請求在組級別處理,并且單個權限組對應于應用清單中的多個權限聲明。例如,SMS組同時包含READ_SMS和 RECEIVE_SMS聲明。通過這種方式對權限進行分組,使用戶可以做出更有意義和更明智的選擇,而不會因復雜而技術性的權限請求而煩惱。

所有危險的Android權限均屬于權限組。無論保護級別如何,任何許可都可以屬于許可組。但是,如果權限很危險,則權限的組只會影響用戶體驗。
如果設備運行的是Android 6.0(API級別23),并且應用程序的版本targetSdkVersion為23或更高版本,則當您的應用程序請求危險許可時,將發生以下系統行為:
- 如果該應用程序當前在權限組中沒有任何權限,則系統會向用戶顯示權限請求對話框,以描述該應用程序要訪問的權限組。該對話框未描述該組內的特定權限。例如,如果某個應用程序請求該
READ_CONTACTS權限,則系統對話框僅顯示該應用程序需要訪問該設備的聯系人。如果用戶授予批準,則系統僅向應用程序授予其請求的權限。 - 如果已在同一權限組中為該應用程序授予了另一個危險權限,則系統將立即授予該權限,而無需與用戶進行任何交互。例如,如果某個應用先前已請求并被授予
READ_CONTACTS許可,然后又請求WRITE_CONTACTS,則系統會立即授予該許可,而不會向用戶顯示許可對話框。
警告:未來版本的Android SDK可能會將特定權限從一個組轉移到另一個組。因此,請勿將您應用的邏輯基于這些權限組的結構。
例如,與Android 8.1(API級別27)READ_CONTACTS處于同一權限組 WRITE_CONTACTS。如果您的應用請求了READ_CONTACTS 權限,然后又請求了 WRITE_CONTACTS權限,請不要假設系統可以自動授予 WRITE_CONTACTS權限。
如果設備運行的是Android 5.1(API級別22)或更低版本,或者應用程序的 targetSdkVersion操作系統是22或更低版本,則系統會要求用戶在安裝時授予權限。再次,系統只是告訴用戶應用程序需要什么權限組,而不是單個權限。例如,當應用程序請求READ_CONTACTS安裝對話框時,將列出“聯系人”組。當用戶接受時,僅將READ_CONTACTS權限授予該應用程序。
注意:即使用戶已經在同一組中授予了另一個權限,您的應用程序仍需要顯式請求其所需的每個權限。此外,權限的分組可能會在未來的Android版本中更改。您的代碼不應具有依賴同一組中一組特定權限的邏輯。
查看應用程序的權限
您可以使用“設置”應用程序和shell命令查看系統中當前定義的所有權限adb shell pm list permissions。要使用“設置”應用,請轉到“設置” >“ 應用”。選擇一個應用程序并向下滾動以查看該應用程序使用的權限。對于開發人員,adb的-s選項以類似于用戶查看權限的形式顯示權限:
$ adb shell pm list permissions -s All Permissions: Network communication: view Wi-Fi state, create Bluetooth connections, full internet access, view network state Your location: access extra location provider commands, fine (GPS) location, mock location sources for testing, coarse (network-based) location Services that cost you money: send SMS messages, directly call phone numbers ...
-g在模擬器或測試設備上安裝應用程序時,還可以使用adb 選項自動授予所有權限:
$ adb shell install -g MyApp.apk

浙公網安備 33010602011771號