ae.kivy_sideloading

kivy mixin and widgets to integrate a sideloading server in your app

This namespace portion provides widgets and a mixin class for you main app instance to easily integrate and control the ae sideloading server <ae.sideloading_server> into your Kivy app.

kivy sideloading integration into your main app class

Add the SideloadingMainAppMixin mixin provided by this ae namespace portion to your main app class:

class MyMainAppClass(SideloadingMainAppMixin, KivyMainApp):

The sub app of the sideloading server will then automatically be instantiated when your app starts and will initialize the sideloading_app attribute with this sub app instance.

Hint

If you prefer to instantiate the sideloading server sub app manually then specify SideloadingMainAppMixin after KivyMainApp in the declaration of your main app class.

Adding sideloading_active to the :ref:`app state variables of your app’s config files will ensure that the running status of the sideloading server gets automatically stored persistent on pause or stop of the app for the next app start.

The running status of the sideloading server will be restored in the app start event handler method (on_app_start()).

To manually start it offering the APK of the embedding app call the on_sideloading_server_start() method passing an empty string and dict:

self.on_sideloading_server_start("", dict())

Hint

when you pass the dict with a number in a ‘port’ key then this number will be used as server listening port.

If no ‘port’ gets passed then SideloadingMainAppMixin will calculate an individual port number from the first character of the app_name of the app mixing in this class. This is to prevent the server socket error [Errno 98] Address already in use if two different applications with sideloading are running on the same device and want to offer sideloading.

To manually pause the sideloading server call the on_sideloading_server_stop() method passing an empty string and dict:

self.on_sideloading_server_stop("", dict())

usage of the sideloading button

This ae namespace portion is additionally providing the SideloadingButton flow button widget to integrate it in your Kivy app. This button can be used to:

  • start or stop the sideloading server,

  • select a file for sideloading via the FileChooserPopup.

  • display file info like full file path and file length.

  • display the URL of your sideloading server as QR code to allow connections from other devices.

To optionally integrate this SideloadingButton into your app add it to the root layout in your app’s main kv file with the id sideloading_button:

MyRootLayout:
    ...
    SideloadingButton:
        id: sideloading_button

If the sideloading server is not active and the user is clicking the SideloadingButton then this portion will first check if the Downloads folder of the device is containing a APK file for the running app and if yes then the sideloading server will be started providing the found APK file.

If the sideloading server is instead already running/active and the user is tapping on the SideloadingButton then a drop down menu will be shown with options to (1) display info of the sideloading file, (2) select a new file, (3) display the sideloading server URL as QR code or (4) stop the sideloading server.

dependencies/requirements in buildozer.spec

To build a Android APK with the kivy sideloading server integrated, make sure that the following external packages are specified in the requirements setting of the [app] section of your buildozer.spec file.

  • ae.kivy_file_chooser

  • ae.kivy_iterable_displayer

  • ae.kivy_qr_displayer

  • ae.kivy_sideloading

  • ae.sideloading_server

  • kivy_garden.qrcode

  • qrcode

Additionally all the packages and ae namespace portions required by the above packages have to be included. E.g. the GlslTester demo app includes the following packages:

requirements = android, hostpython3==3.7.5, python3==3.7.5, kivy==2.0.0,
    plyer, qrcode, kivy_garden.qrcode,
    ae.base, ae.files, ae.paths, ae.deep, ae.droid, ae.inspector, ae.i18n,
    ae.updater, ae.core, ae.literal, ae.console, ae.parse_date, ae.gui_app,
    ae.gui_help, ae.kivy_auto_width, ae.kivy_dyn_chi, ae.kivy_help,
    ae.kivy_relief_canvas, ae.kivy_app, ae.kivy_user_prefs, ae.kivy_glsl,
    ae.kivy_file_chooser, ae.sideloading_server, ae.kivy_sideloading,
    ae.kivy_iterable_displayer, ae.kivy_qr_displayer

sideloading server life cycle

To activate the sideloading server to offer a different file, specify the path (or glob file mask) of the file to be offered/available via sideloading in the sideloading_file_mask attribute and then call the method on_sideloading_server_start(). This method will check if the specified file exists and if yes then it will start the sideloading server. If you specify a file mask instead of a concrete file path then this method will check if exists exactly one file matching the file mask.

After the start of the sideloading server the sideloading_file_ext attribute will contain the file extension of the file available via sideloading.

The sideloading server will automatically be shut down on quit/close of the embedding app. You can alternatively stop the sideloading server manually at any time by calling the on_sideloading_server_stop() method.

Classes

SideloadingMainAppMixin()

mixin class with default methods for the main app class.

SideloadingMenuPopup(**kwargs)

dropdown menu to control sideloading server.

SideloadingMenuTour(main_app)

user preferences menu tour.

class SideloadingMenuPopup(**kwargs)[source]

Bases: ae.kivy_app.FlowDropDown

dropdown menu to control sideloading server.

__init__(**kwargs)[source]

add dynamic creation and refresh of children to this layout (Popup/Dropdown/…) widget.

_container: Widget
class SideloadingMenuTour(main_app)[source]

Bases: ae.gui_help.TourDropdownFromButton

user preferences menu tour.

__init__(main_app)[source]
page_ids: List[str]

list of tour page ids, either initialized via this class attribute or dynamically.

_saved_app_states: Dict[str, Any]
auto_switch_pages: Union[bool, int]

enable/disable automatic switch of tour pages.

set to True, 1 or -1 to automatically switch tour pages; True and 1 will switch to the next page until the last page is reached, while -1 will switch back to the previous pages until the first page is reached; -1 and 1 automatically toggles at the first/last page the to other value (endless ping-pong until back/next button gets pressed by the user).

the seconds to display each page before switching to the next one can be specified via the item value of the the dict page_data dict with the key ‘next_page_delay’.

page_data: Dict[str, Any]

additional/optional help variables (in help_vars key), tour and page text/layout/timing settings.

the class attribute values are default values for all tour pages and get individually overwritten for each tour page by the i18n translations attributes on tour page change via load_page_data().

supported/implemented dict keys:

  • app_flow_delay: time in seconds to wait until app flow change is completed (def=1.2, >0.9 for auto-width).

  • back_text: caption of tour previous page button (def=get_text(‘back’)).

  • fade_out_app: set to 0.0 to prevent the fade out of the app screen (def=1.0).

  • help_vars: additional help variables, e.g. help_translation providing context help translation dict/text.

  • next_text: caption of tour next page button (def=get_text(‘next’)).

  • next_page_delay: time in seconds to read the current page before next request_auto_page_switch() (def=9.6).

  • page_update_delay: time in seconds to wait until tour layout/overlay is completed (def=0.9).

  • tip_text or ‘’ (empty string): tour page tooltip text fstring message text template. alternatively put as first character a ‘=’ character followed by a tour page flow id to initialize the tip_text to the help translation text of the related flow widget, and the self help variable to the related flow widget instance.

  • tour_start_delay: seconds between tour.start() and on_tour_start main app event (def=TOUR_START_DELAY_DEF).

  • tour_exit_delay: seconds between tour.stop() and the on_tour_exit main app event (def=TOUR_EXIT_DELAY_DEF).

pages_explained_matchers: Dict[str, Union[ExplainedMatcherType, Tuple[ExplainedMatcherType, ...]]]

matchers (specified as callable or id-string) to determine the explained widget(s) of each tour page.

each key of this dict is a tour page id (for which the explained widget(s) will be determined).

the value of each dict item is a matcher or a tuple of matchers. each matcher specifies a widget to be explained/targeted/highlighted. for matcher tuples the minimum rectangle enclosing all widgets get highlighted.

the types of matchers, to identify any visible widget, are:

  • find_widget() matcher callable (scanning framework_win.children)

  • evaluation expression resulting in find_widget() matcher callable

  • widget id string, declared via kv lang, identifying widget in framework_root.ids

  • page id string, compiled from widgets app state/flow/focus via widget_page_id() to identify widget

page_idx: int

index of the current tour page (in page_ids)

last_page_idx: Optional[int]

last tour page index (None on tour start)

class SideloadingMainAppMixin[source]

Bases: object

mixin class with default methods for the main app class.

app_name: str
change_app_state: Callable
change_flow: Callable
dpo: Callable
framework_root: kivy.uix.widget.Widget
get_opt: Callable
show_message: Callable
user_specific_cfg_vars: set
vpo: Callable
file_chooser_initial_path: str = ''

used by file_chooser to select sideloaded file

file_chooser_paths: List[str] = []

recently used paths as app state for file chooser

sideloading_active: tuple = ()

app state flag if sideloading server is running

sideloading_app: ae.sideloading_server.SideloadingServerApp

http sideloading server console app

sideloading_file_ext: str = '.'

extension of selected sideloading file

sideloading_file_mask: str = ''

file mask of sideloading file

_init_default_user_cfg_vars()[source]
on_app_start()[source]

app start event.

on_app_started()[source]

initialize and start shaders after kivy app, window and widget root got initialized.

on_debug_level_change(level_name, _event_kwargs)[source]

debug level app state change flow change confirmation event handler.

Parameters
  • level_name (str) – the new debug level name to be set (passed as flow key).

  • _event_kwargs (Dict[str, Any]) – unused event kwargs.

Return type

bool

Returns

True to confirm the debug level change.

on_file_chooser_submit(file_path, chooser_popup)[source]

event callback from FileChooserPopup.on_submit() on selection of file.

Parameters
  • file_path (str) – path string of selected file.

  • chooser_popup (Widget) – file chooser popup/container widget.

on_sideloading_server_start(_flow_key, event_kwargs)[source]

start the sideloading server.

Parameters
  • _flow_key (str) – unused/empty flow key.

  • event_kwargs (Dict[str, Any]) – event kwargs: * ‘port’: TCP/IP server listening port. * ‘tap_widget’: button instance that initiated the start of the server.

Return type

bool

Returns

always True to confirm change of flow id.

on_sideloading_server_stop(_flow_key, _event_kwargs)[source]

stop a running sideloading http server.

Parameters
  • _flow_key (str) – unused/empty flow key.

  • _event_kwargs (Dict[str, Any]) – unused event kwargs.

Return type

bool

Returns

always True to confirm change of flow id.