• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Permission Questions

RhinoCan

Well-Known Member
I've been side-tracked on permissions for a couple of days now, trying to make my app behave the way the tutorials and videos say it should behave. I'm not having a lot of luck though.

I'm trying to write a little experimental app that determines a unique ID from the device it is running on. (I know this is a very dubious quest having stumbled on a StackOverflow discussion so my real app will NOT try to do this. But for now, I still want to finish my experimental app PURELY to learn the proper way of asking and getting permission and getting a unique ID serves that purpose as well as anything.

I've got a big problem in my experimental app. First, the line that says:
Java:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)                                                                    
      == PackageManager.PERMISSION_GRANTED) {
ALWAYS returns false, regardless of whether I have given permission in the manifest or not. My understanding, based on the information I've seen in tutorials and videos is that checkSelfPermission() should return true if the permission is granted in the manifest and false otherwise. Why is my app behaving differently?

Here's my permission:
Code:
<uses-permission android:name="READ_PHONE_STATE"/>

I'm 99% certain that syntax is right and that Android Studio would flag it anyway if it was wrong in some respect. This permission is also in the right place in the manifest: after the initial <manifest> tag but before the <application> tag.

Every video and tutorial tells you to put this permission in the manifest so I have done so but I'm really not clear on something. Does <uses-permission> really mean that the app has permission in advance and doesn't need to acquire permission when it is running? That would seem to be completely opposite to the Android 6.0 model (as I understand it) which says you should not ask for permission at install time but only at run time (at least for a "dangerous" permission like READ_PHONE_STATE). How is <uses-permission> making developers defer getting permission? Or is <uses-permission> simply information used by Android so that it knows in advance what permissions will be requested of the user at runtime? Also, do I need to create <uses-permission> entries for "safe" privileges too or does Android figure out for itself what it needs to get at install time by analyzing my code?

One other thing isn't clear to me either. This line:
Java:
       if (ActivityCompat.shouldShowRequestPermissionRationale(this,                                                
                Manifest.permission.READ_PHONE_STATE)) {
ALWAYS returns false. How do I make it return true? It's going to be hard to see if the code for showing the rationale works unless I can make the if return a true ;-)
 
ALWAYS returns false, regardless of whether I have given permission in the manifest or not

By putting that permission in the manifest, your app has not been granted it. Your code must then ask the user to grant it. Starting with Android 6.0, app permissions must be approved by the user individually. Before that, all permissions listed in the manifest were assumed to be granted, once the app was installed.
This may explain things:

https://developer.android.com/training/permissions/requesting
 
Here's the template:

Code:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Permission is not granted
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {
        // Show an explanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.
    } else {
        // No explanation needed; request the permission
        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
} else {
    // Permission has already been granted
}
 
By putting that permission in the manifest, your app has not been granted it. Your code must then ask the user to grant it. Starting with Android 6.0, app permissions must be approved by the user individually. Before that, all permissions listed in the manifest were assumed to be granted, once the app was installed.
This may explain things:

https://developer.android.com/training/permissions/requesting

I read the article and watched the video but it really doesn't answer my question.

Would you agree that requestSelfPermissions() should return TRUE if I have granted the necessary permission in the manifest, as I believe I have, and FALSE otherwise? Because that is definitely NOT what's actually happening. I get false regardless of whether I have the appropriate <uses-permissions> in the manifest. THAT is what is confusing me. Are there other aspects to whether requestSelfPermissions() returns true above and beyond the <uses-permissions>?

By the way, the article *does* may answer the other question I had, about why shouldShowPermissionsRationale() always returns false. Apparently if I previously checked "don't ask me again" on the permissions dialog, it remembers that and assumes that I never want to see the rationale ever again. I may well have checked that box at some point while testing my code although I don't specifically remember that. Do you have any idea how I could reset that so that it returns true so that I can test that path in my code?
 
Last edited:
Would you agree that requestSelfPermissions() should return TRUE if I have granted the necessary permission in the manifest, as I believe I have, and FALSE otherwise?

There is no requestSelfPermissions() method. Do you mean checkSelfPermissions()?

NO, I don't agree with the above statement. This method will not return TRUE if you have included the necessary permission in the manifest. As I said above, putting a permission in the manifest does not grant it. The user must still explicitly grant the permission, via a pop-up dialog.

Think about how an app works: First time you install it, if it needs READ_PHONE_STATE permission, it will ask you to grant it. Assuming you say 'yes', then thereafter, the app will have that permission granted. So checkSelfPermission() will only return true after the user has explicitly granted it, and not before.
 
By the way, the article *does* may answer the other question I had, about why shouldShowPermissionsRationale() always returns false. Apparently if I previously checked "don't ask me again" on the permissions dialog, it remembers that and assumes that I never want to see the rationale ever again. I may well have checked that box at some point while testing my code although I don't specifically remember that. Do you have any idea how I could reset that so that it returns true so that I can test that path in my code?

How are you testing your app? If it's on a real device, you could uninstall the app, then re-install it. If you're testing on the emulator, then just restart it.
 
I read the article and watched the video but it really doesn't answer my question.

Would you agree that requestSelfPermissions() should return TRUE if I have granted the necessary permission in the manifest, as I believe I have, and FALSE otherwise? Because that is definitely NOT what's actually happening. I get false regardless of whether I have the appropriate <uses-permissions> in the manifest. THAT is what is confusing me. Are there other aspects to whether requestSelfPermissions() returns true above and beyond the <uses-permissions>?
There is no requestSelfPermissions() method. Do you mean checkSelfPermissions()?

NO, I don't agree with the above statement. This method will not return TRUE if you have included the necessary permission in the manifest. As I said above, putting a permission in the manifest does not grant it. The user must still explicitly grant the permission, via a pop-up dialog.

Think about how an app works: First time you install it, if it needs READ_PHONE_STATE permission, it will ask you to grant it. Assuming you say 'yes', then thereafter, the app will have that permission granted. So checkSelfPermission() will only return true after the user has explicitly granted it, and not before.


Yes, that *was* the sound of the penny (or at least some coin) dropping! :-)

Thank you for illuminating my darkness :-) I did NOT correctly understand how checkSelfPermissions() worked. (And yes, I did misremember the name of the method when writing my remarks.) I did not realize that Android was (somehow) "remembering" whether permission had been granted previously or not. None of the articles I read actually talked about that. I assumed checkSelfPermissions() was reading the manifest to figure out what it could do that is apparently 100% wrong.

