S Pen SDK

Testing S Pen apps on the Emulator
Jan 11, 2013
9

Introduction

When creating a new app, it’s important to include device testing as part of the pre-release test process. Currently Samsung Developer members can make use of the Remote Test Lab system, or the emulator supplied with the Android SDK to test their apps, but as the Samsung Galaxy Note uses the S Pen stylus, it can be difficult to fully test. Standard emulators do not support changing of touch interfaces, so a developer would have to use a physical Galaxy Note device in order to test how their app will react to the S Pen Stylus. The S Pen Emulator library provides a solution to this issue, removing the need for a Galaxy Note device to test on.

Topic

This article is about a new tool, which allows testing of S Pen apps without having a device with S Pen support.

Overview

The article will explain how to use the S Pen Emulator Library and how the library works, so the user can modify its code. This article is for people who already possess a certain amount of knowledge about Android Programming. The reader might find useful to get to know the topic of MotionEvents
(http://developer.android.com/reference/android/view/MotionEvent.html ) before reading this.

S Pen Emulator Library – how to use

The first paragraph will explain how you can use the S Pen Emulator Library for testing purposes in your own app.

Connecting the library

The S Pen Emulator Library is very easy to use. All you need to do is put the .jar file attached to this article in the project’s libs folder and instead of extending the Activity class, extend the ActivityWithSPenLayer class. In other words, your app should start out like this:

public class MainActivity extends ActivityWithSPenLayer

Any interfaces can also be used with the user’s activity; the S Pen Emulator Library does not interfere with this in any way.

The only other thing you must keep in mind is that if you use an OptionsMenu, to call the super constructor in it. This should however be obvious to any programmer.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  /*
  * Code of menu
  */
	
  return super.onCreateOptionsMenu(menu);
}

Using the library

The functions of the library can be accessed by pressing the menu button.
There are five options in the menu.

Apply Virtual Layer

This is the primary and most important function of the library. After clicking this, changing of the input device is enabled. Without this function turned ON, all other options are useless and will do nothing.

Example of using the emulator with SPen SDK Demo app

Example of using the emulator with SPen SDK Demo app

Enable Pen/Pen Hover/Finger/Eraser

These four functions all do the same thing – change the input type seen by the app to the appropriate value.

Result after setting the tool type to “PEN”

Result after setting the tool type to “PEN”

Result after setting the tool type to “HOVER”

Result after setting the tool type to “HOVER”

S Pen Emulator Library – how it works

The whole concept of the library is quite simple - cover every object with a view, which will intercept all touch events and change their input tool type to the desired one.

Inserting the view layer

The first thing the library does is iterate through all the views from the user’s app. If it finds a ViewGroup, it digs deeper recursively.

if (pView instanceof ViewGroup) {
  int size = ((ViewGroup) pView).getChildCount();
  for (int i = 0; i < size; i++) {

    final View child = ((ViewGroup) pView).getChildAt(i);
    addLayer(child);
  }
} else {
  /**
  * Insert a layer on the view.
  */
  putLayer(pView);
}

For each view found, a transparent layer is inserted on top of it, and the view is added to a HashMap, to be able to access it later.

OnTouchListener is added to the transparent layer, which will intercept all the touches and then send them underneath.

Modifying touch events

Getting all touch event information

Every MotionEvent caught by the onTouchListener in our transparent layer needs to be modified before being delegated.

Each event has Pointers, which determine where the touch has been made and by what tool etc.

Each Pointer in the event has to be modified. The putLayer(final View pView) class takes care of this in the library.

int pointerCount = event.getPointerCount();
PointerCoords[] pointerCoords = new PointerCoords[pointerCount];
PointerProperties[] pointerProperties = new PointerProperties[pointerCount];

for (int i = 0; i < pointerCount; ++i) {
	pointerCoords[i] = new PointerCoords();
	event.getPointerCoords(i, pointerCoords[i]);
	pointerProperties[i] = new PointerProperties();
	event.getPointerProperties(i, pointerProperties[i]);
}

The code above creates a set of new PointerProperties which will be modified and inserted into a new event.

Changing the tool type

By clicking on settings menu items, you can set a flag determining which tool type you want to use. This is set inside of the loop above, as each individual Pointer has to be set with an input device.

switch (mToolType) {
case PEN_TOUCH:
	pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_STYLUS;
	break;
case ERASER:
	pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_ERASER;
	break;
case FINGER:
	pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_FINGER;
	break;
default:
	break;
}

The code above is all that is needed to change the tool to Stylus, Pen Eraser or Finger. Hovering is discussed below.

Enabling hovering

Since hovering does not provide the same actions as touching (or in the emulator’s case – clicking), the action has to be changed as well. When you click your mouse on the emulator (or touch the screen with your finger) the Action of the MotionEvent is ACTION_DOWN. Moving your mouse/finger while clicked/touched will trigger an ACTION_MOVE action, while finishing the touch/click will result in an ACTION_UP.

For hovering, these actions have to be changed to ACTION_HOVER_ENTER, ACTION_HOVER_MOVE and ACTION_HOVER_EXIT respectively.

if (mToolType == PEN_HOVER) {
	int actionEvent = 0;
	switch (event.getAction()) {
	case MotionEvent.ACTION_DOWN:
		actionEvent = MotionEvent.ACTION_HOVER_ENTER;
		break;
	case MotionEvent.ACTION_MOVE:
		actionEvent = MotionEvent.ACTION_HOVER_MOVE;
		break;
	case MotionEvent.ACTION_UP:
		actionEvent = MotionEvent.ACTION_HOVER_EXIT;
		break;
	default:
		break;
	}
}
S Pen side button

The S Pen Stylus is equipped with a side button which, when clicked, can change the action of the event. The use of the side button is enabled for the emulator by clicking the NUM 4 button with Scroll Lock turned off. This triggers a simple onKeyDown event which in turns sets a flag, that the button is clicked.

@Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
	if (keyCode == NUMERIC4) {
		mButton = true;
	}
	return super.onKeyDown(keyCode, event);
}

And the following code is then used in the putLayer class.

if (mButton) {
	buttonState = MotionEvent.BUTTON_SECONDARY;
	mButton = falsef;
} elsef {
	buttonState = MotionEvent.BUTTON_PRIMARY;
}
Dispatching the new event

All that is left to do is prepare the new MotionEvent with the properties set before and send it to the view lying below. The fields that may have been changed have been colored red to facilitate reading and analyzing.

motionEvent = MotionEvent.obtain(event.getDownTime(), event.getEventTime(), actionEvent, event.getPointerCount(), pointerProperties, pointerCoords, event.getMetaState(), buttonState, event.getXPrecision(), event.getYPrecision(), event.getDeviceId(), event.getEdgeFlags(), event.getSource(), event.getFlags());

Then, the view must receive the new event which is done with a single line of code.

pView.dispatchTouchEvent(motionEvent);

This is done if the event was a touch, if it was a hover action, this is the second difference:

pView.dispatchGenericMotionEvent(motionEvent);
Revision history
REVISION HISTORY DATE
First update Jan 11, 2013