android 权限管理框架,Android 运行时权限管理最佳实践
歡迎訪問我的個人博客 傳送門
從 Android 6.0(API 級別 23)開始,用戶開始在應(yīng)用運行時向其授予權(quán)限,而不是在應(yīng)用安裝時授予。此方法可以簡化應(yīng)用安裝過程,因為用戶在安裝或更新應(yīng)用時不需要授予權(quán)限。它還讓用戶可以對應(yīng)用的功能進行更多控制;例如,用戶可以選擇為相機應(yīng)用提供相機訪問權(quán)限,而不提供設(shè)備位置的訪問權(quán)限。用戶可以隨時進入應(yīng)用的“Settings”屏幕調(diào)用權(quán)限。
正常權(quán)限和危險權(quán)限
系統(tǒng)權(quán)限分為幾個保護級別。需要了解的兩個最重要保護級別是正常權(quán)限和危險權(quán)限,如果應(yīng)用聲明其需要正常權(quán)限,系統(tǒng)會自動向應(yīng)用授予該權(quán)限,如:訪問網(wǎng)絡(luò)。如果應(yīng)用聲明其需要危險權(quán)限,則用戶必須明確向應(yīng)用授予該權(quán)限,如:訪問聯(lián)系人、讀寫權(quán)限。
正常權(quán)限
官網(wǎng)可查 點擊查詢
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMINbaidu_push
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
危險權(quán)限
可通過adb 命令獲取 adb shell pm list permissions -d -g
group:android.permission-group.RCS_PERMISSION
group:com.google.android.gms.permission.CAR_INFORMATION
permission:com.google.android.gms.permission.CAR_VENDOR_EXTENSION
permission:com.google.android.gms.permission.CAR_MILEAGE
permission:com.google.android.gms.permission.CAR_FUEL
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.ANSWER_PHONE_CALLS
permission:android.permission.READ_PHONE_NUMBERS
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:com.google.android.gms.permission.CAR_SPEED
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:com.sina.weibo.permission-group
permission:com.sina.weibo.permission.USER
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
從上面的權(quán)限列表中可以看出危險權(quán)限都是分組的,如果應(yīng)用請求其清單中列出的危險權(quán)限,而應(yīng)用在同一權(quán)限組中已有另一項危險權(quán)限,則系統(tǒng)會立即授予該權(quán)限,而無需與用戶進行任何交互。例如,如果某應(yīng)用已經(jīng)請求并且被授予了 READ_CONTACTS 權(quán)限,然后它又請求 WRITE_CONTACTS,系統(tǒng)將立即授予該權(quán)限。
請求權(quán)限
這里以申請日歷讀寫權(quán)限為例
1.在 AndroidMainifest 中聲明所需權(quán)限
2.檢查權(quán)限
private fun checkPermissions(): Boolean {
return when (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR)) {
PackageManager.PERMISSION_GRANTED -> {//有此權(quán)限
true
}
PackageManager.PERMISSION_DENIED -> {//無此權(quán)限
false
}
else -> false
}
}
這里用到系統(tǒng)提供的 ContextCompat.checkSelfPermission 方法,用于檢測某個權(quán)限是否已經(jīng)被授予,方法返回值為 PackageManager.PERMISSION_GRANTED 表示已權(quán)限,為PackageManager.PERMISSION_DENIED 表示無此權(quán)限需要進行申請授權(quán)。
3.申請權(quán)限
private fun requestPermissions() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CALENDAR)) {
// 是否需要向用戶解釋為何申請權(quán)限
toast(this,"需要此權(quán)限管理日歷")
} else {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.READ_CALENDAR),
1)
}
}
ActivityCompat.shouldShowRequestPermissionRationale 方法 用于在實際顯示權(quán)限對話框之前是否顯示一個對正在請求權(quán)限的解釋,在app第一次安裝的時候。這個方法會返回false,因此你可以直接請求任何需要的權(quán)限。
如果用戶以前拒絕了一個請求,則分為兩種情況:
如果用戶僅拒絕沒有點不再提示,這個方法將返回 true
如果用戶拒絕并點擊不再提示,這個方法將返回 false
ActivityCompat.requestPermissions 方法 用于申請權(quán)限,第二個參數(shù)為 所需權(quán)限數(shù)組,也就是可申請一個,或多個權(quán)限。第三個參數(shù)為 requestCode 回調(diào)的時候使用
4.處理權(quán)限申請回調(diào)
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
1 -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
toast(this, "已授權(quán)")
} else {
toast(this, "未授權(quán)")
}
}
else -> {
}
}
}
處理權(quán)限要實現(xiàn) onRequestPermissionsResult 方法,該方法有三個參數(shù)
requestCode 和申請權(quán)限時 requestCode 對應(yīng),
permissions 申請的權(quán)限數(shù)組
grantResults 申請結(jié)果
完整的代碼如下:
fun click(view: View?) {
when (view?.id) {
R.id.bt_query_permissions -> when (checkPermissions()) {
true -> toast(this, "有權(quán)限")
false -> toast(this, "無權(quán)限")
}
R.id.bt_request_permissions -> requestPermissions()
}
}
private fun checkPermissions(): Boolean {
return when (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR)) {
PackageManager.PERMISSION_GRANTED -> {//有此權(quán)限
true
}
PackageManager.PERMISSION_DENIED -> {//無此權(quán)限
false
}
else -> false
}
}
private fun requestPermissions() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CALENDAR)) {
toast(this,"需要此權(quán)限管理日歷")
} else {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.READ_CALENDAR),
1)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
1 -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
toast(this, "已授權(quán)")
} else {
toast(this, "未授權(quán)")
}
}
else -> {
}
}
}
推薦使用 RxPermissions
RxPermissions 是一個基于 RxJava 實現(xiàn)的權(quán)限框架,比使用 Android 自帶的 API 方便很多,可擴展性高。GitHub 地址
引入
這里以 Rxjava2 為例
repositories {
jcenter() // If not already there
}
dependencies {
//compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar' // Rxjava1
compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar' // Rxjava2
compile "io.reactivex.rxjava2:rxjava:2.1.7"
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
}
請求權(quán)限
request 可申請一個或多個權(quán)限 直接返回是否授權(quán)成功
val rxPermissions = RxPermissions(this)
rxPermissions.request(Manifest.permission.READ_CALENDAR)
.subscribe({ t ->
if (t) {
toast(this, "已授權(quán)")
} else {
toast(this, "未授權(quán)")
}
})
requestEach or ensureEach 來分別獲取每一個權(quán)限請求的結(jié)果
rxPermissions.requestEach(Manifest.permission.READ_CALENDAR, Manifest.permission.CAMERA)
.subscribe({ t ->
when {
t.granted -> toast(this, "${t.name} 已授權(quán)")
t.shouldShowRequestPermissionRationale -> toast(this, "${t.name} 未授權(quán)")
else -> toast(this, "${t.name} 已拒絕,并不提示")
}
})
這里的 shouldShowRequestPermissionRationale 參照上文 權(quán)限申請
最后
權(quán)限申請的坑還有很多,特別是在國產(chǎn)手機上有各種各樣的bug,這個就要具體踩坑,具體解決了
總結(jié)
以上是生活随笔為你收集整理的android 权限管理框架,Android 运行时权限管理最佳实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lenovo人工服务电话(联想lenov
- 下一篇: android Q gradle配置,【