Tasker
Home
Download
TaskerNet
Usage Examples
Pre-made Projects
FAQs
Guides
Reviews
Wiki
Plugin List
Forum
Support
Userguide (5.0+)
Index: en es fr zh
1 Page: en
More
Join
AutoApps
Developers
History
Privacy Policy
Release Notes
Next Version
Feature Requests
Report Issues

Developers: Plugins Library

You can use an Android library to make it very easy to implement a new plugin for Tasker. Simply add this to your gradle script:

   
       implementation 'com.joaomgcd:taskerpluginlibrary:0.3'
   

You can download a sample Tasker Plugin implementation, as well as check out the source code for this library here.

In the project you have the app module which is a collection of use cases examples for the library.

Check out all the examples along with their comments so you can see the various use cases that are possible with this.

Quick Start

Actions

To create a Tasker action (to change a setting or an action in your app), add something like the following to the manifest:

   
        <activity
            android:name=".ActivityConfigMySetting"
            android:exported="true"
            android:icon="@mipmap/ic_launcher"
            android:label="My Tasker Action">
            <intent-filter>
                <action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
            </intent-filter>
        </activity>
   

Then create a class that extends the TaskerPluginRunnerAction class

State Conditions

To create a Tasker state condition (a condition that can match or not match a situation at any given time, ie. a light being on or off; music is playing or not;) add something like the following to the manifest:

   
        <activity
            android:name=".ActivityConfigMyState"
            android:exported="true"
            android:icon="@mipmap/ic_launcher"
            android:label="My State Condition">
            <intent-filter>
                <action android:name="com.twofortyfouram.locale.intent.action.EDIT_CONDITION" />
            </intent-filter>
        </activity>
   

Then create a class that extends the TaskerPluginRunnerConditionState class

State Events

To create a Tasker state event (a condition that is instantly triggered and has no state, ie. user just pushed a button; new update for podcast is out;) add something like the following to the manifest:

   
        <activity android:name=".ActivityConfigMyEvent"
            android:exported="true"
            android:icon="@mipmap/ic_launcher"
            android:label="My Event Condition">
            <intent-filter>
                <action android:name="net.dinglisch.android.tasker.ACTION_EDIT_EVENT" />
            </intent-filter>
        </activity>
   

Then create a class that extends the TaskerPluginRunnerConditionEvent class

For each of these actions/conditions you need to:

  • Make your Config Activity extend the TaskerPluginConfig class
  • create a class that extends the TaskerPluginConfigHelper class

Here's a complete example for a very simple action that shows a toast with the text "Hello Tasker World" when ran.

   
      class HelloWorldActivity : ActivityConfigTaskerNoOutputOrInput() {
          override fun getNewHelper(config: TaskerPluginConfig) = HelloWorldHelper(config)

      }

      class HelloWorldHelper(config: TaskerPluginConfig) : TaskerPluginConfigHelperNoOutputOrInput(config) {
          override val runnerClass = HelloWorldRunner::class.java
          override fun addToStringBlurb(input: TaskerInput, blurbBuilder: StringBuilder) {
              blurbBuilder.append("This will show a toast saying 'Hello Tasker World'")
          }
      }

      class HelloWorldRunner : TaskerPluginRunnerActionNoOutputOrInput() {
          override fun run(context: Context, input: TaskerInput): TaskerPluginResult {
              "Hello Tasker World".toToast(context)
              return TaskerPluginResultSucess()
          }
      }
   

Main Concepts: Runner, Config Helper and Config

I'll intruduce the Runner, Config Helper and Config concepts using the "Hello World" example above.

Runner

   
      class HelloWorldRunner : TaskerPluginRunnerActionNoOutputOrInput() {
          override fun run(context: Context, input: TaskerInput<Unit>): TaskerPluginResult<Unit> {
              "Hello Tasker World".toToast(context)
              return TaskerPluginResultSucess()
          }
      }
   

A Runner is the class that will perform the actual action you want. When the runner is done it returns a TaskerPluginResult instance depending on what the result is: TaskerPluginResultSucess for success, TaskerPluginResultError when there's an error

Here the runner will simply create a toast with the text "Hello Tasker World" and return success

