David T.
David T.

Reputation: 23371

How to PROPERLY check android permission dynamically

Multiple choice question:

which of the follow will correctly check whether or not an application has a certain permission declared in their AndroidManifest.xml?

getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED

or

getContext().getPackageManager().checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, getContext().getPackageName()) == PackageManager.PERMISSION_GRANTED

Basically, i got scared from the android documentation of what checkCallingOrSelfPermission claims -> it grants an IPC permissions if you just check for it?? what does that even mean? http://developer.android.com/reference/android/content/Context.html#checkCallingOrSelfPermission(java.lang.String)

So any explanation on the true differences would be awesome :D

*note: I am giving this code in a library, so i am only allowed to check permissions at runtime, unless you know of a better way.

Upvotes: 6

Views: 10476

Answers (3)

Laraib
Laraib

Reputation: 7036

You can use Context.checkCallingorSelfPermission() function for this. Here is an example

private boolean checkWriteExternalPermission()
{

    String permission = "android.permission.WRITE_EXTERNAL_STORAGE";
    int res = getContext().checkCallingOrSelfPermission(permission);
    return (res == PackageManager.PERMISSION_GRANTED);            
}

Upvotes: 0

dst
dst

Reputation: 3337

From my understanding (which might be wrong, as I did not work much with IPC, yet):

Given that your code is executed from another application (e.g. your library was not compiled into the application, but exposed to a third party using Binder or something like that), you can use checkCallingPermission to check if the third party application has the given permission, while checkCallingOrSelfPermission includes permissions from the application your library was compiled into.

You need to handle caller's permissions separately as you could leak permissions to other applications when checking the own permissions, too. From the security tips:

Do not leak permission-protected data. This occurs when your app exposes data over IPC that is only available because it has a specific permission, but does not require that permission of any clients of it’s IPC interface.

[...]

If providing an interface that does require access controls, use checkCallingPermission() to verify whether the caller has a required permission. This is especially important before accessing a service on behalf of the caller, as the identify of your application is passed to other interfaces.

The package manager way you describe checks only the permissions of the application your library was compiled into.

So, if your code is not executed from another process you probably don't have to care about the difference. Else, use the package manager way or clear the calling identity stuff if you're interested in whether you can perform an task; additionally check the caller's permissions if you wish to check if the calling process could perform the task, too.

Upvotes: 4

Phil
Phil

Reputation: 36289

You can use this method:

//for example, permission can be "android.permission.WRITE_EXTERNAL_STORAGE"
public boolean hasPermission(String permission) 
{
    try {
        PackageInfo info = getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
        if (info.requestedPermissions != null) {
            for (String p : info.requestedPermissions) {
                if (p.equals(permission)) {
                    return true;
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

Upvotes: 3

Related Questions