zobnin / aiolauncher_scripts

Scripts for the AIO Launcher
https://aiolauncher.app
86 stars 20 forks source link
android launcher lua

Introduction

Starting from version 4.0, AIO Launcher supports scripts written in the Lua scripting language. Scripts should be placed in the directory /sdcard/Android/data/ru.execbit.aiolauncher/files/.

There are three types of scripts:

The type of script is determined by the line (meta tag) at the beginning of the file:

Read more about meta tags at the end of the document.

Links

Changelog

5.3.5

5.3.1

5.3.0

Full changelog

Widget scripts

The work of the widget script begins with one of the three described functions. Main work should be done in one of them.

The on_resume() and on_alarm() callbacks are also triggered when a widget is added to the screen (if on_load() is not defined) and the screen is forced to refresh.

For most network scripts on_alarm() should be used.

Search scripts

Unlike widget scripts, search scripts are launched only when you open the search window:

Then the following function is triggered each time a character is entered:

The search script can use two functions to display search results:

When user click on a result, one of the following functions will be executed:

Both functions gets index of the clicked element (starting with 1) as an argument. Each function can return true or false, depending on whether the script wants to close the search window or not.

If you want the script to respond only to search queries that have a word in the beginning (prefix), use the appropriate meta tag. For example:

-- prefix="youtube|yt"

If you put such a tag at the beginning of your script, its on_search() function will only be called if a user types something like "youtube funny video" or "yt funny video". The prefix itself will be removed before being passed to the function.

Side menu scripts

With side menu scripts, you can display your own list in the menu. The script can be selected by pulling the menu down.

The script starts with the following function:

In this function, you must prepare a list and display it using one of the following functions:

The following functions are also available:

Clicking on list items will call on_click(index), long-clicking will call on_long_click(index), clicking a bottom icon will call on_button_click(index).

The list output functions support HTML and Markdown (see User Interface section for details).

API Reference

User Interface

Available only in widget scripts. _AIO Launcher also offers a way to create more complex UIs: instructions_

The ui:show_chart() function takes a string as its third argument to format the x and y values on the screen. For example, the string x: date y: number means that the X-axis values should be formatted as dates, and the Y-values should be formatted as a regular number. There are four formats in total:

Clicks

When you click on any element of the interface, the on_click(number) callback will be executed, where number is the ordinal number of the element. A long click calls on_long_click(number). For example, if you use ui:show_buttons to show three buttons, then clicking the first button will call on_click with argument 1, the second with arguments 2, and so on. If there is only one element on the screen, the argument will always be equal to one and can be omitted.

Folding

By default, the script shows either the first line of content or a line specified in the function argument in collapsed mode. However, you can change this behavior using a special meta-tag:

-- on_resume_when_folding = "true"

In this case, the on_resume() callback will be triggered each time the widget is collapsed. Then you can check the widget's collapsed status using the ui:folding_flag() function and display different UI depending on the state of this flag.

HTML and Markdown formatting

The functions ui:show_text(), ui:show_lines() and ui:show_table() support many HTML tags. For example:

First line<br/> Second line
<b>Bold Line</b><br/><i>Oblique Line</i>
<font color="red">Red text</font>
<span style="background-color: #00FF00">Text on green background</span>

You can also use Markdown markup. To do this, add the prefix %%mkd%% to the beginning of the line. Or you can disable the formatting completely with the prefix %%txt%%.

_Keep in mind: HTML formatting and icons will not work if you use the second parameter in ui:show_lines()._

Icons

You can insert FontAwesome icons inside the text, to do this use this syntax: `%%fa:ICON_NAME%%. For example:

ui:show_text("<b>This</b> is the text with icons %%fa:face-smile%% %%fa:poo%% <i>and styles</i>")

The ui:show_buttons() function supports Fontawesome icons. Simply specify fa:icon_name as the button name, for example: fa:play.

Note: AIO only supports icons up to Fontawesome 6.3.0.

Dialogs

Available only in widget scripts.

Dialog button clicks should be handled in the on_dialog_action(number) callback, where 1 is the first button, 2 is the second button, and -1 is nothing (dialog just closed). ui:show_radio_dialog() returns the index of the selected item or -1 in case the cancel button was pressed. ui:show_checkbox_dialog() returns the table of indexes or -1. ui:show_edit_dialog() returns text or -1.

If the first argument of the dialog contains two lines separated by \n, the second line becomes a subtitle.

List dialog accepts table as argument:

`title` - dialog title;
`lines` - table with strings to display;
`search` - true if the dialog should display a search string (default: true);
`zebra` - true if the dialog is to strip the colors of the lines into different colors (default: true);
`split_symbol` - symbol, which will be used as a line separator into right and left parts.

Text editor

Avaialble from: 4.4.1

Dialog accepts table as argument:

`text` - default text to show in the editor;
`new` - boolean value indicating that it is new note/task/etc;
`list` - boolean velue indicating that text should be shown as list with checkboxes;
`date` - date of the note/task/etc creation;
`due_date` - task completion date;
`colors` - a table of colors from which the user can choose;
`color` - default color`;
`checkboxes` - up to three checkboxes to display under text;

