中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

為什么說在Android中請求權限從來都不是一件簡單的事情

發布時間:2021-10-22 16:30:42 來源:億速云 閱讀:97 作者:iii 欄目:移動開發

這篇文章主要講解了“為什么說在Android中請求權限從來都不是一件簡單的事情”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“為什么說在Android中請求權限從來都不是一件簡單的事情”吧!

假設我正在開發一個拍照功能,拍照功能通常都需要用到相機權限和定位權限,也就是說,這兩個權限是我實現拍照功能的先決條件,一定要用戶同意了這兩個權限我才能繼續進行拍照。

那么怎樣去申請這兩個權限呢?Android 提供的運行時權限 API 相信每個人都很熟悉了,我們自然而然可以寫出如下代碼:

class MainActivity : AppCompatActivity() {      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         ActivityCompat.requestPermissions(this,             arrayOf(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION), 1)     }      override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {         super.onRequestPermissionsResult(requestCode, permissions, grantResults)         when (requestCode) {             1 -> {                 var allGranted = true                 for (result in grantResults) {                     if (result != PackageManager.PERMISSION_GRANTED) {                         allGranted = false                     }                 }                 if (allGranted) {                     takePicture()                 } else {                     Toast.makeText(this, "您拒絕了某項權限,無法進行拍照", Toast.LENGTH_SHORT).show()                 }             }         }     }      fun takePicture() {         Toast.makeText(this, "開始拍照", Toast.LENGTH_SHORT).show()     }  }

可以看到,這里先是通過調用 requestPermissions() 方法請求相機權限和定位權限,然后在  onRequestPermissionsResult()  方法里監聽授權的結果。如果用戶同意了這兩個權限,那么我們就可以去進行拍照了,如果用戶拒絕了任意一個權限,那么彈出一個 Toast  提示,告訴用戶某項權限被拒絕了,從而無法進行拍照。

這種寫法麻煩嗎?這個就仁者見仁智者見智了,有些朋友可能覺得這也沒多少行代碼呀,有什么麻煩的。但我個人認為還是比較麻煩的,每次需要請求運行時權限時,我都會覺得很心累,不想寫這么啰嗦的代碼。

不過我們暫時不從簡易性的角度考慮,從正確性的角度上來講,這種寫法對嗎?我認為是有問題的,因為我們在權限被拒絕時只是彈了一個 Toast  來提醒用戶,并沒有提供后續的操作方案,用戶如果真的拒絕了某個權限,應用程序就無法繼續使用了。

因此,我們還需要提供一種機制,當權限被用戶拒絕時,可以再次重新請求權限。

現在我對代碼進行如下修改:

class MainActivity : AppCompatActivity() {      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         requestPermissions()     }      override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {         super.onRequestPermissionsResult(requestCode, permissions, grantResults)         when (requestCode) {             1 -> {                 var allGranted = true                 for (result in grantResults) {                     if (result != PackageManager.PERMISSION_GRANTED) {                         allGranted = false                     }                 }                 if (allGranted) {                     takePicture()                 } else {                     AlertDialog.Builder(this).apply {                         setMessage("拍照功能需要您同意相機和定位權限")                         setCancelable(false)                         setPositiveButton("確定") { _, _ ->                             requestPermissions()                         }                     }.show()                 }             }         }     }      fun requestPermissions() {         ActivityCompat.requestPermissions(this,             arrayOf(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION), 1)     }      fun takePicture() {         Toast.makeText(this, "開始拍照", Toast.LENGTH_SHORT).show()     }  }

這里我將請求權限的代碼提取到了一個 requestPermissions() 方法當中,然后在 onRequestPermissionsResult()  里判斷,如果用戶拒絕了某項權限,那么就彈出一個對話框,告訴用戶相機和定位權限是必須的,然后在 setPositiveButton 的點擊事件中調用  requestPermissions() 方法重新請求權限。

可以看到,現在我們對權限被拒絕的場景進行了更加充分的考慮。

