Mercurial > libervia-desktop-kivy
diff cagou/core/platform_/android.py @ 400:71f51198478c
android: handle runtime permissions:
- some mandatory permissions are requested on Cagou start, Cagou won't start at all and
display a warning message if they are not granted (we request 5 times before showing the
warning)
- transfer plugin can now use "android_permissions" in plugin_info, to indicate what is
necessary. The permissions will then be requested, and the plugin widget won't be shown
if they are not granted (and a warning not will then be displayed)
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 09 Feb 2020 23:47:29 +0100 |
parents | a5457241c17f |
children | 788e05d1e2bf |
line wrap: on
line diff
--- a/cagou/core/platform_/android.py Sun Feb 09 23:47:29 2020 +0100 +++ b/cagou/core/platform_/android.py Sun Feb 09 23:47:29 2020 +0100 @@ -27,18 +27,26 @@ import mimetypes from jnius import autoclass, cast from android import activity +from android.permissions import request_permissions, Permission +from kivy.clock import Clock +from kivy.uix.label import Label from sat.core.i18n import _ from sat.core import log as logging from sat_frontends.tools import jid from cagou.core.constants import Const as C from cagou.core import dialog from cagou import G -from kivy.clock import Clock from .base import Platform as BasePlatform log = logging.getLogger(__name__) +# permission that are necessary to have Cagou running properly +PERMISSION_MANDATORY = [ + Permission.READ_EXTERNAL_STORAGE, + Permission.WRITE_EXTERNAL_STORAGE, +] + service = autoclass('org.salutatoi.cagou.ServiceBackend') PythonActivity = autoclass('org.kivy.android.PythonActivity') mActivity = PythonActivity.mActivity @@ -109,11 +117,56 @@ log.error(f"Error while getting profile to autoconnect: {failure_}") G.host.postInit() - def do_postInit(self): - G.host.bridge.profileAutoconnectGet( + def _show_perm_warning(self, permissions): + root_wid = G.host.app.root + perm_warning = Label( + size_hint=(1, 1), + text_size=(root_wid.width, root_wid.height), + font_size='22sp', + bold=True, + color=(0.67, 0, 0, 1), + halign='center', + valign='center', + text=_( + "Requested permissions are mandatory to run Cagou, if you don't " + "accept them, Cagou can't run properly. Please accept following " + "permissions, or set them in Android settings for Cagou:\n" + "{permissions}\n\nCagou will be closed in 20 s").format( + permissions='\n'.join(p.split('.')[-1] for p in permissions))) + root_wid.clear_widgets() + root_wid.add_widget(perm_warning) + Clock.schedule_once(lambda *args: G.host.app.stop(), 20) + + def permission_cb(self, permissions, grant_results): + if not all(grant_results): + # we keep asking until they are accepted, as we can't run properly + # without them + # TODO: a message explaining why permission is needed should be printed + # TODO: the storage permission is mainly used to set download_dir, we should + # be able to run Cagou without it. + if not hasattr(self, 'perms_counter'): + self.perms_counter = 0 + self.perms_counter += 1 + if self.perms_counter > 5: + Clock.schedule_once( + lambda *args: self._show_perm_warning(permissions), + 0) + return + + perm_dict = dict(zip(permissions, grant_results)) + log.warning( + f"not all mandatory permissions are granted, requesting again: " + f"{perm_dict}") + request_permissions(PERMISSION_MANDATORY, callback=self.permission_cb) + return + + Clock.schedule_once(lambda *args: G.host.bridge.profileAutoconnectGet( callback=self.profileAutoconnectGetCb, - errback=self.profileAutoconnectGetEb - ) + errback=self.profileAutoconnectGetEb), + 0) + + def do_postInit(self): + request_permissions(PERMISSION_MANDATORY, callback=self.permission_cb) return False def onProfilePlugged(self, profile): @@ -298,6 +351,20 @@ log.debug(msg) + def check_plugin_permissions(self, plug_info, callback, errback): + perms = plug_info.get("android_permissons") + if not perms: + callback() + perms = [f"android.permission.{p}" if '.' not in p else p for p in perms] + + def request_permissions_cb(permissions, granted): + if all(granted): + Clock.schedule_once(lambda *args: callback()) + else: + Clock.schedule_once(lambda *args: errback()) + + request_permissions(perms, callback=request_permissions_cb) + def open_url(self, url, wid=None): parsed_url = urlparse(url) if parsed_url.scheme == "geo":