Tasker
Home
Download
FAQs
Guides
Reviews
Wiki
Forum
Support
Userguide (5.0+)
Index: en es fr zh
1 Page: en
More
Developers
History
Privacy Policy
Release Notes
Next Version

Developers: Plugins

Tasker supports standard Android automation plugins. Any such plugins installed on the device will appear in the Plugins action (for settings plugins), state (for condition plugins) or Event category (a Tasker-only extension) in the Tasker UI.

Please see here for the base specification.

There is also an introduction to creating plugins for Tasker.

Tasker Limitations

  • Tasker only supports the value types int, long, float, double, boolean, String
  • String [] and ArrayList (from v4.3) values are also supported, as long as they are not null
  • bundle keys must match XML tag name constraints, due to how Tasker stores bundle data
  • the bundle key class is disallowed

Tasker Protocol Extensions

Tasker provides a few additions to the protocol to enable features which are not relevant to most automation 'host' apps. Most of these extensions require Tasker 4.2+.

If you want to take advantage of the Tasker extensions, you will need to copy TaskerPlugin.java into your plugin/host project (and change the pacakge name at the top to match).

Tasker Setting Plugin Extensions

Variable Replacement

The host can be requested do variable replacements on any String, String [] or ArrayList extras in a setting plugin bundle which are specified by the plugin.

In your plugin EditActivity:

   if ( TaskerPlugin.Setting.hostSupportsOnFireVariableReplacement( this ) )
      TaskerPlugin.Setting.setVariableReplaceKeys( resultBundle, new String [] { "com.sample.plugin.MYVALUE" } );

For the bundle key com.sample.plugin.MYVALUE, the host will scan for variable names and replace them with the current values of the variables in the host.

So if the following bundle values were passed to the host from the EditActivity...

Bundle KeyBundle Value (String)
com.sample.plugin.MYVALUEYour location is currently %LOC +- %LOCACC.
com.sample.plugin.MYOTHERVALUEI am %ONEHUNDRED sure this string won't be touched.

... then the following values might be passed to the BroadcastReceiver when the host triggers the action:

Bundle KeyBundle Value (String)
com.sample.plugin.MYVALUEYour location is currently -1.0,1.5 +- 500m
com.sample.plugin.MYOTHERVALUEI am %ONEHUNDRED sure this string won't be touched.

If the string values which are being replaced have an internal structure which could be broken by the values in the variables being replaced, you can specify this to the host via the setKeyEncoding function:

   if ( TaskerPlugin.hostSupportsKeyEncoding( this ) )
      TaskerPlugin.setKeyEncoding( resultBundle, new String [] { "com.sample.plugin.MYVALUE" }, TaskerPlugin.Encoding.JSON );

Synchronous Settings

The base plugin protocol only supports asynchronous settings; once the plugin has fired the host has no idea when it's finished or if it's worked and all it can do is hope for the best and continue. The Tasker plugin extensions provide a mechanism for the plugin to signal when it has finished, return completion status and set local variables in the task which called the plugin.

Firstly, in the EditActivity, the plugin may optionally indicate that it wishes to run synchronously by specifying a timeout:

   if (  TaskerPlugin.Setting.hostSupportsSynchronousExecution( getIntent().getExtras() ) )
      TaskerPlugin.Setting.requestTimeoutMS( resultIntentToHost, 3000 );

Note that the host may choose to ignore the requested timeout or even run the plugin completely asynchronously. From Tasker 4.7, you can find out which timeout the host is actually applying when the action fires using the function TaskerPlugin.Setting.getTimeoutHint() in FireReceiver. That may be useful for aborting processing if it can't be completed within the timeout period.

Secondly, in the plugin FireReceiver, the plugin knows that the host is waiting for it if isOrderedBroadcast() in onReceive returns true. If so, it can set a result and/or return some variables.

   if ( isOrderedBroadcast() )  {

      setResultCode( TaskerPlugin.Setting.RESULT_CODE_OK );

      if ( TaskerPlugin.Setting.hostSupportsVariableReturn( intent.getExtras() ) ) {
         Bundle vars = new Bundle();
         vars.putString( "%pcolour", "boo" );

         TaskerPlugin.addVariableBundle( getResultExtras( true ), vars );
      }
   }          

Note that the default result is OK, you can skip setResultCode in the case where there were no problems.

If your plugin cannot complete it's processing within the onReceive() function, put this code at the end of onReceive() instead:

   if ( isOrderedBroadcast() ) 
      setResultCode( TaskerPlugin.Setting.RESULT_CODE_PENDING );

This tells the host that you will send a separate completion intent at a later time.

When you're finished processing, probably in a Service, signal finish like this:

   TaskerPlugin.Setting.signalFinish( context, fireIntentFromHost, TaskerPlugin.Setting.RESULT_CODE_OK, varsBundle );

fireIntentFromHost is the second argument in FireReceiver.onReceive(). The third argument indicates the completion status. The final argument is an optional (use null if unneeded) bundle of variable values that will be applied by the host.

Error Reporting (Tasker 4.6+)

When the response code indicates failure, it's placed in the local variable %err in the task, so that the user can take an appropriate action if they wish (the user must have configured the plugin action with Continue On Error to do that).

In addition to the built-in responses, plugins can return their own customized failure codes using any integer from Setting.RESULT_CODE_FAILED_PLUGIN_FIRST upwards.

