In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "why it is never a simple thing to ask for permission in Android". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn why it is never easy to ask for permission in Android.
Suppose I am developing a photo function, which usually requires camera permission and location permission, that is to say, these two permissions are prerequisites for me to implement the photo function. I must agree to these two permissions before I can continue to take pictures.
So how to apply for these two permissions? I believe everyone is familiar with the runtime permissions API provided by Android, so we can naturally write the following code:
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, 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 "you denied a permission. Unable to take pictures ", Toast.LENGTH_SHORT) .show ()} fun takePicture () {Toast.makeText (this," start taking pictures ", Toast.LENGTH_SHORT) .show ()}}
As you can see, the camera permission and location permission are requested by calling the requestPermissions () method, and then the result of the authorization is listened for in the onRequestPermissionsResult () method. If the user agrees to these two permissions, then we can take pictures, and if the user denies either permission, a Toast prompt pops up to tell the user that a permission has been denied, thus unable to take pictures.
Is it troublesome to write this way? This is a matter of benevolence and wisdom, and some friends may think that there are not many lines of code, so what's the trouble? But I personally think it's troublesome. Every time I need to request runtime permissions, I feel very tired and don't want to write such verbose code.
But let's not consider it from the point of view of simplicity for the time being, but from a correct point of view, is this correct? I think there is a problem, because when the permission is denied, we just play a Toast to remind the user that there is no follow-up action plan, and if the user really refuses a permission, the application will not be able to continue to use.
Therefore, we also need to provide a mechanism to re-request permissions when they are denied by the user.
Now I make the following changes to the code:
Class MainActivity: AppCompatActivity () {override fun onCreate (savedInstanceState: Bundle?) {super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) requestPermissions ()} override fun onRequestPermissionsResult (requestCode: Int, permissions: Array, 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 ("camera function requires you to agree to camera and positioning permissions") setCancelable (false) setPositiveButton ("OK") {_ _-> requestPermissions ()} .show ()} fun requestPermissions () {ActivityCompat.requestPermissions (this, arrayOf (Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION) 1)} fun takePicture () {Toast.makeText (this, "start taking pictures", Toast.LENGTH_SHORT) .show ()}}
Here I extract the code that requests permission into a requestPermissions () method, and then determine in onRequestPermissionsResult () that if the user refuses a permission, a dialog box pops up telling the user that camera and location permissions are required, and then call the requestPermissions () method in the click event of setPositiveButton to request permission again.
As you can see, we have now given more full consideration to the scenario in which permissions are denied.
So now this way of writing, does it take into account all the scenarios in which runtime permissions are requested? Actually, not yet, because the Android permissions system also provides a very "disgusting" mechanism to refuse and no longer ask.
When a permission is denied by the user once, the next time we apply for this permission, there will be an option on the interface to deny and no longer ask. As long as the user chooses this option, then we will not be able to request this permission after that, because the system will directly return that our permission has been denied.
This mechanism is very friendly to users because it can prevent some malware from repeatedly applying for permissions indefinitely, thus seriously harassing users. But for developers, it makes us miserable. What should I do if I have to rely on this permission to run a feature and now that the user refuses it and no longer asks?
Of course, the vast majority of users are not stupid, of course, know that the camera function requires camera permissions, I believe 99% of users will click to agree to authorization. But can we ignore the remaining 1% of users? No, because your company's test is the 1% of users, they will do this stupid operation.
In other words, even for the sake of the 1% of users, for this unlikely mode of operation, we still have to take this scenario into account in the program.
So, what should we do if the permission is denied and no longer asked? A more common way to deal with it is to remind users to manually set the open permissions, and if you want to do better, you can provide a function to automatically jump to the current application settings interface.
Let's improve on this scenario, as follows:
Class MainActivity: AppCompatActivity () {override fun onCreate (savedInstanceState: Bundle?) {super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) requestPermissions ()} override fun onRequestPermissionsResult (requestCode: Int, permissions: Array, grantResults: IntArray) {super.onRequestPermissionsResult (requestCode, permissions GrantResults) when (requestCode) {1-> {val denied = ArrayList () val deniedAndNeverAskAgain = ArrayList () 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 ("photo function requires you to agree to photo album and location permission") SetCancelable (false) setPositiveButton ("OK") {_ _-> requestPermissions ()}}. Show ()} else {AlertDialog.Builder (this). Apply {setMessage ("you need to go to the configuration to agree. Photo album and location permission ") setCancelable (false) setPositiveButton (" OK ") {_ _ > 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, "start taking photos" Toast.LENGTH_SHORT) .show ()}}
Now that the code has become longer, I'll take you to sort it out.
Here I add two sets, denied and deniedAndNeverAskAgain, to the onRequestPermissionsResult () method, which are used to record rejections and permissions that are no longer asked. If both collections are empty, then all permissions are granted, and you can take pictures directly.
If the denied collection is not empty, the permission has been denied by the user, so we still pop up a dialog box to remind the user and reapply for the permission. If the deniedAndNeverAskAgain is not empty, it means that the permission is rejected by the user and is no longer asked. In this case, the user can only be prompted to set the permission to open manually. We have written an Intent to execute the jump logic and reapply the permission in the onActivityResult () method, that is, when the user returns from the setting.
As you can see, when we deny permission for the first time, we remind the user that camera and location permissions are necessary. If the user continues to ignore it and chooses to refuse and no longer ask, then we will remind the user that he must manually open an account with these permissions to continue to run the program.
Until now, we have dealt with a "simple" permission request process in a relatively perfect way. But is it really easy to write the code here? Every time you apply for runtime permission, you have to write such a long piece of code, can you really stand it?
That's why I wrote PermissionX, an open source library. It's never easy to request permissions in Android, but it shouldn't be so complicated.
PermissionX encapsulates the complex logic that should be taken into account when requesting runtime permissions, exposing only the simplest interfaces to developers, so that you don't have to consider as many scenarios as I discussed above.
We use PermissionX to achieve exactly the same function as above, just write:
Class MainActivity: AppCompatActivity () {override fun onCreate (savedInstanceState: Bundle?) {super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) PermissionX.init (this) .requests (Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION) .onExplainRequestReason {scope DeniedList-> val message = "Photo function requires you to agree to album and location permissions" val ok = "OK" scope.showRequestReasonDialog (deniedList, message, ok)} .onForwardToSettings {scope DeniedList-> val message = "you need to set permission for photo albums and positioning" val ok = "OK" scope.showForwardToSettingsDialog (deniedList, message, ok)} .request {_ _ _-> takePicture ()} fun takePicture () {Toast.makeText (this, "start taking pictures", Toast.LENGTH_SHORT) .show ()}}
As you can see, the code that requests permissions suddenly becomes extremely concise.
We just need to pass in the name of the permission to be requested in the permissions () method, fill in the prompt information on the dialog box in the onExplainRequestReason () and onForwardToSettings () callbacks, and then ensure that all the requested permissions have been authorized in the request () callback, and call the takePicture () method to start taking pictures.
Through this intuitive comparison, you should be able to feel the convenience brought by PermissionX, right? I really wrote the long code asking for permission to show you, and I don't want to write it again.
In addition, this article mainly demonstrates the ease of use of PermissionX, and does not cover many specific uses, such as Android 11 compatibility, custom dialog style, and so on. If you are interested, please refer to the link below for more usage.
The ultimate solution of Android runtime permissions, use PermissionX.
PermissionX now supports Java! There is also an explanation of Android 11 permission change.
PermissionX blockbuster update to support custom permission reminder dialog box
Introducing PermissionX into the project is also very simple, as long as you add the following dependencies:
Dependencies {... Implementation 'com.permissionx.guolindev:permissionx:1.3.1'} Thank you for your reading. The above is the content of "Why it is never easy to request permission in Android". After the study of this article, I believe you have a deeper understanding of why it is never a simple thing to request permission in Android, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.