Create an action extension for IoTool

Action extension is used to execute certain code when triggered manually or by fulfilled condition set by the user in options menu. This can range from calling a number, to launching an application and more. We provide certain cations already, however there you may need a certain action that is not provided by us. This document will address general thing on how to create your own action for your device.

Naming your extension

Before we start, we need to address certain rules on naming the packages, classes etc. Extensions have to follow the naming rules in order to avoid interference between extensions. These rules are described in detail in a document found on this link. However we need to also address the differences in naming between sensor extension and action extension. First of, there is no ServiceID to name, but for the sake of making thing easier we should choose a name that reflects it. Secondly, the only mandatory types classes in this extension are and receiver. Thirdly, the naming rules are for packages and classes are the same. And lastly, all instances of our chosen ServiveID of the example code should be replaced by your chosen ServiceID.

Classes and Important Files

As above mentioned, action extension will usually only contain 2 types of classes (provider and multiple receiver classes). Additionally action extension will also contain JSON file called "raw.json". This file is important, because it links the UI input to the parameters used to process information in the receiver class. It also contains the type of UI input with which we get information.

"IoToolActionProvider" + ServiceID + ".java"

This gets the parameters needed to process data set by the user. It also contains the function that processes set data when triggered. Function that gets the parameters is called getInputParamNames.

@Override
protected String[] getInputParamNames(String... requiredParameters) {
    return new String[] { "phone_number" };
}

The function, that gets triggered, is onActionExecute, and it contains the code to execute set action. Example uses "getString" to get value from parameter. There are also other methods that return different type of value (for example getBoolean will return value type boolean).

@Override
protected void onActionExecute(Context context, Bundle args, Bundle extras) {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
        String uri = "tel:" + args.getString("phone_number");
        Intent intent = new Intent(Intent.ACTION_CALL);
        intent.setData(Uri.parse(uri));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    } else {
        requestPermissions(context, new String[] { Manifest.permission.CALL_PHONE });
    }
}

ServiceID+ "Provider.java"

This class is used to link the information between JSON files and parameters set in above class. It will most likely remain the same unless you change JSON file name and/or add new JSON file to the package to read from.

public class DeviceActionsProvider extends IoToolActionProvider {
    @Override
    protected int getActionsRawResourceId() {
        return R.raw.actions;
    }
}

"raw.json"

This file describes the link between UI elements and parameters, which type of UI element is used to get value for the parameter, etc. The root JSON object contains for variables:

  • package (the lowest level package that contains all provider and receiver in that package or subpackages or higher level packages)

  • description

  • developer

  • action (Array of JSON objects)

Each JSON object in array in action contains the following variables:

  • classname (remaining path to the certain receiver)

  • description (brief description)

  • params (Array of JSON objects)

Each JSON object in array in params contains the following variables:

  • type (class of the UI elemnt)

  • description (brief description)

  • values (Required only to define values for ActionInputListSpinner, etc. It contains array of strings)

List of all input types:

  • io.senlab.iotool.actions.input.ActionInputPhoneNumber

  • io.senlab.iotool.actions.input.ActionInputStringMultiline

  • io.senlab.iotool.actions.input.ActionInputInteger

  • io.senlab.iotool.actions.input.ActionInputString

  • io.senlab.iotool.actions.input.ActionInputBoolean

  • io.senlab.iotool.actions.input.ActionInputListSpinner

  • io.senlab.iotool.actions.input.ActionInputPassword

  • io.senlab.iotool.actions.input.ActionInputWifiDevice

  • io.senlab.iotool.actions.input.ActionInputReading

  • io.senlab.iotool.actions.input.ActionInputDataFile

Note: make sure that the parameters are defined in the same order as the order you get them in getInputParamNames.

{
  "package": "io.senlab.iotool.actionprovider.device",
  "description": "Device actions",
  "developer": "SenLab",
  "actions": [
    {
      "classname": "receiver.IoToolActionProviderDeviceCall",
      "description": "Call",
      "params": [
        {
          "type": "io.senlab.iotool.actions.input.ActionInputPhoneNumber",
          "description": "Phone number to call"
        }
      ]
    }
  ]
}