Plugins can also optionally set a human-readable error message by including a variable with name Setting.VARNAME_ERROR_MESSAGE in the appropriate parameter of addVariableBundle and addRelevantVariableList.

The error message variable should only be set when the BroadcastReceiver response code indicates a failure.

Relevant Variables

It might be useful for the plugin to know which variables the user might want the plugin to set. The host can pass these 'relevant' variables to the plugin EditActivity. They can be retrieved by the plugin as follows (typically in onCreate()):

   if ( TaskerPlugin.hostSupportsRelevantVariables( getIntent().getExtras() ) )
      String [] passedNames = TaskerPlugin.getRelevantVariableList( getIntent().getExtras() );

It might also be useful for the host to know which variables a plugin is likely to set upon completion. Tasker, for example, can use this information to show the user a variable selection list for subsequent actions in the task.

Specify that in your EditActivity just before setResult():

   if ( TaskerPlugin.hostSupportsRelevantVariables( getIntent().getExtras() ) )
      TaskerPlugin.addRelevantVariableList( resultIntent, new String [] { 
         "%pcolour\nPet Colour\nThe colour of the pet <B>last bought</B>"
      } );

The variable specification consists of 3 parts separated by newline characters:

  • the variable name
  • a localized (if possible) human-readable label in plain text format
  • an optional, localized (if possible) human-readable description of what the variable contains at which times etc in HTML

The variable name and label are mandatory, the description is optional.

Tasker Condition Plugin Extensions

Condition Variables

Condition plugins can stipulate variable names and values (in a Bundle) which will be visible in any tasks that run as a result of a change in plugin state.

Example code in BroadcastReceiver.onReceive():

   if ( TaskerPlugin.Condition.hostSupportsVariableReturn( intent.getExtras() ) ) {
      Bundle varsBundle = new Bundle();

         varsBundle.putString( "%colour", "red" );

      TaskerPlugin.addVariableBundle( getResultExtras( true ), varsBundle );
   }

Relevant Variables

'Relevant' variables are also supported for condition plugins. The intention is that the user should be shown in the host UI any variables which may be passed by the plugin to the host.

The code is the same as for a settings plugin EditActivity (see here).

Tasker Event Plugin Extension

The base protocol supports a plugin which can tell the host app whether a condition is currently true or not e.g. there is an unread SMS. This corresponds to a Tasker state context.

However, many plugins are more event based i.e. Tasker should be notified if something has happened e.g an SMS has been received. This corresponds to a Tasker event context.

From Tasker 4.3, event plugins are supported as a third class of plugin next to the setting (action) and condition (state) types.

From the point of view of the plugin developer, event plugins are almost identical to condition plugins. When developing an event plugin you can follow all the same documentation and code except for taking into account the following differences:

  • the plugin EditActivity should listen (with the IntentFilter in its Manifest) for the action net.dinglisch.android.tasker.ACTION_EDIT_EVENT instead of the previous EDIT_CONDITION.

  • when the host queries the plugin via QUERY_CONDITION, only the SATISFIED result code will be acted upon by the host. UNSATISFIED or UNKNOWN will be ignored.

  • when the plugin sends a REQUEST_QUERY intent, it should add a message ID to the intent with TaskerPlugin.addPassThroughMessageID() and when it receives a QUERY_CONDITION it should check the message ID. This serves three purposes.
    1. it prevents some security problems such as rogue apps sending false data under pretences of being the host
    2. it allows the plugin to associate each QUERY_CONDITION with an event which occured
    3. it allows plugins which need to use a service to be kickstarted by the host e.g. after a reboot; when the plugin doesn't see a message ID in a REQUEST_QUERY, it knows that the intent is not as a result of an event occuring and can be ignored.

Note that the plugin still has to ask the host to query it for the SATISFIED result code. The main reasons are to maintain as much compatibility as possible, ease transition and maintain security.

If the plugin wishes, it can pass through an event data bundle when it request the host to query if via QUERY_REQUEST, see addPassThroughData/retrievePassThroughData. In this case, it's still advisable to add a message ID as described above.

Notes

Variables

Each host may have different requirements on variable names and values. For instance, Tasker requires all variable names passed from a plugin be lower-case (i.e. be 'local' variables).

You may wish to check the validity of any variable names used since they'll be rejected by Tasker otherwise and it may not be clear to the user where the bad variable name is coming from:

   if ( TaskerPlugin.variableNameValid( "%colour" ) )
      varBundle.put( "%colour", "red" );
Tasker-Generated Apps
From Tasker 1.2.2, Tasker supports generation of standalone apps which can be installed on phones other than the one on which the app was generated.

If the user has configured a plugin condition or action, the stored Bundle data will also be carried over to the new app.

For that reason you should store all data in the passed Bundle if possible because otherwise your plugin won't work when installed on new devices when distributed e.g. via Play Store. It's beneficial to a plugin developer to be included in user-generated apps because the child app will prompt for installation of your plugin at runtime and thus increase it's presence.

Clearly, this advice does not apply to sensitive user data such as passwords. If you need to store such data locally in your plugin application, then your plugin is not going to work when distributed as an app and the user will discover that during testing and just have to live with it.

Identifying Plugins
From version 4.8u2, Tasker identifies plugins by a combination of their type, package name and class name of the edit activity. That means that if your package name changes e.g. between beta and release, your users will need to delete and recreate their plugin configurations.