feat: add Locale automation integration and live Klick'r controls - #974
feat: add Locale automation integration and live Klick'r controls#974vibhor1102 wants to merge 14 commits into
Conversation
|
@Nain57, one remaining UI-organization choice to decide separately from the finalized Locale-plugin behavior: Should External Action remain a distinct Smart-scenario action, as implemented here, or should it be combined with the existing raw Intent action? I kept it separate because it gives Tasker/MacroDroid users an end-to-end friendly flow: name the signal in Klick'r, select the same name while configuring the host event, then use it as a normal automation trigger. The existing Intent action remains untouched for the developer/advanced use cases you mentioned in Discussion #949. However, since the raw Intent action is already useful and its dialog could potentially support multiple external-communication formats, I can merge this UI into it if that is the preferred long-term organization. This is the only remaining design choice from my side; the plugin surface, launch semantics, and background fallback are finalized. |
|
@Nain57 The decision remains open whether to:
|
76b180e to
7700196
Compare
8431ffa to
7db309b
Compare
|
Update: changed the ic_external_action.xml from older 24x24 viewport Material Icon to newer 960x960 viewport Material Symbol, consistent with the other Material Symbols used within the repository |
Summary
This PR adds a complete, user-facing integration between Klick'r and automation hosts implementing the Locale plug-in protocol, notably MacroDroid, Tasker, and LlamaLab Automate.
The original July scope from Discussion #949 was to replace difficult raw-intent setup with native host configuration screens, support loading/stopping scenarios, and let a Smart scenario emit a named event to an automation host. During August testing, the same standard protocol proved capable of something more broadly useful: live Klick'r state can be queried into host variables, and Klick'r can proactively request a fresh query whenever that state changes. This enables users to build their own conditions and flows rather than limiting the integration to a fixed set of commands.
The resulting integration contains five host-visible entries:
No host-specific MacroDroid, Tasker, or Automate implementation is used. The common Locale contract remains the integration boundary.
Temporary scenario-switcher dependency
The first five commits in this PR are not part of this feature review. They belong to the preceding scenario-switcher branch/PR and should be ignored here. This branch uses that work because status reporting and Run Current must recognize the switcher as an open child overlay. As soon as the scenario-switcher PR is merged, this branch will be rebased onto the updated
master, leaving only the eight automation-integration commits.Demonstrations
External Action
Screenrecorder-2026-07-09-14-37-15-704.mp4
The video shows the intended low-friction flow: assign a meaningful External Action name inside Klick'r, configure the matching event once in the automation host, and then use it as a normal trigger.
Launch Scenario and MediaProjection fallback
Screenrecorder-2026-07-12-13-40-16-410.1.mp4
The video first shows the notification continuation used when Android/OEM policy prevents the screen-capture prompt from opening in the background, then a launch where the required permission/session is already available.
Additional short demonstrations for Klick'r Status and Run current Klick'r scenario can be recorded if they would help review.
User-facing behavior and usage
Launch Klick'r scenario
In the automation host, the user adds the Klick'r action and selects a Smart or Dumb scenario from Klick'r's own configuration screen. The saved host action contains the scenario database ID and type, but those implementation details are never exposed to the user.
Execution resolves the ID against the current database. A deleted scenario fails safely. Launch means select/load and prepare, not automatically press Play. This preserves Klick'r's established safety model and allows the user to confirm the overlay before execution.
When replacing an already loaded scenario, Klick'r performs an orderly replacement. A Smart scenario can reuse an active MediaProjection session, avoiding another capture prompt. An already selected scenario is left alone instead of being restarted unnecessarily.
Typical uses include loading a game-specific scenario when the game opens, preparing different scenarios from a home-screen automation, or selecting Klick'r behavior as one step in a larger host flow.
Stop Klick'r
This is an immediately configured action with no scenario picker. It stops the current Klick'r session and removes the overlay. Calling it with no active scenario is harmless.
Run current Klick'r scenario
This deliberately does only one thing: move the currently loaded scenario from paused to running.
It runs only when all of these are true:
It is a silent no-op when there is no loaded scenario, the scenario is already running, the overlay is hidden, settings are open, the scenario switcher is open, or any other child overlay is above the root. In particular, a running scenario keeps its current session and is never stopped/restarted. Eligibility is checked beside the live service/engine state and checked again before Smart execution, including after a delayed billing flow, so a stale external request cannot override newly opened UI or unsaved edits.
This pairs naturally with Klick'r Status: a host can check for
paused, then invoke Run Current.Klick'r Status
This is a Locale condition plug-in that always returns a successful condition result when Klick'r can answer the query, allowing hosts to store both variables:
%klickr_scenario_name— visible scenario name, or an empty string when none is loaded.%klickr_scenario_state— one ofrunning,paused,hidden,settings, ornone.State precedence is:
settingswhen a child overlay is above the scenario root, including the scenario switcher;hiddenwhen the overlay stack is hidden;runningorpausedfor the loaded scenario;nonewhen no scenario is loaded or the accessibility service is unavailable.Klick'r emits the standard
REQUEST_QUERYsignal whenever the relevant state changes. Hosts therefore update immediately instead of relying on an undocumented polling interval. The requery marker includes the loaded scenario ID, so switching between two scenarios also refreshes the public scenario-name variable even when both have the same running state. Stop/unload, hide/show, settings navigation, pause/run, and scenario switching are all covered.This is intentionally general-purpose. Users can build conditions such as “only run my macro when Klick'r is paused,” display the active scenario elsewhere, react when the overlay is hidden, or combine Klick'r state with any other host variables/actions.
Klick'r external action
Smart scenarios gain an External Action action type carrying a non-empty, user-defined name. When executed, Klick'r sends a standard requery with that name in pass-through data. The host's configured Klick'r event becomes satisfied only when the configured name matches the fired name.
The scenario editor offers existing names for reuse so a signal can be shared consistently across events and scenarios. Names are identifiers, not secrets or authorization tokens. This allows Klick'r to delegate broad or device-specific work—changing system settings, controlling another app, sending messages, or running a complex macro—to the automation application designed for it, without expanding Klick'r with many niche actions.
The existing raw Intent action remains available and unchanged.
Protocol and host compatibility
The implementation follows the open Locale plug-in actions and bundle conventions:
EDIT_SETTING/FIRE_SETTINGfor actions;EDIT_CONDITION/QUERY_CONDITION/REQUEST_QUERYfor conditions and events;ResultReceiverdelivery where supplied;MacroDroid was the initially uncertain host because its UI does not explain when condition output variables are refreshed. End-to-end device testing confirmed that it accepts Klick'r's standard requery broadcast and updates the mapped variables immediately. The implementation contains no MacroDroid-only path. Tasker and Automate are expected to consume the same standard protocol; their final UI-level smoke tests can be done during beta testing.
Security and failure handling
FIRE_SETTINGis an exported protocol broadcast, so saved action configurations are encoded as JSON and signed with HMAC-SHA256 using a private AndroidKeyStore key. Klick'r verifies the reconstructed payload before resolving or executing it. Missing, malformed, unsigned, altered, or obsolete configurations are rejected. Scenario IDs are resolved from the live database at execution time.Condition variables and External Action names are intentionally public automation data and are not treated as secrets.
MediaProjection consent cannot be bypassed and cannot reliably be opened from every Android background state. For a Smart scenario without a reusable capture session, the launch flow:
Request IDs and persisted hand-off state prevent delayed activities, stale notification taps, or overlapping requests from reviving old work. Notification permission is optional, but disabling it means the fallback cannot be displayed.
Architecture
feature:external-launch; the existing tile continues to use the same shared service boundary.Caveats
settingsis a protective umbrella for any overlay above the scenario root, not only the scenario editor.nonealso covers an unavailable accessibility service; this avoids exposing a niche extra state to automation users.Validation
running,paused,hidden,settings, andnonetransitions, including stop/unload and hide/show behavior.git diff --check upstream/master...feature/automation-triggerpasses.Commit map
Temporary scenario-switcher base — ignore in this review
c66d5d324— feat: add scenario switcher foundationsd82e81c48— feat: add responsive scenario switcher dialogaf28b202e— feat: integrate pause-safe scenario switching44478d864— test: cover scenario switching and usage state099fb1434— feat: translate scenario switcher interfaceAutomation integration — this PR
bad03a227— refactor(external-launch): generalize Quick Settings module8c4040c29— feat(actions): add external actions to smart scenarios5df96a564— feat(locale): add signed scenario-control plugin configuration9f5bd7495— feat(locale): add external-action event plugin5c62380fd— feat(locale): execute scenario controls with safe launch fallbackd81817f4d— feat(locale): expose live Klick'r status11e489fa2— feat(locale): run the current paused scenario7db309b3e— feat(locale): translate automation integrationsAfter the scenario-switcher PR merges, this branch will be rebased and the final review history will contain only commits 6–13.
FAQ
Why use Locale plug-ins instead of asking users to send raw intents?
Raw intents remain useful for developers, but they expose package/action/extra details and provide poor discovery for ordinary automation users. Locale lets Klick'r provide its own picker/configuration UI inside the host while retaining a shared standard across applications.
Why is External Action separate from the existing Intent action?
It represents a named application-wide signal, closer to a reusable event/variable than a raw Android intent. Keeping it distinct improves discoverability, avoids complicating the advanced Intent editor, and allows the same name to be reused across scenarios. The existing Intent feature is preserved.
Why does Launch Scenario not press Play automatically?
Loading a scenario can require MediaProjection consent and changes the visible Klick'r session. Separating preparation from execution avoids surprising starts. Users wanting controlled execution can combine Launch Scenario, Klick'r Status, and Run Current in their host flow.
Why does Klick'r Status report the condition as satisfied even for
none?Hosts only persist output variables when the query itself succeeds.
noneis valid data, not a failed query. Returning success allows the host to replace stale values immediately when a scenario stops or accessibility becomes unavailable.Does MacroDroid poll these variables?
It can query conditions itself, but the integration does not depend on a polling schedule. Klick'r sends the standard requery request when its public status changes, and MacroDroid was observed updating mapped variables immediately.
Why only two status variables?
scenario_nameandscenario_stateare the generally actionable, user-facing information. Database IDs, scenario type, accessibility details, and a narrowly definedcan_runflag would expose internals or duplicate logic that the automation host can express itself.Can Run Current disrupt an already running scenario?
No. The live service checks that the scenario is paused and that the visible root overlay is unobstructed. A running session is left intact; the action does not toggle, stop, reload, or restart it.
What happens when settings or the switcher is open?
Status reports
settings, and Run Current does nothing. This prevents an automation from changing execution while the user has unsaved edits or is choosing another scenario.Are Tasker and Automate separate implementations?
No. Supporting three separate proprietary paths would increase maintenance and inconsistent behavior. The implementation uses their shared Locale-compatible protocol, with standard ordered-broadcast and Tasker ResultReceiver response forms.
Can the MediaProjection prompt be skipped?
Only when Klick'r already owns a reusable active capture session. Android requires user consent for a new projection. When Android cannot present it directly, Klick'r offers a notification continuation rather than attempting to bypass the platform restriction.
Can another app forge scenario-control commands?
Not through a saved Klick'r setting payload: action configurations are signed with an install-local AndroidKeyStore key and verified before execution. External Action names and status variables are deliberately non-secret public integration data.
Why are five unrelated commits visible?
This work currently depends on the unmerged scenario-switcher branch. They are shown transparently and listed above so reviewers can ignore them. They will be removed from this PR by rebasing immediately after the scenario-switcher work lands.
Are more demonstrations available?
Yes. The existing Launch Scenario and External Action videos remain above. Short focused recordings for live status variables, requery behavior, scenario switching, and Run Current can be added if requested.