Runners have to extend one of these classes

  • TaskerPluginRunnerAction
  • TaskerPluginRunnerConditionState
  • TaskerPluginRunnerConditionEvent

In this case the Runner is extending TaskerPluginRunnerActionNoOutputOrInput because it's a Tasker action and it requires no input or output.

Config Helper

   
      class HelloWorldHelper(config: TaskerPluginConfig<Unit>) : TaskerPluginConfigHelperNoOutputOrInput<HelloWorldRunner>(config) {
          override val runnerClass = HelloWorldRunner::class.java
          override fun addToStringBlurb(input: TaskerInput<Unit>, blurbBuilder: StringBuilder) {
              blurbBuilder.append("This will show a toast saying 'Hello Tasker World'")
          }
      }
   

This will help you configure the plugin, which you will usually do in an Activity. It allows you to manipulate input and output variables, the resulting string blurb, amongst other things.

In this case it's only setting the String Blurb to "This will show a toast saying 'Hello Tasker World'" and indicating the runner class

ConfigHelpers have to extend the TaskerPluginConfigHelper class. In this case it extends the TaskerPluginConfigHelperNoOutputOrInput class because it doesn't need inputs or outputs.

Config

   
      class HelloWorldActivity : ActivityConfigTaskerNoOutputOrInput<HelloWorldRunner, HelloWorldHelper>() {
          override fun getNewHelper(config: TaskerPluginConfig<Unit>) = HelloWorldHelper(config)

      }
   

Usually an activity. It's a class that implements the various methods in TaskerPluginConfig and allows you to send inputs from the Activity to Tasker and vice-versa.

In this case the Config does nothing but intantiating the appropriate Config Helper.

Configs have to implement the TaskerPluginConfig interface. Because it's an interface they have to implement, Configs can have any other subclass they want. In this case this action is configured in an activity so it extends the ActivityConfigTaskerNoOutputOrInput activity which is a base activity for all of the plugin sample Configs.

Input and Output

Both actions and conditions can use Inputs and Outputs.

Inputs

This is the input for the GetIP example.

   
      @TaskerInputRoot
      class GetIPInput @JvmOverloads constructor(
              @field:TaskerInputField("separator", R.string.separator) var separator: String? = null,
              @field:TaskerInputObject("optionsip") var options: GetIPInputOptions = GetIPInputOptions()
      )

      @TaskerInputObject("options", R.string.options)
      class GetIPInputOptions @JvmOverloads constructor(
              @field:TaskerInputField("split", R.string.split) var split: Boolean = false
      )
   

Inputs are what is used by Configs to configure the Tasker action/condition. Think of them as input fields that a user can configure in your app

They will be sent to your config via the assignFromInput method, and you have to send them back to Tasker via the inputForTasker val:

   
    override fun assignFromInput(input: TaskerInput<GetIPInput>) = input.regular.run {
        editTextSeparator.setText(separator)
        checkboxSplit.isChecked = options.split
    }

    override val inputForTasker get() = TaskerInput(GetIPInput(editTextSeparator.text?.toString(), GetIPInputOptions(checkboxSplit.isChecked)))
   

In this example an EditText is assigned the separator input and a checkbox state is based on the split input.

You can also add dynamic input in the inputForTasker val if needed.

They will also be sent to your Runner when running the action/condition so you can have different behaviour based on your input:

   
    override fun run(context: Context, input: TaskerInput<GetIPInput>): TaskerPluginResult<GetIPOutput> {
      .....
    }
   

Here are a few rules for Inputs

  • An Input class has to have either the @TaskerInputRoot or @TaskerInputObject annotations
  • Each Input field has to be either an int, long, float, double, boolean, String, String[], ArrayList<String> or another Input Object
  • Each Input field has to have the @TaskerInputField annotation. These annotations are applied to the class fields themselves, and not on the getters or setters
  • Inputs can be nested. You can optionally apply the @TaskerInputField annotation on the nested object to give it a specific key.
  • Inputs are based on keys. If you change the keys between app versions those inputs will be lost for users
  • In Kotlin Input fields need to be var so that they can be written to by the library.

Outputs

