# Automation: adb and Tasker

> Let adb, Tasker, MacroDroid or any app that sends an Android intent switch language, theme, mode and more, with a switch per action and nothing allowed until you turn it on.

URL: https://wmkeyboard.pages.dev/reference/automation/
Section: Reference

WM Keyboard accepts commands from other apps as broadcast intents. Send them
from a computer with `adb`, or from an automation app such as Tasker,
MacroDroid or Automate. Put French on when you open one app, switch to a dark
theme at night, mute the key sound in a meeting, or show the keyboard from a
home-screen shortcut.

## Turning it on

Privacy / Let other apps control the keyboard

Nothing works until you turn on **Let other apps control the keyboard**. It is
off on a fresh install, and while it is off the keyboard ignores every command
in this page, layout switching included.

When it is on, an **Allowed actions** row appears under it. That screen has one
switch for each kind of command, in two groups:

Privacy / Allowed actions

| Row | Group | Default | Commands |
|---|---|---|---|
| Switch language and layout | Keyboard controls | On | `SET_LAYOUT`, `SET_LANGUAGE`, `NEXT_LAYOUT`, `PREVIOUS_LAYOUT`, `LIST_LAYOUTS` |
| Apply a keyboard mode | Keyboard controls | On | `SET_MODE` |
| Change the theme | Keyboard controls | On | `SET_THEME` |
| Show and pin the keyboard | Keyboard controls | On | `SHOW_KEYBOARD`, `SET_PINNED`, `SET_FLOATING_BUTTON` |
| Sound and haptics | Keyboard controls | On | `SET_KEY_SOUND`, `SET_HAPTICS` |
| Power saving and data saver | Keyboard controls | On | `SET_POWER_SAVING`, `SET_DATA_SAVER` |
| Size and position | Keyboard controls | On | `SET_POSITION` |
| Open a tool | Keyboard controls | On | `OPEN_TOOL` |
| Turn incognito on | Keyboard controls | On | `SET_INCOGNITO` with `enabled` true |
| Turn incognito off | Needs more trust | Off | `SET_INCOGNITO` with `enabled` false |
| Add and block words | Needs more trust | Off | `ADD_WORD`, `BLOCK_WORD` |
| Back up now | Needs more trust | Off | `BACKUP_NOW` |
| Pause and resume backups | Needs more trust | Off | `PAUSE_BACKUP`, `RESUME_BACKUP`, `PAUSE_SYNC`, `RESUME_SYNC` |
| Export data | Needs more trust | Off | `EXPORT_DATA` |
| Announce layout changes | Needs more trust | Off | The `LAYOUT_CHANGED` event the keyboard sends |
| Type text (not in the Google Play edition) | Needs more trust | Off | `TYPE_TEXT` |

The **Keyboard controls** each do what a control on the keyboard does, and you
can undo them. The **Needs more trust** rows change what the keyboard knows,
type into other apps, or tell other apps what you do, so each one stays off
until you turn it on by name. Turn one on only for an automation you set up
yourself.

A command whose row is off is refused, and the answer says which row to turn
on. The switches take effect on the next command, with nothing to restart.

## Sending a command

Every command is a broadcast to the package `com.wasimaster.wmkeyboard`, with
an action that starts `com.wasimaster.wmkeyboard.action.`. Name the package
with `-p`: Android 8 and newer do not deliver a broadcast to an app that the
sender doesn't name.

```sh
adb shell am broadcast -a com.wasimaster.wmkeyboard.action.SET_LANGUAGE -p com.wasimaster.wmkeyboard --es language fr
adb shell am broadcast -a com.wasimaster.wmkeyboard.action.SET_THEME -p com.wasimaster.wmkeyboard --es theme default
adb shell am broadcast -a com.wasimaster.wmkeyboard.action.SET_KEY_SOUND -p com.wasimaster.wmkeyboard --ez enabled false
```

`am broadcast` prints the keyboard's answer. A command that worked reads
`result=-1` and says what it did:

```
Broadcast completed: result=-1, data="builtin_french"
```

A command the keyboard can't carry out reads `result=0` and says why, for
example `no enabled layout is for the language "de"` or
`not allowed: turn on "theme" under Settings › Privacy › Allowed actions`.

### From Tasker

Tasker, MacroDroid and Automate each have an action that sends an intent. The
fields are the same in each. In Tasker:

1. Add the action **System › Send Intent**.
2. Set **Action** to `com.wasimaster.wmkeyboard.action.SET_LANGUAGE`.
3. Set **Extra** to `language:fr`.
4. Set **Package** to `com.wasimaster.wmkeyboard`.
5. Set **Target** to **Broadcast Receiver**.