The values of these fields affect the appearance of the dialog. Any of these fields can be omitted.

When user closes the dialog by pressing one of the buttons at the bottom of the dialog (Save or Cancel), the on_dialog_action colbeck will be called, the parameter for which will be either -1 in case of pressing Cancel. Or a table of the following content:

`text` - text;
`color` - selected color;
`due_date` - selected task completion date;
`checked` - table of selected checkboxes;
`list` - boolean velue indication that text should be shown as list with checkboxes;

Context menu

Available only in widget scripts.

ui:show_context_menu({
    { "share", "Menu item 1" },
    { "copy",  "Menu item 2" },
    { "trash", "Menu item 3" },
})

Here share, copy and trash are the names of the icons, which can be found at Fontawesome.

When you click on any menu item, the collback on_context_menu_click(idx) will be called, where idx is the index of the menu item.

Meta widgets

Avaialble from: 4.7.0

The function takes a command table of this format as a parameter:

`battery` - battery progress bar;
`ram` - ram progress bar;
`nand` - nand progress bar;
`traffic` - traffic progress bar;
`screen` - screen time progress bar;
`alarm` - next alarm info;
`notes [NUM]` - last NUM notes;
`tasks [NUM]` - last NUM tasks;
`calendar [NUM]` - last NUM calendar events;
`exchage [NUM] [FROM] [TO]` - exchange rate FROM currency TO currency;
`player` - player controls;
`health` - health data;
`weather [NUM]` - weather forecast for NUM days;
`worldclock [TIME_ZONE]` - time in the given TIME_ZONE;
`notify [NUM]` - last NUM notifications;
`dialogs [NUM]` - last NUM dialogs;
`text [TEXT]` - just shows TEXT;
`space [NUM]` - NUM of spaces.

Sample.

System

The result of executing a shell command is sent to the on_shell_result(string) callback.

These two functions can be used to display, update, and delete system notifications. The possible fields for the table (each of them is optional) are:

`message` - the message displayed in the notification;
`silent` - true if the notification should be silent;
`action1` - the name of the first notification action;
`action2` - the name of the second notification action;
`action3` - the name of the third notification action.

When the notification is clicked, the main launcher window will open. When one of the three actions is clicked, the callback on_notify_action(idx, name) will be executed with the action's index and name as parameters.

Keep in mind that the callback will only be executed for scripts of type widget.

Intents

Intent table format (all fields are optional):

Launcher control

Format of table elements returned by aio:available_widgets():

`name` - internal name of the widget;
`label` - title of the widget;
`type` - widget type: `builtin`, `script` or `plugin`;
`description` - widget description (usually empty for non-script widgets);
`clonable` - true if the widget can have clones (examples: "My apps", "Contacts", "Mailbox" widgets);
`enabled` - true if the widget is placed on the screen.

Format of table elements returned by aio:active_widgets():

`name` - internal name of the widget;
`label` - widget visible name;
`position` - position on the screen;
`folded` - true if widget is folded.

Format of table elements returned by aio:actions():

`name` - action name;
`short_name` - action short name;
`label` - action name visible to the user;
`args` - action arguments if any.

To accept a value sent by the send_message function, the receiving script must implement a callback on_message(value).

The script can track screen operations such as adding, removing or moving a widget with the on_widget_action() callback. For example:

function on_widget_action(action, name)
    ui:show_toast(name.." "..action)
end

This function will be called on add, remove or move any widget.

It is also possible to process an swiping to right action (if this action is selected in the settings). To do this, create a function on_action:

function on_action()
    ui:show_toast("Action fired!")
end

To change the action of the settings icon in the widget's edit menu, you can add the on_settings() function to the script. It will be called every time the user presses the icon.

function on_settings()
    ui:show_toast("Settings icon clicked!")
end

Application management

The format of the apps table:

`pkg` - name of the app package (if it is cloned app or Android for Work app package name will also contain user id, like that: `com.example.app:123`);
`name` - name of the application;
`color` - application color;
`hidden` - true if the application is hidden;
`suspended` - true if the application is suspended;
`category_id` - category ID;
`badge` - number on the badge;
`icon` - icon of the application in the form of a link (can be used in the side menu scripts).

The format of the category table:

`id` - category id (id above 1000 are custom categories);
`name` - category name;
`icon` - category icon;
`color` - category color;
`hidden` - the category is hidden by the user.

Sorting options:

Any application-related events (installation, removal, name change, etc.) will call the on_apps_changed() callback (not in the search scripts).

