Mercurial > libervia-desktop-kivy
diff cagou/core/platform_/android.py @ 342:89799148f894
core: use classes and factory to handle platform specific behaviours in a generic way
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 04 Jan 2020 16:24:57 +0100 |
parents | e2b51663d8b8 |
children | a3cefa7158dc |
line wrap: on
line diff
--- a/cagou/core/platform_/android.py Fri Jan 03 15:48:59 2020 +0100 +++ b/cagou/core/platform_/android.py Sat Jan 04 16:24:57 2020 +0100 @@ -17,12 +17,15 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys +import os +import socket from jnius import autoclass, cast from android import activity from sat.core import log as logging from cagou.core.constants import Const as C from cagou import G from kivy.clock import Clock +from .base import Platform as BasePlatform log = logging.getLogger(__name__) @@ -41,84 +44,108 @@ SOCKET_DIR = "/data/data/org.salutatoi.cagou/" SOCKET_FILE = ".socket" -# cache for callbacks to run when profile is plugged -cache = [] + +class Platform(BasePlatform): + + def __init__(self): + super().__init__() + # cache for callbacks to run when profile is plugged + self.cache = [] + + def init_platform(self): + # sys.platform is "linux" on android by default + # so we change it to allow backend to detect android + sys.platform = "android" + C.PLUGIN_EXT = 'pyc' + + def on_app_build(self, wid): + # we don't want menu on Android + wid.root_menus.height = 0 + + def on_host_init(self, host): + argument = '' + service.start(mActivity, argument) + activity.bind(on_new_intent=self.on_new_intent) + self.cache.append((self.on_new_intent, mActivity.getIntent())) + host.addListener('profilePlugged', self.onProfilePlugged) + + def on_initFrontendState(self): + # XXX: we use a separated socket instead of bridge because if we + # try to call a bridge method in on_pause method, the call data + # is not written before the actual pause + s = self._frontend_status_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(os.path.join(SOCKET_DIR, SOCKET_FILE)) + s.sendall(STATE_RUNNING) + + def onProfilePlugged(self, profile): + log.debug("ANDROID profilePlugged") + for method, *args in self.cache: + method(*args) + del self.cache + G.host.removeListener("profilePlugged", self.onProfilePlugged) + + def on_pause(self): + G.host.sync = False + self._frontend_status_socket.sendall(STATE_PAUSED) + return True -def on_new_intent(intent): - log.debug("on_new_intent") - Intent = autoclass('android.content.Intent') - action = intent.getAction(); - intent_type = intent.getType(); - if action == "android.intent.action.SEND": - # we have receiving data to share, we parse the intent data - # and show the share widget - data = {} - text = intent.getStringExtra(Intent.EXTRA_TEXT) - if text is not None: - data['text'] = text - item = intent.getParcelableExtra(Intent.EXTRA_STREAM) - if item is not None: - uri = cast('android.net.Uri', item) - data['uri'] = uri.toString() - path = getPathFromUri(uri) - if path is not None: - data['path'] = path + def on_resume(self): + self._frontend_status_socket.sendall(STATE_RUNNING) + G.host.sync = True + + def on_stop(self): + self._frontend_status_socket.sendall(STATE_STOPPED) + self._frontend_status_socket.close() + + def getPathFromUri(self, uri): + cursor = mActivity.getContentResolver().query(uri, None, None, None, None) + if cursor is None: + return uri.getPath() else: + cursor.moveToFirst() + # FIXME: using DATA is not recommended (and DATA is deprecated) + # we should read directly the file with + # ContentResolver#openFileDescriptor(Uri, String) + col_idx = cursor.getColumnIndex(DATA); + if col_idx == -1: + return uri.getPath() + return cursor.getString(col_idx) + + def on_new_intent(self, intent): + log.debug("on_new_intent") + Intent = autoclass('android.content.Intent') + action = intent.getAction(); + intent_type = intent.getType(); + if action == "android.intent.action.SEND": + # we have receiving data to share, we parse the intent data + # and show the share widget + data = {} + text = intent.getStringExtra(Intent.EXTRA_TEXT) + if text is not None: + data['text'] = text + item = intent.getParcelableExtra(Intent.EXTRA_STREAM) + if item is not None: + uri = cast('android.net.Uri', item) + data['uri'] = uri.toString() + path = self.getPathFromUri(uri) + if path is not None: + data['path'] = path + else: + uri = None + path = None + + Clock.schedule_once(lambda *args: G.host.share(intent_type, data), 0) + else: + text = None uri = None path = None - Clock.schedule_once(lambda *args: G.host.share(intent_type, data), 0) - else: - text = None - uri = None - path = None - - msg = (f"NEW INTENT RECEIVED\n" - f"type: {intent_type}\n" - f"action: {action}\n" - f"text: {text}\n" - f"uri: {uri}\n" - f"path: {path}") - - log.debug(msg) - - -def onProfilePlugged(profile): - log.debug("ANDROID profilePlugged") - global cache - for method, *args in cache: - method(*args) - del cache - G.host.removeListener("profilePlugged", onProfilePlugged) - + msg = (f"NEW INTENT RECEIVED\n" + f"type: {intent_type}\n" + f"action: {action}\n" + f"text: {text}\n" + f"uri: {uri}\n" + f"path: {path}") -def init_platform(): - # sys.platform is "linux" on android by default - # so we change it to allow backend to detect android - sys.platform = "android" - C.PLUGIN_EXT = 'pyc' - - -def host_init(host): - argument = '' - service.start(mActivity, argument) - - activity.bind(on_new_intent=on_new_intent) - cache.append((on_new_intent, mActivity.getIntent())) - host.addListener('profilePlugged', onProfilePlugged) - - -def getPathFromUri(uri): - cursor = mActivity.getContentResolver().query(uri, None, None, None, None) - if cursor is None: - return uri.getPath() - else: - cursor.moveToFirst() - # FIXME: using DATA is not recommended (and DATA is deprecated) - # we should read directly the file with - # ContentResolver#openFileDescriptor(Uri, String) - col_idx = cursor.getColumnIndex(DATA); - if col_idx == -1: - return uri.getPath() - return cursor.getString(col_idx) + log.debug(msg)