# Actions for the Android SDK

Airship Actions provide a convenient way to automatically perform tasks by
name in response to push notifications, Message Center App Page interactions,
and JavaScript.


An action describes a function, which takes an optional argument
and performs a predefined task, producing an optional result.
Actions may restrict or vary the work they perform depending on the
arguments they receive, which may include type introspection and
runtime context.

The Airship SDK includes built-in actions for common tasks, and you can create custom actions to extend functionality.

For a complete list of available built-in actions, see the [Actions User Guide](https://www.airship.com/docs/guides/messaging/messages/actions/).

## Action Situations

Actions are triggered with extra context in the form of a Situation.
The different situations allow actions to determine if they should
run, and may perform different behavior depending on the situation.

| Description | Android |
|-------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
| Action was invoked manually. | [.SITUATION_MANUAL_INVOCATION](https://www.airship.com/docs/reference/libraries/android-kotlin/latest/urbanairship-core/com.urbanairship.actions/-action/-situation/-m-a-n-u-a-l_-i-n-v-o-c-a-t-i-o-n/index.html)
 |
| Action was invoked from a launched push notification. | [.SITUATION_PUSH_OPENED](https://www.airship.com/docs/reference/libraries/android-kotlin/latest/urbanairship-core/com.urbanairship.actions/-action/-situation/-p-u-s-h_-o-p-e-n-e-d/index.html)
 |
| Action is triggered when a notification is opened. | [.SITUATION_PUSH_OPENED](https://www.airship.com/docs/reference/libraries/android-kotlin/latest/urbanairship-core/com.urbanairship.actions/-action/-situation/-p-u-s-h_-o-p-e-n-e-d/index.html)
 |
| Action was invoked from JavaScript or a URL. | [.SITUATION_WEB_VIEW_INVOCATION](https://www.airship.com/docs/reference/libraries/android-kotlin/latest/urbanairship-core/com.urbanairship.actions/-action/-situation/-w-e-b_-v-i-e-w_-i-n-v-o-c-a-t-i-o-n/index.html)
 |
| Action was invoked from a foreground interactive notification button. | [.SITUATION_FOREGROUND_NOTIFICATION_ACTION_BUTTON](https://www.airship.com/docs/reference/libraries/android-kotlin/latest/urbanairship-core/com.urbanairship.actions/-action/-situation/-f-o-r-e-g-r-o-u-n-d_-n-o-t-i-f-i-c-a-t-i-o-n_-a-c-t-i-o-n_-b-u-t-t-o-n/index.html)
 |
| Action was invoked from a background interactive notification button. | [.SITUATION_BACKGROUND_NOTIFICATION_ACTION_BUTTON](https://www.airship.com/docs/reference/libraries/android-kotlin/latest/urbanairship-core/com.urbanairship.actions/-action/-situation/-b-a-c-k-g-r-o-u-n-d_-n-o-t-i-f-i-c-a-t-i-o-n_-a-c-t-i-o-n_-b-u-t-t-o-n/index.html)
 |
| Action was invoked from automation. | [.SITUATION_AUTOMATION](https://www.airship.com/docs/reference/libraries/android-kotlin/latest/urbanairship-core/com.urbanairship.actions/-action/-situation/-a-u-t-o-m-a-t-i-o-n/index.html)
 |

## Action Registry

The action registry is the central place to register actions by name.
Each entry in the registry contains an action, the names that the
action is registered under, a predicate that allows filtering when an
action should run, and allows specifying alternative actions for different
situations.


#### Kotlin


```kotlin
Airship.actionRegistry.registerEntry(setOf("my_action_name", "my_alias")) {
    ActionRegistry.Entry(action = CustomAction())
}
```



#### Java


```java
Airship.getActionRegistry().registerEntry(Set.of("my_action_name", "my_alias"), () -> {
    return new ActionRegistry.Entry(new CustomAction());
});
```





#### Kotlin


```kotlin
val entry = Airship.actionRegistry.getEntry("my_action_name")
```



#### Java


```java
ActionRegistry.Entry entry = Airship.getActionRegistry().getEntry("my_action_name");
```





#### Kotlin


```kotlin
// Predicate that will reject PUSH_RECEIVED, causing the action to never run during that situation.
val rejectPushReceivedPredicate: ActionPredicate = object : ActionPredicate {
    override fun apply(arguments: ActionArguments): Boolean {
        return SITUATION_PUSH_RECEIVED != arguments.situation
    }
}

// Update the entry with a new predicate
Airship.actionRegistry.updateEntry("my_action_name", predicate = rejectPushReceivedPredicate)
```



#### Java


```java
// Predicate that will reject PUSH_RECEIVED, causing the action to never run during that situation.
ActionPredicate rejectPushReceivedPredicate = new ActionPredicate() {
    @Override
    public boolean apply(ActionArguments arguments) {
        return !(SITUATION_PUSH_RECEIVED.equals(arguments.getSituation()));
    }
};

// Update the entry with a new predicate
Airship.getActionRegistry().updateEntry("my_action_name", null, Collections.emptyMap(), rejectPushReceivedPredicate);
```




## Triggering Actions

In addition to triggering actions from messages, you can trigger them programmatically.


#### Kotlin


```kotlin
// Running an action directly through the ActionRunRequest
ActionRunRequest.createRequest("actionName")
    .setSituation(SITUATION_MANUAL_INVOCATION)
    .setValue("actionValue")
    .run()

// Running an action by registered name
ActionRunRequest.createRequest("my_action_name")
    .setValue("actionValue")
    .run()

// An optional callback when finished
ActionRunRequest.createRequest("my_action_name")
    .setValue("actionValue")
    .run { arguments, result ->
        Logger.info("Action finished! Result: $result")
    }

// Block until the action finishes
val result = ActionRunRequest.createRequest("my_action_name").runSync()
```



#### Java



```java
// Running an action directly through the ActionRunRequest
ActionRunRequest.createRequest("actionName")
    .setSituation(Situation.MANUAL_INVOCATION)
    .setValue("actionValue")
    .run();

// Running an action by registered name
ActionRunRequest.createRequest("my_action_name")
    .setValue("actionValue")
    .run();

// An optional callback when finished
ActionRunRequest.createRequest("my_action_name")
    .setValue("actionValue")
    .run(new ActionCompletionCallback() {
        public void onFinish(ActionArguments arguments, ActionResult result) {
            Logger.info("Action finished!  Result: " + result);
        }
    });

// Block until the action finishes
ActionResult result = ActionRunRequest.createRequest("my_action_name").runSync();
```




## Custom Actions

The action framework supports any custom actions. Create an action by extending the `Action` base class on Android. After `takeOff`, register the action. The action can be triggered the same way as built-in actions.


#### Kotlin


```kotlin
class CustomAction : Action() {
    override fun acceptsArguments(arguments: ActionArguments): Boolean {
        if (!super.acceptsArguments(arguments)) {
            return false
        }

        // Do any argument inspections. The action will stop
        // execution if this method returns false.

        return true
    }

    override fun perform(arguments: ActionArguments): ActionResult {
        Log.i("CustomAction", "Action is performing!")
        return ActionResult.newEmptyResult()
    }
}
```



#### Java


```java
public class CustomAction extends Action {
    @Override
    public boolean acceptsArguments(ActionArguments arguments) {
        if (!super.acceptsArguments(arguments)) {
            return false;
        }

        // Do any argument inspections. The action will stop
        // execution if this method returns false.

        return true;
    }

    @Override
    public ActionResult perform(ActionArguments arguments) {
        Log.i("CustomAction", "Action is performing!");
        return ActionResult.newEmptyResult();
    }
}
```




> **Note:** On Android, custom actions may override the `shouldRunOnMainThread()` method to specify whether the action should
> be run on the main tread, or on a background thread. Implementations should take care to avoid long-running tasks,
> especially when running on the main thread.


