From bc608d699f2abb0570297d8d41c5cd2d54ce337f Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Thu, 9 May 2019 10:56:28 +0100 Subject: [PATCH] feat: Allows registering the onRequestPermissionsResult callback. Adds an interface in PythonActivity and a method to register a Python function which will be called when the onRequestPermissionsResult callback is received. In android/permissions.py, a new function 'register_permissions_callback' is added to register a Python function (that takes three arguments) which will receive the three arguments of onRequestPermissionsResult. --- .../java/org/kivy/android/PythonActivity.java | 35 ++++++++++++++++-- .../android/src/android/permissions.py | 37 ++++++++++++++++++- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java index 425923433f..8193dbbd3e 100644 --- a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java @@ -581,7 +581,34 @@ public void onWindowFocusChanged(boolean hasFocus) { // call native function (since it's not yet loaded) } considerLoadingScreenRemoval(); - } + } + + /** + * Used by android.permissions p4a module to register a call back after + * requesting runtime permissions + **/ + public interface PermissionsCallback { + void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults); + } + + private PermissionsCallback permissionCallback; + private boolean havePermissionsCallback = false; + + public void addPermissionsCallback(PermissionsCallback callback) { + permissionCallback = callback; + havePermissionsCallback = true; + Log.v(TAG, "addPermissionsCallback(): Added callback for onRequestPermissionsResult"); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + Log.v(TAG, "onRequestPermissionsResult()"); + if (havePermissionsCallback) { + Log.v(TAG, "onRequestPermissionsResult passed to callback"); + permissionCallback.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } /** * Used by android.permissions p4a module to check a permission @@ -592,9 +619,9 @@ public boolean checkCurrentPermission(String permission) { try { java.lang.reflect.Method methodCheckPermission = - Activity.class.getMethod("checkSelfPermission", java.lang.String.class); + Activity.class.getMethod("checkSelfPermission", java.lang.String.class); Object resultObj = methodCheckPermission.invoke(this, permission); - int result = Integer.parseInt(resultObj.toString()); + int result = Integer.parseInt(resultObj.toString()); if (result == PackageManager.PERMISSION_GRANTED) return true; } catch (IllegalAccessException | NoSuchMethodException | @@ -612,7 +639,7 @@ public void requestPermissions(String[] permissions) { try { java.lang.reflect.Method methodRequestPermission = Activity.class.getMethod("requestPermissions", - java.lang.String[].class, int.class); + java.lang.String[].class, int.class); methodRequestPermission.invoke(this, permissions, 1); } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { diff --git a/pythonforandroid/recipes/android/src/android/permissions.py b/pythonforandroid/recipes/android/src/android/permissions.py index 6c2d384334..91198975ad 100644 --- a/pythonforandroid/recipes/android/src/android/permissions.py +++ b/pythonforandroid/recipes/android/src/android/permissions.py @@ -1,6 +1,6 @@ try: - from jnius import autoclass + from jnius import autoclass, PythonJavaClass, java_method except ImportError: # To allow importing by build/manifest-creating code without # pyjnius being present: @@ -421,6 +421,41 @@ class Permission: ) +class onRequestPermissionsCallback(PythonJavaClass): + """Callback class for registering a Python callback from + onRequestPermissionsResult in PythonActivity. + """ + __javainterfaces__ = ['org.kivy.android.PythonActivity$PermissionsCallback'] + __javacontext__ = 'app' + _callback = None # To avoid garbage collection + + def __init__(self, func): + self.func = func + onRequestPermissionsCallback._callback = self + super().__init__() + + @java_method('(I[Ljava/lang/String;[I)V') + def onRequestPermissionsResult(self, requestCode, permissions, grantResults): + self.func(requestCode, permissions, grantResults) + + +def register_permissions_callback(callback): + """Register a callback. This will asynchronously receive arguments from + onRequestPermissionsResult on PythonActivity after request_permission(s) + is called. + + The callback must accept three arguments: requestCode, permissions and + grantResults. + + Note that calling request_permission on SDK_INT < 23 will return + immediately (as run-time permissions are not required), and so this + callback will never happen. + """ + java_callback = onRequestPermissionsCallback(callback) + python_activity = autoclass('org.kivy.android.PythonActivity') + python_activity.addPermissionsCallback(java_callback) + + def request_permissions(permissions): python_activity = autoclass('org.kivy.android.PythonActivity') python_activity.requestPermissions(permissions)