Network

These functions do not return any value, but instead call the on_network_result(string, [code]) callback. The first argument is the body of the response, the second (optional) is the code (200, 404, etc.).

If id was specified in the request, then the function will call on_network_result_$id(string, [code]) instead of the callback described above. That is, if the id is "server1", then the callback will look like on_network_result_server1(string, [code]).

If there is a problem with the network, the on_network_error_$id callback will be called. But it does not have to be processed.

Calendar

Event table format:

`id` - event ID;
`calendar_id` - calendar ID;
`title` - title of the event;
`description` - description of the event;
`color` - color of the event;
`status` - status string of the event or empty;
`location` - address of the event by string;
`begin` - start time of the event (in seconds);
`end` - time of the event end (in seconds);
`all_day` - boolean value, which means that the event lasts all day.

Calendar table format:

`id` - calendar identifier;
`name` - name of the calendar;
`color` - color of the calendar in the format #XXXXXXXX.

The function calendar:request_permission() calls on_permission_granted() callback if the user agrees to grant permission.

Phone

Contacts table format:

`id` - contact id;
`lookup_key` - unique contact identifier;
`name` - contact name;
`number` - contact number;
`icon` - contact icon in the form of a link (can be used in the side menu scripts).

The function phone:request_permission() calls on_permission_granted() callback if the user agrees to grant permission.

Upon the first launch of the application, contacts may not yet be loaded, so in the scripts, you can use the on_contacts_loaded() callback, which will be called after the contacts are fully loaded.

Tasks

Avaialble from: 4.8.0

Once the tasks are loaded, the on_tasks_loaded() function will be executed.

The format of the task table:

`id` - task ID;
`text` - text;
`date` - date of creation;
`due_date` - deadline;
`completed_date` - task completion date;
`high_priority` - flag of high priority;
`notification` - flag of notification display;
`is_today` - is it today's task?

Notes

Avaialble from: 4.8.0

Once the notes are loaded, the on_notes_loaded() function will be executed.

The format of the note table:

`id` - note ID;
`text` - text;
`color` - note color ID;
`position` - note position on the screen.

Weather

Avaialble from: 4.1.0

Function returns the weather data in the on_weather_result(result) callback, where result is a table of tables with the following fields:

`time` - time in seconds;
`temp` - temperature;
`icon_code` - code of weather icon;
`humidity` - humidity;
`wind_speed` - wind speed;
`wind_direction` - wind direction.

Cloud

Avaialble from: 4.1.0

All data are returned in on_cloud_result(meta, content). The first argument is the metadata, either a metadata table (in the case of list_dir()) or an error message string. The second argument is the contents of the file (in the case of get_file()).

Profiles

Avaialble from: 5.3.6.

AI

Avaialble from: 5.3.5. Requires subscription.

All functions return an answer in the callback on_ai_answer. For example:

function on_alarm()
    ai:complete("Who are you?")
end

function on_ai_answer(answer)
    ui:show_text(answer)
end

Keep in mind that the launcher imposes certain limitations on the use of this module. If you use it too frequently, you will receive an error: rate limit instead of a response. Additionally, an error will be returned if the request includes too much text.

Reading notifications

Available only in widget scripts. Avaialble from: 4.1.3.

This module is intended for reading notifications from other applications. To send notifications, use the system module.

The notify:request_current() function asks for all current notifications. The Launcher returns them one by one to the on_notify_posted(table) callback, where table is the table representing the notification. The same callback will be called when a new notification appears. When the notification is closed, the on_notify_removed(table) colbeck will be called.

Notification table format:

`key` - a key uniquely identifying the notification;
`time` - time of notification publication in seconds;
`package` - name of the application package that sent the notification;
`number` - the number on the notification badge, if any;
`importance` - notification importance level: from 1 (low) to 4 (high), 3 - standard;
`category` - notification category, for example `email`;
`title` - notification title;
`text` - notification text;
`sub_text` - additional notification text;
`big_text` - extended notification text;
`is_clearable` - true, if the notification is clearable;
`group_id` - notification group ID;
`messages` - table of tables with fields: `sender`, `text`, `time` (_available from: 4.1.5_);
`actions` - table notifications actions with fields: `id`, `title`, `have_input` (_available from: 4.1.5_);

Keep in mind that the AIO Launcher also calls request_current() every time you return to the launcher, which means that all scripts will also get notification information in the on_notify_posted() callback every time you return to the desktop.

Files

Avaialble from: 4.1.3

All files are created in the subdirectory /sdcard/Android/data/ru.execbit.aiolauncher/files/scripts without ability to create subdirectories.

Rich UI

Starting with version 5.2.1, AIO Launcher includes an API that allows for displaying a more complex interface than what the high-level functions of the ui module allowed. For example, you can display text of any size, center it, move it up and down, display buttons on the left and right sides of the screen, draw icons of different sizes, and much more. Essentially, you can replicate the appearance of any built-in AIO widget.