Hmm. That raises some new questions. The articles mention the distinction between "safe" and "dangerous" permissions. Am I correct in assuming that both "safe" and "dangerous" permissions need to be mentioned in the manifest in order for the app and that Android, knowing which ones are safe and which are dangerous, will ask for all the safe permissions at install time automatically? Or do I still need to write code to check for permission on even the "safe" permissions?
 
How are you testing your app? If it's on a real device, you could uninstall the app, then re-install it. If you're testing on the emulator, then just restart it.

I'm testing it on a real phone. Any time I touch the code, I click the Run button to test it again (or Debug 'app' if using the debugger). I assume both of those actions are effectively an uninstall/reinstall. Am I right? If not, what do I need to do to "reset" the app so that Android treats the permissions as if this is a first install?
 
I'm testing it on a real phone. Any time I touch the code, I click the Run button to test it again (or Debug 'app' if using the debugger). I assume both of those actions are effectively an uninstall/reinstall. Am I right? If not, what do I need to do to "reset" the app so that Android treats the permissions as if this is a first install?

You'll need to manually uninstall it from your phone, then reinstall from Android Studio.
 
Hmm. That raises some new questions. The articles mention the distinction between "safe" and "dangerous" permissions. Am I correct in assuming that both "safe" and "dangerous" permissions need to be mentioned in the manifest in order for the app and that Android, knowing which ones are safe and which are dangerous, will ask for all the safe permissions at install time automatically? Or do I still need to write code to check for permission on even the "safe" permissions?

https://developer.android.com/guide/topics/permissions/overview

"If your app lists normal permissions in its manifest (that is, permissions that don't pose much risk to the user's privacy or the device's operation), the system automatically grants those permissions to your app.

If your app lists dangerous permissions in its manifest (that is, permissions that could potentially affect the user's privacy or the device's normal operation), such as the SEND_SMS permission above, the user must explicitly agree to grant those permissions."
 
https://developer.android.com/guide/topics/permissions/overview

"If your app lists normal permissions in its manifest (that is, permissions that don't pose much risk to the user's privacy or the device's operation), the system automatically grants those permissions to your app.

If your app lists dangerous permissions in its manifest (that is, permissions that could potentially affect the user's privacy or the device's normal operation), such as the SEND_SMS permission above, the user must explicitly agree to grant those permissions."

How did I miss that line? Seriously, I've read several articles/tutorials on this and never saw that fact mentioned.

Thank you VERY much for all your help! The way this works is FINALLY starting to come together for me :-)
 
Cool. As with most new things, it's the odd nugget of useful information that brings it into focus.
 
Back
Top Bottom