Air Actions

Overview

S Pen is connected to the device by BLE (Bluetooth Low Energy), and the connection is managed by the S Pen Framework.

BLE events are not directly sent to the app, but the S Pen Framework converts them to KeyEvents before sending them to app.

Figure 1 Use Case Scenario

Therefore, apps can handle an S Pen event by recycling the existing KeyEvent-Callback without the need to add other interfaces.

The S Pen Remote Event handling and the process of sending the defined KeyEvent to the apps is outlined in the figure below.

Collecting S Pen Remote Events published by Apps

Figure 2 S Pen Remote Events Collection

The KeyEvents received by the apps are defined in an .xml format and make them public, and the S Pen Framework collects and manages them.

Sending S Pen Remote Events to Apps

Figure 3 S Pen Remote Events Transmission

  1. A BLE event is sent to the S Pen Framework.

  2. S Pen Framework checks for the foreground app and looks for the KeyEvent that the app made public.

  3. The found KeyEvent is sent to the app's KeyEvent-Callback.

  4. The app performs the actions defined in the KeyEvent.

To facilitate the app functionality, the app must define the RemoteActions and follow the implementation process below.

Implementation of RemoteActions

Specifying the KeyEvent to be Mapped to S Pen Remote Event in a Manifest

  1. Check for the activity to handle the KeyEvent in a manifest file (AndroidManifest.xml).

  2. Add <intent-filter> and <meta-data> elements to that activity.
    An .xml resource file defining RemoteActions must be specified for <meta-data>.

<manifest xmlns:android="http://schemas.android.com/apk/res/android
   package="com.samsung.android.blesample ">

	<application ... >
	   <activity android:name="SampleActivity" >
		  <intent-filter>
			  <action android:name="com.samsung.android.support.REMOTE_ACTION" />
		  </intent-filter>

		  <meta-data android:name="com.samsung.android.support.REMOTE_ACTION"
							 android:resource="@xml/remote_action_sample"/>
	   </activity>
		...
	</application>
</manifest>
  1. Create an .xml file under res/xml/.

    (Name the file with the same name as the resource specified in Step 2.)

    Figure 4 Sample Resource Tree

    The XML has a root element of , and may include several elements. In addition, each contains information about id, label, priority, trigger_key, etc.

Structure of the XML file

<?xml version="1.0" encoding="utf-9">
<remote-actions version="float"
enable_key="string">
   <action
      id="string"
      label="@string/resource_name"
      priority="int"
      trigger_key="string"
      repeatable=["true" | "false"]
      repeatable_interval=["short" | "medium" | "long" | "int"]>
      <preference name="gesture" value=["click", "double_click", "swipe_left", 
                    "swipe_right", "swipe_up", "swipe_down", "circle_ccw", "circle_cw"]/>
      <preference name="button_only" value=["true" | "false"]/>
      <preference name="motion_only" value=["true" | "false"]/>
   </action>
</remote-actions>

<remote-actions>

syntax:

<remote-actions version="float">
            ...
</remote-actions>

can contain:

<action>

description:

This element contains one or more action elements

attribute:

  • version

    • Mandatory
    • Latest version is 1.2
  • actionset_label

    • Optional
    • It is the title of App Action Card to be displayed on the S Pen Remote Setting Screen. If it's not specified, then the app name is used by default.
    • Only String Resource ID within the app package is allowed.
  • enable_key

    • Optional
    • It is the value that is set to a default ON in the Air Actions setting of your app.
    • The value differs for each app, and it needs to be issued by a Samsung internal.

<action>

syntax:

<action   id="string"
    label="@string/resource_name"
    priority="int"
    trigger_key="string"
    repeatable=["true" | "false"]
    repeatable_interval=["short" | "medium" | "long" | "int"]>
     . . .
</action>

contained in:

<remote-actions>

can contain:

<preference>

description:

Defines the key events mapped to the S Pen gesture and the information to be displayed on the Air actions settings screen.

