Android权限申请的学习实践
1.引子
在換到Android手機之前,對Android系統的印象是這系統app的跑馬場,app可以任意索取各種權限,隨意竊取各種隱私,換手機后才知道Android系統對權限的管理已有很大的改觀,索取的每個危險權限都需要提示用戶,當然Android只是盡可能提示用戶,還是存在著用戶不同意就不給用的情況。
權限管理的改進給開發者增加了一定工作量,申請危險權限不再是簡單的在AndroidManifest.xml添加一行代碼的事,而是需要提示用戶進行動態申請。了解動態申請之后,覺得沒多復雜,但不了解時,只知道在網上拷貝現成代碼片段,碰到需要申請新的權限就不知道從何下手。我曾經粘貼了幾段動態申請權限代碼,就是因為不了解原理,只會復制粘貼,代碼雖然能夠運行,但無比臃腫。
為此通過此文梳理Android權限,以便掌握Android權限管理,拒絕做Copy工程師。
2.權限的作用
權限的目的是保護Android用戶的隱私。作為一個可以任意定制的開源系統,權限真是用戶隱私最后的屏障,Android系統要求,在默認情況下,任何應用程序無權執行會對其他應用程序、操作系統或用戶產生不利影響的任何操作。包括讀寫用戶的私人數據(例如聯系人或電子郵件),讀寫其他應用程序的文件,訪問網絡等等。要執行這些操作,Android應用必須獲得對應的權限。
Android有上百種權限,可分為三大類,一類是普通權限,一類是簽名權限,還有一類是危險權限。
其中普通權限是指那些不會威脅到用戶安全和隱私的權限,例如設置鬧鐘權限。授予app普通權限只需要在AndroidManifest.xml文件里聲明,系統會自動授權,不需要用戶確認,用戶也無法做撤銷操作。
第二種是簽名權限,這類權限同樣是在應用安裝時由系統授予,不過并不是無條件授予,想使用權限的應用程序必須與定義該權限的應用程序使用相同的證書才行,例如應用A使用證書A簽名,定義了一個簽名權限,應用B想使用這個權限,必須由證書A簽名。簽名權限使用的場景如一個公司有多個app,為了能讓這些app能夠相互調用,但不希望被外部app調用,就可以通過自定義一個簽名調用權限實現。
最后再來看第三類危險權限,危險權限之所以被危險,是因為這類權限涉及到用戶個人敏感數據資源,或者影響用戶存儲的數據或者其他應用程序的數據,例如讀取用戶聯系人,打開麥克風等,江湖上一直有傳言,目前許多app會偷偷打開麥克風竊聽用戶對話,然后根據對話內容精準推送廣告,這類傳言像是都市傳說,因為具有神秘性能廣泛傳播,要知道,原版Android系統中,應用索取危險權限必須需要向用戶提示,在用戶許可之前,應用是無法獲取權限的。不過Android系統畢竟是開源的,將原生Android權限管理功能修改倒是有可能雖然用戶沒同意,但app仍可以獲得權限,這話題就在本文之外了,個人認為有其他更好的方法來竊取隱私,竊聽對話是成本較高的那種,用起來不值得。
如前所述,權限有上百種,一一記住不現實,其實我們只要知道哪些是危險權限,危險權限之外都是普通權限。
危險權限總共9個分組,24個權限,如果我們申請的權限不在這個表中,那就說明是普通權限,而權限分組意思是組內的這些權限同屬于一個組,用戶同意授權一個權限組,則組內的所有權限都會授予,比如,應用被授予READ_EXTERNAL_STORAGE權限之后,如果再申請WRITE_EXTERNAL_STORAGE權限,系統會立即授予該權限,不再向用戶提示。
3.申請權限步驟和示例
-
在AndroidManifest文件中聲明,這一步不可少
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-
在應用啟動代碼中檢查權限,確認應用是否已經擁有讀寫存儲的權限。這部分是在代碼中實現了,所以叫動態申請。Android中使用ContextCompat.checkSelfPermission()檢查權限的授權情況,這個方法第一個參數是上下文Context,第二個參數是所要申請權限的名稱,名稱當然不能隨便寫阿貓阿狗,而是有特定名稱,建議直接調Android在Manifest.permission中已定義好的名稱,比如現在要申請的讀外部存儲權限是Manifest.permission.WRITE_EXTERNAL_STORAGE。該方法返回一個int類型的PERMISSION_GRANTED(同意)或者PERMISSION_DENIED`(拒絕)。一般來說,程序初次安裝后,所申請的權限的時候都是處于PERMISSION_DENIED狀態,需要提出申請,用戶同意之后不需要再次申請,除非卸載應用重新安裝或者到系統設置里把權限給關了;
-
接下來是申請權限,申請使用的方法requestPermissions(),該方法傳入參數有三個,第一個是Activity、 第二個是需要請求授權的權限字符串數組,可以把想申請的權限名稱都列入其中,第三個是識別權限請求的請求代碼,在權限申請的回調函數onRequestPermissionsResult()用得著,該值必須大于或等于0,其作用在回調函數里再詳細說明,這里只要理解成是一個自定義的標記。需要注意的是,申請權限是異步處理,也就是說,代碼不會阻塞在等用戶點擊,而是用戶點擊后再回調onRequestPermissionsResult()。以上兩個步驟的代碼如下:
-
- 接下來是覆寫申請權限回調函數onRequestPermissionsResult(),對權限申請做后續處理,該回調函數有三個返回結果,第一個requestCode,這個參數就是在requestPermissions()提到的識別權限的請求代碼,作用就是一個回執單號,根據這個單號我們能確定是我們申請權限的處理結果,也就是說,在申請權限時傳入這個參數,在處理結束后,回調函數原封不動給回來,這樣我們就知道是不是我們的處理結果;第二個參數是權限字符串數組,也就是我們在requestPermissions()填的權限字符串數組;第三個參數用戶響應的數組,用戶的對每個申請權限的批復情況就是在這個數組里,這個數組的個數是和申請權限數組是一一對應的。代碼如下:
以上如果申請單個權限,如果申請多個權限又怎么操作呢?基本步驟和申請單個權限類似,但因為是多個權限,還需要做一下額外處理,例如怎么判斷是否每個權限都授權了。下面以多申請一個錄音權限來說明
- 同樣,首先在AndroidManifest.xml做聲明
- 準備工作是創建一個權限字符串數組和聲明一個權限列表list,其中列表用于判斷每個權限的處理情況String[] permissions = new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.READ_EXTERNAL_STORAGE};
List<String> mPermissionList = new ArrayList<>();
- 判斷每個權限授權情況,未同意的列入申請名單,然后申請權限
- 覆寫請求權限回調的方法,做后續處理
4.總結
經過了解Android權限后,可以看出申請權限過程不是很復雜,普通權限比較簡單,只需要在AndroidManifest.xml中聲明即可,危險權限不僅需要在AndroidManifest.xml聲明,同時還需要在代碼中動態申請,首先是使用checkSelfPermission()檢查是否某個危險權限是否已授權,如果沒有授權,則requestPermissions()申請授權,記得這是異步處理,代碼不會阻塞在等待用戶授權位置,接下來就是處理授權情況,系統回調onRequestPermissionsResult通知我們處理結果,我們根據這個結果做進一步處理。同時申請多個權限稍微復雜一點,需要處理每個權限的處理情況。
總結
以上是生活随笔為你收集整理的Android权限申请的学习实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Activity生命周期的学习和验证
- 下一篇: Android广播的学习和使用