Put the action in a task that an **App** profile starts, and the keyboard
changes language as that app opens. An automation app does not read the answer
the way `adb` does, so test a new command from `adb` first.

## Every command

All extras are strings unless the table says otherwise. The on/off commands
take `enabled` as a boolean (`--ez enabled true`) or as text (`true`, `false`,
`on`, `off`, `1`, `0`), which is what Tasker sends. Leave `enabled` out and the
command flips the current state.

| Action | Extras | Does | Needs the keyboard running |
|---|---|---|---|
| `SET_LAYOUT` | `layout`: layout id or name | Switches to that layout. | No |
| `SET_LANGUAGE` | `language`: language id, locale or name | Switches to a layout of that language. | No |
| `NEXT_LAYOUT` | none | One layout forward in your switch order. | No |
| `PREVIOUS_LAYOUT` | none | One layout back. | No |
| `LIST_LAYOUTS` | none | Changes nothing. Answers with the layouts you have on. | No |
| `SET_MODE` | `mode`: mode id or name, or `auto` | Applies a keyboard mode, as the Modes tool does. `auto` goes back to automatic. | Yes |
| `SET_THEME` | `theme`: theme id or name, or `default` | Picks the keyboard theme. | No |
| `SHOW_KEYBOARD` | none | Brings the keyboard up over the field in use. | Yes |
| `SET_PINNED` | `enabled` | Keeps the keyboard on screen, or stops. | No |
| `SET_FLOATING_BUTTON` | `enabled` | Shows the floating button, or takes it down. Without `enabled` it toggles. The button still needs Android's permission to draw over other apps, given once in the app. | No |
| `SET_KEY_SOUND` | `enabled` | Key sound on or off. | No |
| `SET_HAPTICS` | `enabled` | Vibration on key press on or off. | No |
| `SET_POWER_SAVING` | `enabled` | Power saving's manual switch. | No |
| `SET_DATA_SAVER` | `enabled` | Data saver's manual switch. | No |
| `SET_POSITION` | `position`: `normal`, `left`, `right`, `split` or `floating` | Puts the keyboard in that shape. Each one turns the others off. | No |
| `OPEN_TOOL` | `tool`: a tool name such as `TRANSLATE` or `EMOJI` | Opens that tool's panel. | Yes |
| `SET_INCOGNITO` | `enabled` | Incognito on or off. | No |
| `ADD_WORD` | `word` | Adds one word to your personal dictionary, as adding it by hand does. | Yes |
| `BLOCK_WORD` | `word`, and `language` if the block is for one language only | Stops the word being suggested. | No |
| `BACKUP_NOW` | none | Starts a backup to every location ticked under **Back up to** in Automatic backup. Fails when none is ticked. Runs even while backups are paused. | No |
| `PAUSE_BACKUP` | `hours`: 1 to 168, or left out for until resumed | Pauses the scheduled backups, as **Pause backups** does. Answers "paused for `<n>` h" or "paused until resumed". Any other `hours` is refused. | No |
| `RESUME_BACKUP` | none | Ends a backup pause. | No |
| `PAUSE_SYNC` | `hours`, as for `PAUSE_BACKUP` | Pauses the scheduled syncs, as **Pause sync** does. | No |
| `RESUME_SYNC` | none | Ends a sync pause and syncs straight away. | No |
| `EXPORT_DATA` | `sections`: a comma-separated list, or left out for `settings,dictionary` | Writes those parts of your data to `wm-keyboard-export.json` in the folder you picked. See [Exporting your data](#exporting-your-data). | No |
| `TYPE_TEXT` | `text`, or `snippet`: a snippet's trigger or label | Types into the field in use. | Yes |

"Needs the keyboard running" means WM Keyboard is the keyboard you have
selected. The other commands also work while a different keyboard is selected:
they change the setting, and WM Keyboard opens with it next time.

## How each one decides

- **`SET_LAYOUT`** takes the layout's id, such as `builtin_qwerty`. Case does
  not matter. It also takes the layout's name, such as `AZERTY`, but only when
  exactly one of your layouts has that name. When two share it, the command is
  refused, not guessed. Only layouts you turned on can be chosen.
- **`SET_LANGUAGE`** takes a language id (`en`, `bn`, `bn_rom`), a locale
  (`en-US`, `bn_BD`), or the language's name in English or in the language
  itself (`French`, `Français`). A locale the keyboard has no exact match for
  falls back to its first part, so `fr-CA` finds French. When you have several
  layouts of the language on, the one you used last wins. When a layout of it
  is already in use, nothing changes.
- **`NEXT_LAYOUT` and `PREVIOUS_LAYOUT`** walk your switch order and wrap
  around at either end. They always use the plain order, even with
  **🌐 goes back to the last language** on, so an automation gets the same
  result every time.
- **`SET_MODE`** and **`SET_THEME`** match an id first and then a name, and
  refuse a name that two modes or two themes share. A theme you made wins a
  name it shares with a built-in theme. A mode applied this way lasts like one
  picked from the Modes tool: until you change app, or until you change it,
  depending on your setting for that.
- **`SET_THEME` while the automatic light and dark pair is on** saves the pick,
  but the pair still decides what you see. The answer says so.
- **`OPEN_TOOL`** opens only tools that have a panel. Tools that act at once,
  such as Paste, Select all, Undo or the flashlight, are refused, because
  opening a tool should not change your text or your phone. The tool name is
  the one on [Deep links](https://wmkeyboard.pages.dev/reference/deep-links/) for `tool/{toolName}`, in any
  case.
- **`TYPE_TEXT`** types into the field that has the keyboard, never into a
  password field, and at most 10,000 characters at once. The Google Play
  edition leaves it out: the row is not on Allowed actions, and the command is
  refused with a reason even if a backup from another edition had it on. The
  GitHub and F-Droid editions keep it. A snippet is found by
  its trigger first and its label second, and expands exactly as a tap on it
  in the Snippets panel does.

### Finding the ids

Send `LIST_LAYOUTS` to see what you can switch to:

```sh
adb shell am broadcast -a com.wasimaster.wmkeyboard.action.LIST_LAYOUTS -p com.wasimaster.wmkeyboard
```

Each line holds a layout id, its language id and its name, separated by tabs,
in your switch order. A `*` marks the layout in use.

```
Broadcast completed: result=-1, data="* builtin_qwerty	en	QWERTY
  builtin_avro	bn	Avro phonetic"
```

For modes and themes, the name on screen works. It must be the name exactly as
you gave it, or for a built-in theme, its English name.

## Hearing about layout changes

With **Announce layout changes** on, the keyboard sends a broadcast every time
the layout on screen changes, whatever changed it:

| Action | Extras |
|---|---|
| `com.wasimaster.wmkeyboard.event.LAYOUT_CHANGED` | `layout` (id), `language` (language id), `name` (layout name) |

In Tasker, use the **Intent Received** event with that action. Tasker then has
`%layout`, `%language` and `%name` to work with. Any app on the phone that
listens gets the same broadcast, which is why the row is off by default: it
tells other apps which language you are typing in.

## Exporting your data

`EXPORT_DATA` lets an automation read what the keyboard has learned without
handing it over through an intent. It writes a file you can open yourself.

Privacy / Allowed actions / Export folder

Turn on **Export data**, then pick an **Export folder** in the group that
appears. Until you pick one the command is refused. An app can't name a
different place, because any app on the phone can send these commands: if the
sender chose the folder, a stranger app could send your dictionary to itself.

```sh
adb shell am broadcast -a com.wasimaster.wmkeyboard.action.EXPORT_DATA -p com.wasimaster.wmkeyboard --es sections dictionary,snippets
```

The answer means the export has started, and the file appears a moment later.
Each export replaces `wm-keyboard-export.json`, so the folder never fills up
with old copies.

- **`sections`** takes `settings`, `dictionary`, `snippets`, `emoji`,
  `statistics` and `vocab`. `dictionary` holds your words, their counts and the
  corrections the keyboard has learned. Anything else is refused.
- **Never in the file:** API keys and other passwords, your clipboard, your
  notes, and where your backups go.
- **The file is not encrypted.** Any app that can open the folder can read it,
  so pick a folder only the apps you trust can open. It is the same format as a
  backup, so restoring a backup can read it back.
- **You see each one.** Every export posts a notification, and the group keeps
  the last 20 with their time and what they held. It names the app that asked
  only on Android 14 and newer, and only if that app chose to give its name.

## Details & edge cases

- **The switch is a switch, not a password.** Any app on the phone can send
  these commands. What stops one is your setting, not who sent it. Android has
  no permission that Tasker could hold and a stranger app could not.
- **Nothing happens before the first unlock after a restart.** Android keeps
  apps from receiving broadcasts until you unlock the phone once. From then on
  the commands work on the lock screen too.
- **A layout switch is the same switch the 🌐 key makes.** A half-typed word is
  committed first, the suggestions change language at once, and the layout goes
  on your recently-used list. With **Remember language per app** on, the app you
  are typing in remembers it too.
- **A settings backup carries these switches.** Restore one on a new phone and
  **Let other apps control the keyboard** comes back as it was.
- **To open a settings screen instead,** use a `wmkeyboard://` link. See
  [Deep links & launcher shortcuts](https://wmkeyboard.pages.dev/reference/deep-links/).