This is the output for the GetArtists example.

   
      @TaskerOutputObject()
      class MusicArtist(
              @get:TaskerOutputVariable(R.string.artist, R.string.artist_label, R.string.artist_html_label) val name: String,
              val album: MusicAlbum,
              val songs: Array<MusicSong>

      )

      @TaskerOutputObject()
      class MusicSong(
              @get:TaskerOutputVariable(R.string.song, R.string.song_label, R.string.song_html_label) val name: String,
              @get:TaskerOutputVariable(R.string.duration, R.string.duration_label, R.string.duration_html_label) val duration: Int
      )
      @TaskerOutputObject()
      class MusicAlbum(
              @get:TaskerOutputVariable(R.string.album, R.string.album_label, R.string.album_html_label) val name: String
      )
   

Outputs are what are used by Runners to create Tasker variables from the action/condition.

In the Configs you need to specify the output class:

   
    override val outputClass = Array<MusicArtist>::class.java
   

In this example you can see that it's outputting an array of Music Artists

In the Runners you have to return them from the run method:

   
    override fun run(context: Context, input: TaskerInput<Unit>): TaskerPluginResult<Array<MusicArtist>> {
        val result = arrayOf(
                MusicArtist("Pearl Jam", MusicAlbum("Backspacer"), arrayOf(MusicSong("Even Flow", 200), MusicSong("Alive", 300))),
                MusicArtist("Rui Veloso", MusicAlbum("Mingos E Os Samurais"), arrayOf(MusicSong("Sayago Blues", 360), MusicSong("Dia De Passeio", 240)))
        )
        return TaskerPluginResultSucess(result)
    }
   

In this example it's outputting a list of artists where each has a name, an album name and a list of songs.

Here are a few rules for Outputs

  • An Output class has to have the @TaskerOutputObject annotation
  • Each Output value is converted to a string using its toString method
  • Each Output method has to have the @TaskerOutputVariable annotation. These annotations are applied to methods so you can have methods that output the values you want and not have backing fields for them
  • Outputs can be nested as long as each nested object has the @TaskerOutputObject annotation in its class declaration.
  • Array Outputs will automatically create Tasker variable arrays. Nested arrays (like in the example) will be joined in the output.

Update

Only Tasker event conditions have access to Updates. These are bits of data that are related to whichever event that happened.

This is the Update for the GotTime example

   
      @TaskerInputRoot
      class GotTimeUpdate @JvmOverloads constructor(@field:TaskerInputField("time") var time: Long? = null)
   

As you can see these behave just like Inputs so all the same rules apply.

Triggering Events/States

To trigger an event or state condition use the requestQuery method on the Activity you configured in the manifest (or the TaskerPluginRunnerCondition.requestQuery method if you're not using Kotlin).

This is an example that triggers the GotTime event:

   
        ActivityConfigGotTime::class.java.requestQuery(context, GotTimeUpdate(Date().time))
   

As you can see in this example you're sending a GotTimeUpdate object as an Update to the event.

Returning Result in Event/States Conditions

This is for the PlayStateChanged event example:

   
    override fun getSatisfiedCondition(context: Context, input: TaskerInput<PlayStateFilter>, update: PlayState?): TaskerPluginResultCondition<PlayState> {
        if (update?.playing == null) return TaskerPluginResultConditionUnsatisfied()
        val matchesPlaying = input.regular.isPlaying && update.playing
        val matchesStopped = input.regular.isStopped && !update.playing
        if (!matchesPlaying && !matchesStopped) {
            return TaskerPluginResultConditionUnsatisfied()
        }
        return TaskerPluginResultConditionSatisfied(context, update)
    }
   

A condition has to return either TaskerPluginResultConditionSatisfied, TaskerPluginResultConditionUnsatisfied or TaskerPluginResultConditionUnknown

In the example you can see that the condition is only satisfied if the playing state from the update matches the playing state that the user has configured.

This is how Tasker conditions will react to each state:

  • TaskerPluginResultConditionSatisfied:
    • Events: will trigger
    • States: will be enabled (or stay enabled if already in that state)
  • TaskerPluginResultConditionUnsatisfied:
    • Events: will not trigger
    • States: will be disabled (or stay disabled if already in that state)
  • TaskerPluginResultConditionUnknown:
    • Events: will not trigger
    • States: will not change state