Mike Korcha

Blog

Adding Tasker/Locale Support

A feature that was requested a couple times of my app Media Button Overlay was an action plugin for Tasker, an automation tool for Android. While working though this, I found that there weren't too many resources online, other than sample code. Now that I've figured it out, I've decided to write up how I did it for others in the future.

1. Build locale-api and include it as a dependency

Tasker uses Locale's API for interactions, allowing you to kill two birds with one stone and create a plugin for both. To do so, you either need to build the API or drop in a binary, depending on what you're doing.

2. Add related files to your project

These files are taken directly from Tasker's example plugin. The main ones we're concerned with involve keeping extras that we don't need out of Bundles, and working with extra data sent to Tasker.

The files you'll need are in the "src" directory:

  • Constants.java
  • PluginApplication.java
  • bundles/BundleScrubber.java
  • bundles/PluginBundleManager.java

Note that I prefer to keep these in their own package (which I name net.dinglisch.tasker), but you're free to do this how you please.

3. Add the Receiver

Apps can communicate with each other through the use of Intents. Tasker and Locale have their own specific Intents that they send to apps, which can respond to them. Once the Intent is received, it will execute whatever you assign to it.

// Make sure you import these!
import net.dinglisch.tasker.bundle.BundleScrubber;
import net.dinglisch.tasker.bundle.PluginBundleManager;

public class TaskerReceiver extends BroadcastReceiver {       
    @Override
    public void onReceive(final Context context, final Intent intent){
        // Make sure we're getting the right Intent
        if (!com.twofortyfouram.locale.Intent.ACTION_FIRE_SETTING.equals(intent.getAction())) return;

        // Clear it of any extras
        BundleScrubber.scrub(intent);

        Bundle bundle = intent.getBundleExtra(com.twofortyfouram.locale.Intent.EXTRA_BUNDLE);
        BundleScrubber.scrub(intent);

        // If the Bundle is valid, execute
        if(PluginBundleManager.isBundleValid(bundle)) {
            /*
             ...
             */
        }
    }
}

This is based on the sample code, which just checks that the Intent is valid before executing your plugin.

4. Add the Edit Activity

A requirement for Tasker plugins is an Activity that allows the user to edit settings. This activity would normally extend a class they created with their sample, however it had some code that depended on severely out of date Android version. This has the required bits of it, but does not subclass that functionality.

// Make sure to import these!
import net.dinglisch.tasker.Constants;
import net.dinglisch.tasker.bundle.BundleScrubber;
import net.dinglisch.tasker.bundle.PluginBundleManager;

public class TaskerActivity extends MainActivity {
    boolean mIsCancelled = false;

    // Your standard onCreate, do as you would a normal activity!
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*
         ...
         */
    }

    @Override
    public void finish() {
        if(this.mIsCancelled) return;

        // This string is what shows under "Configuration" in the Tasker interface. If you don't
        // have this set, you might not be able to get the plugin working properly
        String message = "Configured!";

        Intent resultI = new Intent();
        Bundle resultB = PluginBundleManager.generateBundle(getApplicationContext(), message);

        resultI.putExtra(com.twofortyfouram.locale.Intent.EXTRA_BUNDLE, resultB);
        resultI.putExtra(com.twofortyfouram.locale.Intent.EXTRA_STRING_BLURB, message);

        setResult(RESULT_OK, resultI);

        super.finish();
    }

    // Adds the Tasker menus at the top

    @Override
    public boolean onCreateOptionsMenu(final Menu menu){
        super.onCreateOptionsMenu(menu);

        getMenuInflater().inflate(com.twofortyfouram.locale.api.R.menu.twofortyfouram_locale_help_save_dontsave, menu);

        getActionBar().setDisplayHomeAsUpEnabled(true);

        try {
            getActionBar().setIcon(getPackageManager().getApplicationIcon(getCallingPackage()));
        }
        catch (final PackageManager.NameNotFoundException e) {
            if (Constants.IS_LOGGABLE)
                Log.w(Constants.LOG_TAG, "An error occurred loading the host's icon", e); //$NON-NLS-1$
        }

        return true;
    }

    // Handles menu item selection
    @Override
    public boolean onMenuItemSelected(final int featureId, final MenuItem item) {
        final int id = item.getItemId();

        if (android.R.id.home == id) {
            this.finish();
            return true;
        }

        else if (R.id.twofortyfouram_locale_menu_dontsave == id) {
            mIsCancelled = true;
            this.finish();
            return true;
        }

        else if (R.id.twofortyfouram_locale_menu_save == id) {
            this.finish();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

5. Update Manifest

Finally, in your AndroidManifest.xml, you need to add the proper Intent filters to the receiver and the activity, so that you actually respond when Tasker says to do something.

<activity
    android:name=".tasker.TaskerActivity"
    android:exported="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
    </intent-filter>
</activity>
<receiver
    android:name=".tasker.TaskerReceiver"
    android:exported="true"
    android:process=":background">
    <intent-filter>
        <action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
    </intent-filter>
</receiver>

6. Test

Plug it in, create a profile and test your new plugin. You should be able to get an example working easily with Toasts to ensure it is working; after that, just go to town on your code and create whatever plugin you can imagine!


  • tasker
  • android
  • java
Written 2014-04-07