Handle S Pen's Raw Data


Objective

Learn how to implement S Pen Remote SDK and handle raw data of S Pen. Modify a breakout game to control its paddle's position with S Pen.

Overview

S Pen Remote SDK allows you to develop an application that uses S Pen Remote generated events. S Pen includes buttons and motion sensor, and events from these units can be delivered to the application through the S Pen Framework. Simple gestures, such as button click, 4-directional swipe, and circular gesture, can easily be recognized by defining RemoteActions XML. But to implement a more powerful application using the raw data of units, you must use the S Pen Remote SDK.

Supported Features

The S Pen Remote SDK provides functions to identify motion coordinates and verifying if the side button is pressed for your application.

S Pen Remote SDK supports the following detailed features:

  • Checking if the side button is pressed or released
  • Identifying motion coordinates
    • Two-dimensional device movement
    • Relative values of the current position from the previous position
    • A positive value for the x-coordinates means to move right
    • A positive value for the y-coordinates means to move up
    • Value range : -1.0 ~ 1.0

Set up your environment

You will need the following:

  • Java SE Development Kit 10 (JDK) or later
  • Android Studio (latest version recommended)
  • Samsung Galaxy device with S Pen Remote capability:
    • Galaxy Note10 series or newer
    • Galaxy Tab S6 series or newer
    • Galaxy S22 Ultra

Sample Code

Here is a sample code for you to start coding in this Code Lab. Download it and start your learning experience!

S Pen Remote SDK Sample Code
(272.50 KB)

Start your project

In Android Studio, click Open an existing Android Studio project.

Locate the Android Project from the directory and click OK.

To install SpenRemote for Android Studio:

  1. Add the spenremote-v1.0.X.jar and sdk-v1.0.0.jar files to the libs folder in Android Studio

  2. Add dependencies for the SDK library folder in build.gradle

    
    dependencies{
            implementation fileTree(dir: 'libs', include: ['*.jar'])
            … 
    }
    
    

Initialize SPenRemote in onResume() of activity

  1. Check whether S Pen features are supported in the device
  2. Check if already connected
  3. Connect to the S Pen Framework using connect() API
  4. If the connection is successful, register SpenEventListener for each unit

public class GameActivity extends Activity {
    …
 private SpenUnitManager mSpenUnitManager = null;
 private boolean mButtonPressed = false;
     …
    @Override
    protected void onResume() { 
        …
        initSpenRemote();   //initialize Spen Remote
    
        }
        private void initSpenRemote() {
            //Check whether S Pen features are supported in the device
            SpenRemote spenRemote = SpenRemote.getInstance();
            if (!spenRemote.isFeatureEnabled(SpenRemote.FEATURE_TYPE_AIR_MOTION)) {
                return;
        }
        if (!spenRemote.isFeatureEnabled(SpenRemote.FEATURE_TYPE_BUTTON)) {
            return;
        }
    
        //Check if already connected
        if (spenRemote.isConnected()) {
            return;
        }
 
    //Connect to the S Pen Framework
     mSpenUnitManager = null;
     spenRemote.connect(this, new SpenRemote.ConnectionResultCallback() {
       @Override
        public void onSuccess(SpenUnitManager spenUnitManager) {
            //If connection is successful, register SpenEventListener for each units.
            mSpenUnitManager = spenUnitManager;
            initSpenEventListener();
            }
            @Override
            public void onFailure(int e) {
            }
        });
    }
 }
 
 private void initSpenEventListener() {
     SpenUnit buttonUnit = mSpenUnitManager.getUnit(SpenUnit.TYPE_BUTTON);
     if (buttonUnit != null) {
         mSpenUnitManager.registerSpenEventListener(mSpenButtonEventListener, buttonUnit);
     }
     SpenUnit airMotionUnit = mSpenUnitManager.getUnit(SpenUnit.TYPE_AIR_MOTION);
     if (airMotionUnit != null) {
     mSpenUnitManager.registerSpenEventListener(mSpenAirMotionEventListener, airMotionUnit);
     }
 }
 

Handle SpenEvent on EventListener

Register the event listener to SpenUnit using registerSpenEventListener method of SPenUnitManager instance. The data of SpenEvent passed to the SpenEventListener is hidden. You can refer to the data by casting it as a ButtonEvent or AirMotionEvent class:


private SpenEventListener mSpenButtonEventListener = new SpenEventListener() {
    @Override
    public void onEvent(SpenEvent spenEvent) {
        ButtonEvent buttonEvent = new ButtonEvent(spenEvent);
        if (buttonEvent.getAction() == ButtonEvent.ACTION_DOWN) {
            mButtonPressed = true;
        } else {
            mButtonPressed = false;
        }
    }
};

private SpenEventListener mSpenAirMotionEventListener = new SpenEventListener() {
    @Override
    public void onEvent(SpenEvent spenEvent) {
        AirMotionEvent motionEvent = new AirMotionEvent(spenEvent);
        if (mButtonPressed) {
            mPaddleController.move(motionEvent.getDeltaX() * 400f);
        }
    }
};

Release SpenRemote in onPause() of activity

In this part, SpenRemote will be released during onPause() state. disconnect() is used to disconnect from the S Pen Framework:


@Override
protected void onPause() {
   …
   releaseSpenRemote();
}
private void releaseSpenRemote() {
    SpenRemote spenRemote = SpenRemote.getInstance();
    if (spenRemote.isConnected()) {
         spenRemote.disconnect(this);
    }
    mSpenUnitManager = null;
} 

Run the app

Now, everything is ready. Install the game on your device and launch it. The paddle in the game can now be controlled by the S Pen. The game app screen should look like the following:

You're done!

Congratulations! You have successfully achieved the goal of this Code Lab. Now, you can handle raw data of the S Pen and implement it on an app by yourself! If you're having trouble, you may download this file:

S Pen Remote SDK Complete Code
(200.15 KB)