attribute:

  • id

    • Mandatory
    • It requires an action-specific unique ID.
    • Duplicate specification of the same ID is not allowed.
    • Only alphabet, numeric, or underscore are allowed.
  • label

    • Mandatory
    • Label of Action to be displayed on the S Pen Remote Setting Screen.
    • Only String Resource ID within the app package is allowed.
  • priority

    • Mandatory

    • Duplicate specification of the same priority is not allowed.

    • The smaller the number, the higher the priority (1: highest priority).

    • Version 1.0

      • Based on the priority, 1 is mapped to a single click gesture and 2 is mapped to a double click gesture. 3 and afterward are registered to the App action list as candidate action.
    • Version 1.2

      • The position of this action is determined in the App action list. The default gesture is determined by the preferece Tag.
  • trigger_key

    • Mandatory

    • Define the KeyEvent to be received by the app.

    • Use the symbolic name of the keycode defined in Android KeyEvent.java, but exclude the

      "KEYCODE_" part

      Example: KEYCODE_PAGE_UP → trigger_key="PAGE_UP"

    • You can define a KeyShortcut by using "+" as a delimiter.

      Example 1: Combination of KEYCODE_CTRL_LEFT and KEYCODE_N

      → trigger_key="CTRL_LEFT+N"

      Example 2: Combination of KEYCODE_CTRL_LEFT, KEYCODE_SHIFT_LEFT, and KEYCODE_Z

      → trigger_key="CTRL_LEFT+SHIFT_LEFT+Z"

  • repeatable

    • Optional
    • Set to true when this action is repeatable.
    • Version 1.2
  • repeatable_interval

    • Optional (Mandatory if repeatable attribute exist)

    • Can be short, medium, long or int type:

      • short : 300ms
      • medium : 500ms
      • long : 1000ms
      • int type : 50~3000
    • Version 1.2

<preference>

Optional

Version 1.2

syntax:

<preference name="gesture" value=["click", "double_click", "swipe_left", "swipe_right", 
                                "swipe_up", "swipe_down", "circle_ccw", "circle_cw"]/>
<preference name="button_only" value=["true" | "false"]/>
<preference name="motion_only" value=["true" | "false"]/>

contained in:

<action>

description:

Determines the default gesture to be mapped and checks whether this action is a button press or motion gesture

attribute:

  • name

    Should be set to "gesture", "button_only", "motion_only"

    • "gesture": Set the type of gesture you want to set as default
    • "button_only" : Provide the action only for button press
    • "motion_only" : Provide the action only for motion related gestures
  • value

    • if name="gesture", any or all of the following strings are valid values for this attribute.

      Multiple values are separated by '|' - for example, " click| swipe_down| swipe_down ".

      value Gesture type Description
      “click” Button Single click
      “double_click” Button Double click
      “swipe_left” Motion Swipe left ←
      “swipe_right” Motion Swipe right →
      “swipe_up” Motion Swipe up ↑
      “swipe_down” Motion Swipe down ↓
      “circle_ccw” Motion Circle Counter-clock-wise
      “circle_cw” Motion Circle Clock-wise
      button_only

      false or not exist

      true
      motion_only

      false or not exist

      This action can be set on any action. This action can only be set for button press (single or double click).
      true

      This action can only be set for motion gestures (e.g. swipe_left or circle_cw). action will be ignored.

Implementation of KeyEvent-Callback

Implement KeyEvent-Callback to the activity to which RemoteActions have been declared. Since it is the same as handling an Android KeyEvent, only the simple examples of the implementation are introduced here.

Please refer to the Android developers website for detailed guidelines. It is recommended to handle the sent KeyEvent at onKeyDown.

Example :

  • Page Down key: Scroll ScrollView as much as +500 in Y direction

  • Page Up key: Scroll ScrollView as much as -500 in Y direction

public class SampleActivity extends Activity {
    private ScrollView mScrollView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sample_activity1_layout);
        mScrollView = (ScrollView) findViewById(R.id.scroll_view);
    }
        
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
            mScrollView.smoothScrollBy(0, 500);
        } else if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
            mScrollView.smoothScrollBy(0, -500);
        }
        return super.onKeyDown(keyCode, event);
    }
}