Android SDK
TapSdk auto-connects paired devices and can manage Text ↔ Controller across the activity lifecycle.
Package
| Maven | |
|---|---|
| Source | TapWithUs/tap-android-sdk |
Install
Require Maven Central, then:
implementation 'io.github.tapwithus:tap-android-sdk:0.3.6'Hello Tap
TapSdk sdk = TapSdkFactory.getDefault(this);
sdk.registerTapListener(new TapListener() {
@Override
public void onTapConnected(@NonNull String tapIdentifier) {
Log.d("Tap", "connected " + tapIdentifier);
}
@Override
public void onTapDisconnected(@NonNull String tapIdentifier) {
Log.d("Tap", "disconnected " + tapIdentifier);
}
@Override
public void onTapInputReceived(@NonNull String tapIdentifier, int data, int repeatData) {
boolean[] fingers = TapSdk.toFingers(data);
Log.d("Tap", "combination=" + data + " repeat=" + repeatData);
// fingers[0]=thumb … fingers[4]=pinky
// TapXR taps always report repeatData == 1
}
@Override
public void onMouseInputReceived(@NonNull String tapIdentifier, @NonNull MousePacket data) { }
@Override
public void onAirMouseInputReceived(@NonNull String tapIdentifier, @NonNull AirMousePacket data) { }
@Override
public void onRawSensorInputReceived(@NonNull String tapIdentifier, @NonNull RawSensorData rsData) { }
@Override
public void onImuMotionInputReceived(@NonNull String tapIdentifier, @NonNull ImuMotionPacket packet) {
// packet.dx, packet.dy, packet.isMouse, packet.roll, packet.pitch, packet.yaw
}
@Override
public void onTapStandbyStateChanged(@NonNull String tapIdentifier, boolean standby) { }
@Override public void onBluetoothTurnedOn() { }
@Override public void onBluetoothTurnedOff() { }
@Override public void onTapStartConnecting(@NonNull String tapIdentifier) { }
@Override public void onTapResumed(@NonNull String tapIdentifier) { }
@Override public void onTapChanged(@NonNull String tapIdentifier) { }
@Override public void onTapShiftSwitchReceived(@NonNull String tapIdentifier, int data) { }
@Override public void onTapChangedState(@NonNull String tapIdentifier, int state) { }
@Override public void onError(@NonNull String tapIdentifier, int code, @NonNull String description) {
Log.e("Tap", description);
}
});
// Hook activity lifecycle so Text mode is restored in background:
@Override protected void onResume() { super.onResume(); sdk.resume(); }
@Override protected void onPause() { sdk.pause(); super.onPause(); }TapListener
Entry point: TapSdkFactory.getDefault(context) or construct TapSdk with TapBluetoothManager. Register with registerTapListener. Combination onTapInputReceived uses the same 1–31 bitmask as other platforms; repeatData is 1/2/3 for single/double/triple on classic devices. TapXR taps always report repeatData == 1.
onTapShiftSwitchReceived carries Shift (0=off, 1=on, 2=locked) and Switch. Convert with TapSdk.toShiftAndSwitch. TapXR callbacks: onImuMotionInputReceived (dx/dy + Euler angles) and onTapStandbyStateChanged.
Modes
sdk.startControllerMode(tapIdentifier);
sdk.startTextMode(tapIdentifier);
sdk.startControllerWithMouseHIDMode(tapIdentifier);
sdk.startControllerWithFullHIDMode(tapIdentifier);
sdk.startRawSensorMode(tapIdentifier, (byte)0, (byte)0, (byte)0);
sdk.setDefaultMode(mode, true); // applyImmediateBy default the SDK switches to Controller on connect and back to Text when backgrounded (unless you disablePauseResumeHandling). On TapXR these mode calls are translated into feature commands automatically.
Raw sensors
Finger accelerometers plus thumb IMU (Tap Strap 2). Sensitivities: device accelerometer 1–4, IMU gyro 1–4, IMU accelerometer 1–5; 0 means default. TapXR streams the thumb IMU only — there are no finger accelerometers.
sdk.startRawSensorMode(tapIdentifier, (byte)0, (byte)0, (byte)0);
// in onRawSensorInputReceived:
if (rsData.dataType == RawSensorData.DataType.Device) {
Point3 thumb = rsData.getPoint(RawSensorData.iDEV_THUMB);
} else if (rsData.dataType == RawSensorData.DataType.IMU) {
Point3 gyro = rsData.getPoint(RawSensorData.iIMU_GYRO);
}TapXR
TapXR input state is separate from TAP input mode: force air-mouse, tapping, or leave it to the user. TapXR on the new developer firmware supports the full gesture set (taps, thumb-to-finger pinches, pinch-and-drag, thumb swipes, fist). Raw air gestures (swipes, pinches, fist) are available in Python, Web and Android (Android via onAirMouseInputReceived). iOS delivers TapXR air gestures through tapXRAirGestured. Spatial Control states 100–102 may require authorization — request access.
tapSdk.setDefaultXRState(TapXRState.tapping(), true);
tapSdk.setDefaultXRState(TapXRState.userControl(), false);
tapSdk.startXRAirMouseState("identifier");
tapSdk.startXRTappingState("identifier");
tapSdk.startXRUserControlState("identifier");Classic XR air-gesture constants on AirMousePacket include XR_AIR_GESTURE_NONE (100), XR_AIR_GESTURE_THUMB_INDEX (101), XR_AIR_GESTURE_THUMB_MIDDLE (102). These stream several times per second — take the majority of the last three events. TapXR uses UnifiedAirGesture instead (see below).
TapXR developer firmware
TapXR on the new developer firmware uses the same Tap SDK as Tap Strap. The SDK detects the device after connection — no code changes for basic usage. Check with sdk.isV2Tap(tapIdentifier) when you need a device-specific path. A keepalive is sent automatically every 10 seconds to every connected TapXR.
- Taps still arrive via
onTapInputReceived(TapXRrepeatDatais always 1) - Mouse movement via
onMouseInputReceivedandonImuMotionInputReceived(includes roll / pitch / yaw) - Air gestures via
onAirMouseInputReceivedwithUnifiedAirGesturecodes 100–114 (direction, pinches AB/AC/AD/AE, fist, hold variants) - These APIs on Tap Strap report
TapSdk.ERR_V2_NOT_SUPPORTED(103) viaonError
@Override
public void onAirMouseInputReceived(@NonNull String tapIdentifier, @NonNull AirMousePacket data) {
if (sdk.isV2Tap(tapIdentifier)) {
UnifiedAirGesture gesture = UnifiedAirGesture.fromCode(data.gesture.getInt());
if (gesture != null) {
switch (gesture) {
case LEFT: case RIGHT: case UP: case DOWN:
case AB: // thumb-index pinch (AC/AD/AE for other fingers)
case FIST:
case AB_HOLD: // held pinch / drag
case NONE:
break;
}
}
} else {
// Tap Strap — AirMousePacket.AIR_MOUSE_GESTURE_* / XR_AIR_GESTURE_*
}
}Independent feature toggles (DeviceFeature): RAW_IMU_DATA, MODEL_DETECTION, IMU_MOTION_DATA, STANDBY_GESTURE_DETECTION. XR state maps onto the vision sensor: startXRTappingState → TAPPING model + TRIGGER op-mode; startXRAirMouseState → AIR_GESTURE model + STREAM. Getters reply on a TapV2Callback (null after 2s).
boolean isV2 = sdk.isV2Tap(tapIdentifier);
sdk.setFeature(tapIdentifier, DeviceFeature.MODEL_DETECTION, true);
sdk.getFeature(tapIdentifier, DeviceFeature.MODEL_DETECTION, (identifier, enabled) -> {
// enabled is null on timeout
});
sdk.setVisionSensorModel(tapIdentifier, VisionSensorModel.AIR_GESTURE); // or TAPPING
sdk.setVisionSensorOpMode(tapIdentifier, VisionSensorOpMode.STREAM); // TRIGGER / STREAM_ON_TRIGGER
sdk.setImuSensitivity(tapIdentifier, /* gyro 0-5 */ 3, /* accelerometer 0-4 */ 2);
sdk.setStandbyState(tapIdentifier, true);
sdk.sendKeepAlive(tapIdentifier);Haptics
Up to 18 durations (ms) as haptic, pause, haptic, pause…. On TapXR, vibrate is sent automatically.
sdk.vibrate(tapIdentifier, new int[] { 500, 100, 500 });