Detailed instructions

App widgets

Starting from version 5.2.0, AIO Launcher supports interaction with app widgets through scripts. This means that you can create a wrapper for any app's widget that will fully match the appearance and style of AIO. You can also use this API if you need to retrieve information from other applications, such as the balance on your mobile phone account or your car's parking spot. If the application has a widget providing such information, you will be able to access it.

Detailed instructions

Settings

Deprecated in 4.7.4. Use Preferences module.

User can change settings through the dialog, which is available by clicking on the "gear" in the edit menu of the widget. If in the widget metadata there is a field arguments_help, its value will be shown in the edit dialog. If there is a field arguments_default - it will be used to get default arguments.

The standard edit dialog can be replaced by your own if you implement the on_settings() function.

Preferences

The prefs module is designed to permanently store the script settings. It is a simple Lua table which saves to disk all the data written to it.

You can use it just like any other table with the exception that it cannot be used as a raw array.

Sample:

prefs = require "prefs"

function on_resume()
    prefs.new_key = "Hello"
    ui:show_lines{prefs.new_key}
end

The new_key will be present in the table even after the AIO Launcher has been restrated.

The show_dialog() method automatically creates a window of current settings from fields defined in prefs. The window will display all fields with a text key and a value of one of three types: string, number, or boolean. All other fields of different types will be omittedi. Fields whose names start with an underscore will also be omitted. Script will be reloaded on settings save.

Animation and real time updates

Available only in widget scripts. Avaialble from: 4.5.2

The scripts API is designed in a way that every function that changes a widget's UI updates the entire interface. This approach makes the API as simple and convenient as possible for quick scripting, but it also prevents the creation of more complex scripts that change the UI state very often.

There are two modules to solve this problem: morph and anim. The first is used to change individual UI elements, the second is used to animate those elements.

Functions

Avaialble from: 4.1.3

Tasker

Avaialble from: 4.4.4

The run_own_task function takes as a parameter a list of Tasker commands in the following format:

COMMAND1 ARG1 ARG2 ARG3 ...;
COMMAND2 ARG2 ARG2 ARG3 ...;
...

The command itself can be specified either as a command ID or as a name (names can be found here). Unfortunately Tasker has no formal documentation on these commands, so you will have to rely on examples in this repository and Google search.

After task is done, the on_tasker_result(boolean) function will be called with the result of the command (successful or not).

If you want to pass data from the task to the script, you can use the broadcast intent ru.execbit.aiolauncher.COMMAND by adding the following line to the extra:

cmd:script:SCRIPT_FILE_NAME:DATA_STRING

Here SCRIPT_FILE_NAME is the name of the script or * if you want to pass data to all scripts. The DATA_STRING is the string with the data.

On the script side, you can accept this data in the on_command(string) callback.

Note: for these APIs to work you need to enable external control in Tasker: Tasker -> Preferences -> Misc -> Allow External Access. Also you need to enable external control of the launcher itself: AIO Settings -> Tasker -> Remote API.

Other

AIO Launcher includes the LuaJ 3.0.1 interpreter (compatible with Lua 5.2) with a standard set of modules: bit32, coroutine, math, os, string, table.

The modules io and package are excluded from the distribution for security reasons, the module os has been cut in functionality. Only the following functions are available: os.clock(), os.date(), os.difftime() and os.time().

The standard Lua API is extended with the following features:

AIO Launcher also includes:

Metadata

In order for AIO Launcher to correctly display information about the script in the script directory and correctly display the title, you must add metadata to the beginning of the script. For example:

-- name = "Covid info"
-- description = "Cases of illness and death from covid"
-- data_source = "https://covid19api.com"
-- arguments_help = "Specify the country code"
-- arguments_default = "RU"
-- type = "widget"
-- foldable = "false"
-- author = "Evgeny Zobnin (zobnin@gmail.com)"
-- version = "1.0"

Backward compatibiliy

AIO Launcher mantains backward compatibility with existing APIs. But if you want to use API functions which appeared later than 4.0.0 you'd better use a special meta tag which will hide your script on all previous versions of the application.

For example, let's say you want to use the weather module that appeared in version 4.1.3. In this case, add the following line to the script's metadata:

-- aio_version = "4.1.3"

You can also check the presence of a particular API function this way (note the use of a dot instead of a colon):

if ui.show_list_dialog then
    ui:show_text("list dialog is supported")
else
    ui:show_text("list dialog is not supported")
end

Debugging

Some tips on writing and debugging scripts:

Contribution

If you want your scripts to be included in the repository and the official AIO Launcher kit - create a pull request or email me: zobnin@gmail.com. Also I am always ready to answer your questions and discuss extending the current API.