那么現在這種寫法,是不是就將請求運行時權限的各種場景都考慮周全了呢?其實還沒有,因為 Android 權限系統還提供了一種非常 “惡心”  的機制,叫拒絕并不再詢問。

當某個權限被用戶拒絕了一次,下次我們如果再申請這個權限的話,界面上會多出一個拒絕并不再詢問的選項。只要用戶選擇了這一項,那么完了,我們之后都不能再去請求這個權限了,因為系統會直接返回我們權限被拒絕。

這種機制對于用戶來說非常友好,因為它可以防止一些惡意軟件流氓式地無限重復申請權限,從而嚴重騷擾用戶。但是對于開發者來說,卻讓我們苦不堪言,如果我的某項功能就是必須依賴于這個權限才能運行,現在用戶把它拒絕并不再詢問了,我該怎么辦?

當然,絕大多數的用戶都不是傻 X,當然知道拍照功能需要用到相機權限了,相信 99% 的用戶都會點擊同意授權。但是我們可以不考慮那剩下 1%  的用戶嗎?不可以,因為你們公司的測試就是那 1% 的用戶,他們會進行這種傻 X 式的操作。

也就是說,即使只為了那 1% 的用戶,為了這種不太可能會出現的操作方式,我們在程序中還是得要將這種場景充分考慮進去。

那么,權限被拒絕且不再詢問了,我們該如何處理呢?比較通用的處理方式就是提醒用戶手動去設置當中打開權限,如果想做得再好一點,可以提供一個自動跳轉到當前應用程序設置界面的功能。

下面我們就來針對這種場景進行完善,如下所示:

class MainActivity : AppCompatActivity() {      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         requestPermissions()     }      override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {         super.onRequestPermissionsResult(requestCode, permissions, grantResults)         when (requestCode) {             1 -> {                 val denied = ArrayList<String>()                 val deniedAndNeverAskAgain = ArrayList<String>()                 grantResults.forEachIndexed { index, result ->                     if (result != PackageManager.PERMISSION_GRANTED) {                         if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[index])) {                             denied.add(permissions[index])                         } else {                             deniedAndNeverAskAgain.add(permissions[index])                         }                     }                 }                 if (denied.isEmpty() && deniedAndNeverAskAgain.isEmpty()) {                     takePicture()                 } else {                     if (denied.isNotEmpty()) {                         AlertDialog.Builder(this).apply {                             setMessage("拍照功能需要您同意相冊和定位權限")                             setCancelable(false)                             setPositiveButton("確定") { _, _ ->                                 requestPermissions()                             }                         }.show()                     } else {                         AlertDialog.Builder(this).apply {                             setMessage("您需要去設置當中同意相冊和定位權限")                             setCancelable(false)                             setPositiveButton("確定") { _, _ ->                                 val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)                                 val uri = Uri.fromParts("package", packageName, null)                                 intent.data = uri                                 startActivityForResult(intent, 1)                             }                         }.show()                     }                 }             }         }     }      override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {         super.onActivityResult(requestCode, resultCode, data)         when (requestCode) {             1 -> {                 requestPermissions()             }         }     }      fun requestPermissions() {         ActivityCompat.requestPermissions(this,             arrayOf(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION), 1)     }      fun takePicture() {         Toast.makeText(this, "開始拍照", Toast.LENGTH_SHORT).show()     }  }

現在代碼已經變得比較長了,我還是帶著大家來梳理一下。

這里我在 onRequestPermissionsResult() 方法中增加了 denied 和 deniedAndNeverAskAgain  兩個集合,分別用于記錄拒絕和拒絕并不再詢問的權限。如果這兩個集合都為空,那么說明所有權限都被授權了,這時就可以直接進行拍照了。

而如果 denied 集合不為空,則說明有權限被用戶拒絕了,這時候我們還是彈出一個對話框來提醒用戶,并重新申請權限。而如果  deniedAndNeverAskAgain 不為空,說明有權限被用戶拒絕且不再詢問,這時就只能提示用戶去設置當中手動打開權限,我們編寫了一個 Intent  來執行跳轉邏輯,并在 onActivityResult() 方法,也就是用戶從設置回來的時候重新申請權限。

