總結整理了一下android權限相關的知識,因爲篇幅過長,分爲兩篇博客來寫,上篇博客主要是詳解權限和安全,下篇主要是介紹android6.0權限適配問題:
android permission權限與安全機制解析(下)html
用法爲
爲了保證application的正常運行,須要系統授予app的權限聲明。這個權限是在用戶安裝應用的時候授予的。
android:name的值能夠是其餘app經過
android.permission.CAMERA或android.permission.READ_CONTACTS等等。須要注意的一點是uses-permission的權限要求說明,可能會引發app在Android Market中的過濾。
android:maxSdkVersion用來標註該權限所支持的最大api版本號,若是當從某個特定版本時,不須要該權限時就能夠加上該限制。
系統權限列表有不少,各自的用途也不同,有幾個連接能夠參考一下:
blog.csdn.net/zjl5211314/…
developer.android.com/reference/a…
developer.android.com/guide/topic…
developer.android.com/guide/topic…
android:label=」string resource」
android:name=」string」
android:permissionGroup=」string」
android:protectionLevel=[「normal」 | 「dangerous」 |
「signature」 | 「signatureOrSystem」] /> <
android:description:對權限的描述,比lable更加的詳細,介紹該權限的相關使用狀況,好比當用戶被詢問是否給其餘應用該權限時。注意描述應該使用的是string資源,而不是直接使用string串。
android:icon:用來標識該權限的一個圖標。
android:label:權限的一個給用戶展現的簡短描述。方便的來講,這個能夠直接使用一個string字串來表示,可是若是要發佈的話,仍是應該使用string資源來表示。
android:name:權限的惟一名字,因爲獨立性,通常都是使用包名加權限名,該屬性是必須的,其餘的可選,未寫的系統會指定默認值。
android:permissionGroup: 權限所屬權限組的名稱,而且須要在這個或其餘應用中使用
android:protectionLevel:權限的等級
對於普通和危險級別的權限,咱們稱之爲低級權限,應用申請即授予。其餘兩級權限,咱們稱之爲高級權限或系統權限。當應用試圖在沒有權限的狀況下作受限操做,應用將被系統殺掉以警示。系統應用可使用任何權限。權限的聲明者可無條件使用該權限。
下面經過指定一個BroadcastReceiver的權限來實驗,首先建立了兩個app:app A ,app B 。app A中註冊了一個BroadcastReceiver ,app B 發送消息,app A的manifest文件: android
複製代碼
app B 的manifest 文件內容 git
複製代碼
這樣app B 給app A 發送消息,A就能夠收到了,若未在app B的manifest文件中聲明使用相應的權限,app B發送的消息,A是收不到的。 另外,也可在app B 的manifest文件中聲明權限時,添加android:protectionLevel=「signature」,指定app B只能接收到使用同一證書籤名的app 發送的消息。 github
android:name=」string」 />
該標籤包含於在< manifest >標籤中。
該標籤聲明權限樹的基礎名稱。 應用程序擁有樹中的全部名稱。 能夠經過調用 PackageManager.addPermission() 在權限樹中動態添加新的權限。 樹中的名稱以句點(’.’)分隔。 好比,假定基礎名稱爲com.example.project.taxes,則可加入相似如下格式的權限:
com.example.project.taxes.CALCULATE
com.example.project.taxes.deductions.MAKE_SOME_UP
com.example.project.taxes.deductions.EXAGGERATE
注意本元素並非聲明權限,而只是爲後續要加入的權限定義一個命名空間。
android:icon
表明樹中全部權限的圖標。 本屬性必須設爲對 Drawable 資源的引用。
android:label
供用戶閱讀的權限組名稱。 爲了方便起見能夠將其直接設爲字符串, 但在應用程序準備發佈時,應該設爲對字符串的引用,以便對其進行本地化。
android:name
權限樹的基礎名稱,用做樹中全部權限的前綴。 爲了保證名稱的惟一性,應該採用 Java 風格的域名規則。 名稱的路徑必須至少包含兩個句點分割的字段 — 好比:com.example.base 能夠,但 com.example 就不行。api
Android在定義 permission 時, 爲每一個Permission都進行了分組,一個權限主要包含三個方面的信息:權限的名稱;屬於的權限組;保護級別。一個權限組是指把權限按照功能分紅的不一樣的集合。每個權限組包含若干具體 權限,例如在 COST_MONEY 組中包含 android.permission.SEND_SMS , android.permission.CALL_PHONE 等和費用相關的權限。具體以下SDK所示:
developer.android.com/reference/a…
再來看看源碼(在frameworks/base/core/res /AndroidManifest.xml):數組
複製代碼
能夠看到,這邊先定義了一個permissiongroup : android.permission-group.COST_MONEY, 而後又定義了兩個permission :android.permission.SEND_SMS 和 android.permission.CALL_PHONE , 須要注意的是,這兩個權限中都有一個android:permissionGroup屬性,這個屬性就指定了這個權限所屬的PermissionGroup。瀏覽器
android:description
這個屬性用於給權限組定義一個用戶可讀的說明性文本。這個文本應該比標籤更長、更詳細。這個屬性不該該直接使用字串,而應該使用字符串引用。
android:icon
這個屬性定義了一個表明權限的圖標,這個屬性應該使用資源文件來定義。
android:label
這個屬性給權限組定義了一個用戶可讀的名稱。
android:name
這個屬性定義了權限組的名稱,它是可以分配給
Android是一個權限分離的系統,這是利用Linux已有的權限管理機制,經過爲每個Application分配不一樣的uid和gid,從而使得不一樣的Application之間的私有數據和訪問(native以及java層經過這種sandbox機制,均可以)達到隔離的目的 。與此同時,Android 還在此基礎上進行擴展,提供了permission機制,它主要是用來對Application 能夠執行的某些具體操做進行權限細分和訪問控制,同時提供了per-URI permission 機制,用來提供對某些特定的數據塊進行ad-hoc方式的訪問。
經過AndroidManifest.xml文件能夠設置高級權限,以限制訪問系統的全部組件或者使用應用程序。全部的這些請求都包含在你所須要的組件中的 android:permission屬性,命名這個權限能夠控制訪問此組件。
對於組件而言,除了使用權限限制與外部交互的實體外,還有一個屬性也具備該功能,那就是android:exported,這個屬性用於指示該服務是否可以被其餘應用程序組件調用或跟它交互。若是設置爲true,則可以被調用或交互,不然不能。設置爲false時,只有同一個應用程序的組件或帶有相同用戶ID的應用程序才能啓動或綁定該服務。
它的默認值依賴於該服務所包含的過濾器。沒有過濾器則意味着該服務只能經過指定明確的類名來調用,這樣就是說該服務只能在應用程序的內部使用(由於其餘外部使用者不會知道該服務的類名),所以這種狀況下,這個屬性的默認值是false。另外一方面,若是至少包含了一個過濾器,則意味着該服務能夠給外部的其餘應用提供服務,所以默認值是true。
首先是root用戶和system用戶擁有全部的接口調用權限,而後對於其它用戶可使用如下這幾個函數來檢測 :
PackageManager.checkPermission (String permName, String pkgName)
用來檢測一個package中是否授予了指定permission。
Context.checkCallingOrSelfPermission (String permission)
用來檢測本身或者調用進程中是否授予了指定permission。
Context.checkCallingOrSelfUriPermission (Uri uri, int modeFlags)
用來檢測本身或者調用進程中是否授予了一個uri經過modeFlags指定的permission。
Context.checkCallingPermission (String permission)
檢查正在處理的調用者進程是否授予指定permission 權限,若是調用者是本身那麼返回 。
Context.checkCallingUriPermission (Uri uri, int modeFlags)
用來檢測調用進程中是否授予了一個uri經過modeFlags指定的permission。
Context.checkPermission (String permission, int pid, int uid)
用來檢測指定uid和pid的進程中是否授予了指定的permission。
checkSelfPermission (String permission)
23版本api添加,用來檢測本身是否授予了指定permission
Context.checkUriPermission (Uri uri, int pid, int uid, int modeFlags)
用來檢測指定uid和pid的進程中是否授予了一個uri經過modeFlags指定的permission。
Context.checkUriPermission (Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags)
比上面的方法多了一個檢測permission的功能,至關於同時調用checkPermission(String, int, int)和checkUriPermission(Uri, int, int, int)。
-------------
下面這一組和上面一一對應,區別就在於若是遇到檢查不經過時,會拋出異常,打印消息 :
Context.enforceCallingOrSelfPermission(String permission, String message)
Context.enforceCallingOrSelfUriPermission(Uri uri, int modeFlags, String message)
Context.enforceCallingPermission (String permission, String message)
Context.enforceCallingUriPermission (Uri uri, int modeFlags, String message)
Context.enforcePermission (String permission, int pid, int uid, String message)
Context.enforceUriPermission (Uri uri, int pid, int uid, int modeFlags, String message)
Context.enforceUriPermission (Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags, String message)
-----------
Context.grantUriPermission (String toPackage, Uri uri, int modeFlags)
爲指定package添加訪問指定uri 的讀或者寫權限
Context.revokeUriPermission (Uri uri, int modeFlags)
爲指定package刪除訪問指定uri 的讀或者寫權限。
以上函數中check開頭的,只作檢查。enforce開頭的,不單檢查,沒有權限的還會拋出異常。
checkPermission相關函數
//第一個應用程序爲的menifest文件代碼以下:上面給出了兩個程序的menifest定義,二者共用一個ShareUserId,下面咱們看看從一個程序裏面如何獲取另一個程序的Context。假設咱們從package=「com.android.demo_A」的程序獲取package=」com.android.demo_B」的程序的context://第二個應用程序的menifest文件代碼以下: 複製代碼
Context ct=this.createPackageContext("com.android.demo_B", Context.CONTEXT_IGNORE_SECURITY);複製代碼
這樣咱們就可以獲取到另一個應用的Application context了,獲取到上下文以後就可以實現數據共享和通訊,具體能夠查看個人 IPC通訊博客。
只要signature相同,就算不顯式聲明
擁有system級別權限的使用者能夠access其餘普通signature權限聲明設定過的功能。因此,設定爲擁有system級別權限便可。
應用程序安裝的時候,應用程序請求的permissions是經過package installer來批准獲取的。package installer是經過檢查該應用程序的簽名來肯定是否給予該程序request的權限。在用戶使用過程當中不會去檢查權限,也就是說要麼在安裝的時候就批准該權限,使其按照設計可使用該權限;要麼就不批准,這樣用戶也就根本沒法使用該feature,也不會有任何提示告知用戶嘗試失敗。
例如高級權限用有system級別權限設定的api時,須要使其apk擁有system權限。好比在 android 的API中有供給SystemClock.setCurrentTimeMillis()函數來修改系統時間。有兩個方法:
第1個方法簡單點,不過須要在Android系統源碼的狀況下用make來編譯:
第2個方法麻煩點,不過不用開虛擬機跑到源碼環境下用make來編譯:
blog.csdn.net/xyz_lmn/art…
blog.csdn.net/t12x3456/ar…
yelinsen.iteye.com/blog/101274…
berdy.iteye.com/blog/178285…
my.oschina.net/u/589963/bl…
blog.csdn.net/vshuang/art…
www.chawenti.com/articles/12…
ee.ofweek.com/2012-04/ART…
blog.csdn.net/liujian885/…
maoruibin.github.io/%E6%8A%80%E…
www.zhihu.com/question/37…
blog.csdn.net/wirelessqa/…