Skip to content

Commit 3e26bee

Browse files
committed
fix: Convert Android permission int values to True/False
Add docstrings
1 parent 0d889bd commit 3e26bee

File tree

1 file changed

+64
-4
lines changed

1 file changed

+64
-4
lines changed

pythonforandroid/recipes/android/src/android/permissions.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ class Permission:
423423
)
424424

425425

426+
PERMISSION_GRANTED = 0
427+
PERMISSION_DENIED = -1
428+
429+
426430
class _onRequestPermissionsCallback(PythonJavaClass):
427431
"""Callback class for registering a Python callback from
428432
onRequestPermissionsResult in PythonActivity.
@@ -441,8 +445,7 @@ def onRequestPermissionsResult(self, requestCode,
441445

442446

443447
class _RequestPermissionsManager:
444-
"""Internal class for requesting Android permissions via
445-
requestPermissions, including registering callbacks to requestPermissions.
448+
"""Internal class for requesting Android permissions.
446449
447450
Permissions are requested through the method 'request_permissions' which
448451
accepts a list of permissions and an optional callback.
@@ -465,10 +468,18 @@ class _RequestPermissionsManager:
465468
onRequestPermissionsCallback, which allows the Java callback to be
466469
propagated to the class method 'python_callback'. This is then, in turn,
467470
used to call an application callback if provided to request_permissions.
471+
472+
The attribute '_callback_id' is incremented with each call to
473+
request_permissions which has a callback (the value '1' is used for any
474+
call which does not pass a callback). This is passed to requestCode in
475+
the Java call, and used to identify (via the _callbacks dictionary)
476+
the matching call.
468477
"""
469478
_java_callback = None
470479
_callbacks = {1: None}
471480
_callback_id = 1
481+
# Lock to prevent multiple calls to request_permissions being handled
482+
# simultaneously (as incrementing _callback_id is not atomic)
472483
_lock = threading.Lock()
473484

474485
@classmethod
@@ -484,7 +495,7 @@ def request_permissions(cls, permissions, callback=None):
484495
If 'callback' is supplied, the request is made with a new requestCode
485496
and the callback is stored in the _callbacks dict. When a Java callback
486497
with the matching requestCode is received, callback will be called
487-
with arguments of 'permissions' and 'grantResults'.
498+
with arguments of 'permissions' and 'grant_results'.
488499
"""
489500
with cls._lock:
490501
if not cls._java_callback:
@@ -502,13 +513,54 @@ def request_permissions(cls, permissions, callback=None):
502513
def python_callback(cls, requestCode, permissions, grantResults):
503514
"""Calls the relevant callback with arguments of 'permissions'
504515
and 'grantResults'."""
516+
# Convert from Android codes to True/False
517+
grant_results = [x == PERMISSION_GRANTED for x in grantResults]
505518
if cls._callbacks.get(requestCode):
506-
cls._callbacks[requestCode](permissions, grantResults)
519+
cls._callbacks[requestCode](permissions, grant_results)
507520

508521

509522
# Public API methods for requesting permissions
510523

511524
def request_permissions(permissions, callback=None):
525+
"""Requests Android permissions.
526+
527+
Args:
528+
permissions (str): A list of permissions to requests (str)
529+
callback (callable, optional): A function to call when the request
530+
is completed (callable)
531+
532+
Returns:
533+
None
534+
535+
Notes:
536+
537+
Permission strings can be imported from the 'Permission' class in this
538+
module. For example:
539+
540+
from android import Permission
541+
permissions_list = [Permission.CAMERA,
542+
Permission.WRITE_EXTERNAL_STORAGE]
543+
544+
See the p4a source file 'permissions.py' for a list of valid permission
545+
strings (pythonforandroid/recipes/android/src/android/permissions.py).
546+
547+
Any callback supplied must accept two arguments:
548+
permissions (list of str): A list of permission strings
549+
grant_results (list of bool): A list of bools indicating whether the
550+
respective permission was granted.
551+
See Android documentation for onPermissionsCallbackResult for
552+
further information.
553+
554+
Note that if the request is interupted the callback may contain an empty
555+
list of permissions, without permissions being granted; the App should
556+
check that each permission requested has been granted.
557+
558+
Also note that calling request_permission on SDK_INT < 23 will return
559+
immediately (as run-time permissions are not required), and so the callback
560+
will never happen. Therefore, request_permissions should only be called
561+
with a callback if calling check_permission has indicated that it is
562+
necessary.
563+
"""
512564
_RequestPermissionsManager.request_permissions(permissions, callback)
513565

514566

@@ -517,6 +569,14 @@ def request_permission(permission, callback=None):
517569

518570

519571
def check_permission(permission):
572+
"""Checks if an app holds the passed permission.
573+
574+
Args:
575+
- permission An Android permission (str)
576+
577+
Returns:
578+
bool: True if the app holds the permission given, False otherwise.
579+
"""
520580
python_activity = autoclass('org.kivy.android.PythonActivity')
521581
result = bool(python_activity.checkCurrentPermission(
522582
permission + ""

0 commit comments

Comments
 (0)