可以看到,當我們第一次拒絕權限的時候,會提醒用戶,相機和定位權限是必須的。而如果用戶繼續置之不理,選擇拒絕并不再詢問,那么我們將提醒用戶,他必須手動開戶這些權限才能繼續運行程序。

到現在為止,我們才算是把一個 “簡單”  的權限請求流程用比較完善的方式處理完畢。然而代碼寫到這里真的還算是簡單嗎?每次申請運行時權限,都要寫這么長長的一段代碼,你真的受得了嗎?

這也就是我編寫 PermissionX 這個開源庫的原因,在 Android 中請求權限從來都不是一件簡單的事情,但它不應該如此復雜。

PermissionX  將請求運行時權限時那些應該考慮的復雜邏輯都封裝到了內部,只暴露最簡單的接口給開發者,從而讓大家不需要考慮上面我所討論的那么多場景。

而我們使用 PermissionX 來實現和上述一模一樣的功能,只需要這樣寫就可以了:

class MainActivity : AppCompatActivity() {      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         PermissionX.init(this)             .permissions(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION)             .onExplainRequestReason { scope, deniedList ->                 val message = "拍照功能需要您同意相冊和定位權限"                 val ok = "確定"                 scope.showRequestReasonDialog(deniedList, message, ok)             }             .onForwardToSettings { scope, deniedList ->                 val message = "您需要去設置當中同意相冊和定位權限"                 val ok = "確定"                 scope.showForwardToSettingsDialog(deniedList, message, ok)             }             .request { _, _, _ ->                 takePicture()             }     }      fun takePicture() {         Toast.makeText(this, "開始拍照", Toast.LENGTH_SHORT).show()     }  }

可以看到,請求權限的代碼一下子變得極其精簡。

我們只需要在 permissions() 方法中傳入要請求的權限名,在 onExplainRequestReason() 和  onForwardToSettings() 回調中填寫對話框上的提示信息,然后在 request() 回調中即可保證已經得到了所有請求權限的授權,調用  takePicture() 方法開始拍照即可。

通過這樣的直觀對比大家應該能感受到 PermissionX  所帶來的便利了吧?上面那段長長的請求權限的代碼我真的是為了給大家演示才寫的,而我再也不想寫第二遍了。

另外,本篇文章主要只是演示了一下 PermissionX 的易用性,并不涉及其中具體的諸多用法,如 Android 11  兼容性,自定義對話框樣式等等。如果大家感興趣的話,更多用法請參考下面的鏈接。

  • Android 運行時權限終極方案,用 PermissionX 吧

  • PermissionX 現在支持 Java 了!還有 Android 11 權限變更講解

  • PermissionX 重磅更新,支持自定義權限提醒對話框

在項目中引入 PermissionX 也非常簡單,只需要添加如下的依賴即可:

dependencies {     ...     implementation 'com.permissionx.guolindev:permissionx:1.3.1' }

感謝各位的閱讀,以上就是“為什么說在Android中請求權限從來都不是一件簡單的事情”的內容了,經過本文的學習后,相信大家對為什么說在Android中請求權限從來都不是一件簡單的事情這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

自治县| 贵溪市| 房产| 延吉市| 梓潼县| 县级市| 犍为县| 云梦县| 高碑店市| 襄汾县| 庄浪县| 会理县| 塔河县| 通道| 池州市| 普定县| 辽中县| 衡阳市| 南充市| 兰州市| 梅河口市| 大英县| 平南县| 镇雄县| 葵青区| 云林县| 清徐县| 琼中| 马公市| SHOW| 西和县| 双流县| 陇西县| 西林县| 巴彦淖尔市| 阿拉善右旗| 大宁县| 泸水县| 金湖县| 越西县| 衢州市|