view cagou/core/platform_/android.py @ 322:e2b51663d8b8

core, android: new share widget + added Cagou to "share" menu: - new intent filter to add Cagou to share menu for all media types - minimum Kivy version is now 1.11.0 - new "Share" widget to display data to share via SàT and select the target - new core.platform_ module (the suffix "_" avoid trouble with standard "platform" module), for platform specific code. - Android intent are now checked on startup and "on_new_intent" events - if a android.intent.action.SEND action is received (i.e. some data is shared), the "Share" widget is shown - new Cagou.share method to share data using "Share" widget - new Cagou.getAncestorWidget method to easily retrieve an instance of a specific class in a widget's ancestors - ContactList's Avatar and ContactItem widgets have been moved to core.common
author Goffi <goffi@goffi.org>
date Fri, 06 Dec 2019 13:23:03 +0100
parents
children 89799148f894
line wrap: on
line source

#!/usr/bin/env python3

# Cagou: desktop/mobile frontend for Salut à Toi XMPP client
# Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org)

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys
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


log = logging.getLogger(__name__)

service = autoclass('org.salutatoi.cagou.ServiceBackend')
mActivity = autoclass('org.kivy.android.PythonActivity').mActivity
ImagesMedia = autoclass('android.provider.MediaStore$Images$Media')
AudioMedia = autoclass('android.provider.MediaStore$Audio$Media')
VideoMedia = autoclass('android.provider.MediaStore$Video$Media')
DATA = '_data'


STATE_RUNNING = b"running"
STATE_PAUSED = b"paused"
STATE_STOPPED = b"stopped"
SOCKET_DIR = "/data/data/org.salutatoi.cagou/"
SOCKET_FILE = ".socket"

# cache for callbacks to run when profile is plugged
cache = []


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
        else:
            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)


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)