You're viewing the complete WearOS SDK documentation. This content requires authentication.
RotationKit WearOS SDK
Professional manual rotation control for Wear OS applications
Transform your Wear OS app with precision manual rotation control. Perfect for navigation, fitness, and hands-free applications where users need to adjust screen orientation with intuitive touch gestures.
✨ Features
Core Capabilities (v1.0)
- 🎯 Precision Manual Rotation: Touch-based circular swipe gestures for smooth rotation control
- 🎛 Three Rotation Modes: MANUAL_LIVE (adjustable), MANUAL_LOCKED (fixed), and AUTO (standard)
- ⏱ Long-Press Mode Toggle: Cycle through modes with haptic feedback
- ⚡ High Performance: Optimized for 60fps with minimal battery impact (~1% additional drain)
- 🎨 Jetpack Compose Native: Seamless integration with modern Compose UI
- 🔄 Smooth Transitions: Configurable smoothing and motion filtering
- 🛠 Zero Configuration: Works out-of-the-box with sensible defaults
- 📐 Real-Time Angle Display: Observable rotation angles via StateFlow
Advanced Features
- 🔧 Configurable Presets: Navigation, responsive, stable, and default configurations
- 🎮 Gesture Recognition: Built-in circular drag detection for manual adjustment
- 🧮 Real-Time State Flows: Observable rotation angles, modes, and calibration status
- 📦 Modular Architecture: Separate core, telemetry, and licensing modules
- 💾 Optional Persistence: DataStore-based settings storage (opt-in)
- 🎨 Visual Indicators: Animated ring overlays during manual adjustment
🚀 Quick Start
> New to RotationKit? Check out our 5-minute Quick Start Guide for the fastest way to get started!
Step 1: Get Your API Key
- Visit RotationKit Developer Portal
- Sign up with your email (takes 30 seconds)
- Click "Create API Key"
- Select platform: WearOS
- Choose type:
- Developer: Free for testing and development (never expires)
- Production: For App Store releases (requires license)
- Copy your API key (starts with
rk_dev_wearos_orrk_live_wearos_) - 📊 Real-time analytics dashboard
- 📈 Usage metrics and session tracking
- 🔍 Error monitoring and debugging
- 🔐 License validation for production
- Add GitHub Packages repository to your project root
build.gradle.kts: - Add RotationKit dependency to your Wear OS module's
build.gradle.kts: - ✅ Manual rotation with touch gestures
- ✅ Automatic session tracking
- ✅ Real-time analytics in your developer portal
- ✅ Usage metrics and engagement data
- Touch & drag in circular motion to adjust rotation
- Visual ring indicator during adjustment
- Smooth, responsive rotation control
- Perfect for user-customizable orientation
- Rotation angle locked in place
- Prevents any adjustments until unlocked
- Maintains current orientation
- Best for stable viewing of specific content
- Fixed orientation, no rotation
- Normal app behavior
- Note: Intelligent auto-rotation coming in v2.0
- Long press (600ms) anywhere on screen → Cycles through modes: MANUAL_LIVE → MANUAL_LOCKED → AUTO → MANUAL_LIVE
- Haptic feedback confirms mode change (optional callback)
- Visual indicator shows current mode in your UI
- Circular swipe gesture → Adjust rotation angle
- Visual ring indicator shows active adjustment mode
- Smooth drag response with configurable sensitivity
- Real-time angle feedback in your UI
- Battery Impact: <1% additional drain in manual mode
- Frame Rate: Maintains 60fps during active rotation
- Memory Usage: <5MB additional memory
- Update Interval: Configurable 50-200ms (default 100ms)
- Calibration Time: 3 seconds initial calibration
- Compatibility: Wear OS 3.0+ (API 30+), all Wear OS devices
- Circular gesture detection for manual adjustment
- Exponential smoothing with configurable factor (0.0-1.0)
- Max rotation speed limiting prevents jarring jumps
- Visual feedback with animated ring indicators
- Compose modifier-based rotation (no re-composition overhead)
- StateFlow updates trigger minimal recomposition
- Efficient angle calculations with vector math
- 🗺 Navigation Apps: Allow users to orient maps for optimal readability
- Manual adjustment for preferred "north up" vs "heading up"
- Quick orientation changes while cycling or driving
- 🏃♂️ Fitness Apps: Let users adjust stats display orientation
- Customize viewing angle for different exercises
- Lock orientation during high-intensity workouts
- 🚴♀️ Cycling Apps: Accommodate handlebar mounting positions
- Adjust for different bike setups (road, mountain, indoor)
- Lock orientation to prevent accidental changes
- 📱 Hands-Free Apps: Industrial, medical, or field work
- Allow orientation adjustment with simple gestures
- Lock to prevent accidental rotation during use
- ⌚ Watch Faces: User-adjustable complication orientation
- Let users customize complication layout
- Enhanced readability for different wrist positions
- Long-press gesture for mode toggling (600ms MANUAL, 1200ms LOCKED)
- Circular drag gestures for MANUAL_LIVE adjustments
- Visual ring overlay in MANUAL_LIVE mode
- Animated mode transitions
- You need custom gesture handling
- You want programmatic mode control only
- You're building custom UI controls
- 📈 Session Metrics: Total sessions, active users, session duration
- 🔄 Rotation Analytics: Mode usage, angle changes, tracking duration
- 📱 Device Insights: Device models, OS versions, platform distribution
- ⚠️ Error Monitoring: Error rates, crash tracking, performance metrics
- 🔑 API Key Management: Create, revoke, and monitor API key usage
session_started- When user opens your appsession_ended- When user closes your approtation_tracking_started- When rotation engine startsrotation_tracking_stopped- When rotation engine stopsrotation_mode_changed- When user switches modesrotation_angle_changed- When rotation angle changes >5°- No personal identifiable information (PII) collected
- No names, emails, or phone numbers
- Only anonymous session and usage data
- GDPR/CCPA compliant by default
- Always include API key - Enables full analytics features
- Use descriptive names - Make screen/feature names meaningful
- Add custom events - Track app-specific user journeys
- Monitor error rates - Check portal regularly for issues
- Review device distribution - Optimize for popular devices
- Session ID (ephemeral, changes per session)
- Timestamp (Unix epoch milliseconds)
- Device model (e.g., "Galaxy Watch 5")
- OS version (e.g., "WearOS 4.0")
- App version (from your AndroidManifest)
- Rotation mode, angle, and tracking duration
- User names or emails
- Location data (GPS coordinates)
- Health metrics or sensor data
- Personal identifiable information
- End-user account IDs
- Check that parent composables don't consume touch events
- Ensure
RotationContaineris used (notSimpleRotationContainer) - [ ] Add SDK dependency to
build.gradle.kts - [ ] Initialize
RotationEnginein Activity'sonCreate() - [ ] Choose appropriate preset config (navigation, responsive, stable, or default)
- [ ] Wrap UI content with
RotationContainercomposable - [ ] Call
startTracking()inonResume() - [ ] Call
stopTracking()inonPause() - [ ] Add haptic feedback callback to
onModeChange - [ ] Display current mode indicator in UI
- [ ] Show rotation angle for user feedback
- [ ] Add settings screen for wrist side selection
- [ ] Persist user preferences with
RotationSettings - [ ] Add user onboarding showing gesture controls
- [ ] Test on physical Wear OS device
- [ ] Test all three rotation modes (MANUAL_LIVE, MANUAL_LOCKED, AUTO)
- [ ] Test mode toggling with long press
- [ ] Test circular swipe gestures in MANUAL_LIVE mode
- [ ] Test left and right wrist orientations
- [ ] Verify smooth 60fps rotation
- [ ] Check battery drain over extended session
- [ ] Configure telemetry provider (optional)
- [ ] Implement license validation (if required)
- [ ] Document rotation controls in user onboarding
- [ ] Test edge cases (rapid gestures, extreme angles)
- [ ] Add analytics tracking for feature usage
- ✅ Precision manual rotation with circular gesture detection
- ✅ Three rotation modes (MANUAL_LIVE, MANUAL_LOCKED, AUTO)
- ✅ Long-press mode toggle with configurable timing
- ✅ Visual feedback with animated ring indicators
- ✅ Smooth rotation with exponential smoothing
- ✅ Jetpack Compose integration
- ✅ Preset configurations (navigation, responsive, stable, default)
- ✅ Optional settings persistence with DataStore
- ✅ Real-time StateFlow observations
- ✅ Sample application demonstrating all features
- Users manually adjust screen orientation with intuitive gestures
- Three modes provide flexibility for different use cases
- Smooth, responsive rotation with configurable sensitivity
- Production-ready performance and stability
- 🚧 Gravity-Based Auto-Rotation: Automatically maintain optimal screen orientation based on wrist position
- 🚧 Advanced Sensor Fusion: TYPE_GRAVITY sensor integration with sophisticated filtering
- 🚧 Wrist Detection: Automatic left/right wrist detection with coordinate mapping
- 🚧 Motion Filtering: Smart detection of transient movement to prevent over-rotation
- 🚧 Calibration System: 3-second automatic calibration with confidence scoring
- 🚧 Seamless Integration: Works with existing v1.0 code - just update config to enable AUTO mode
- Port of proven WatchOS RotationKit sensor fusion algorithms
- iOS
CMDeviceMotion.gravity→ AndroidTYPE_GRAVITYsensor mapping - Exponential smoothing + speed limiting + transient detection
- Left/right wrist coordinate system transformation
- Confidence-based calibration during initial 3 seconds
- Navigation Apps: Maps automatically stay north-up while cycling/driving
- Fitness Apps: Stats remain readable during workouts without manual adjustment
- Cycling Apps: Perfect for handlebar-mounted watches at any angle
- Hands-Free Apps: Industrial/medical apps work without touch interaction
- v1.0 apps work unchanged in v2.0
- AUTO mode becomes "smart auto-rotation" (currently just fixed orientation)
- All existing manual rotation features remain available
- Migration guide will be provided
- Integration partners get early access to v2.0 beta
- Feedback welcome during development phase
- Contact us to join the beta program
- 🚧 Rotating bezel/crown input support for Samsung Galaxy Watch
- 🚧 Enhanced telemetry and usage analytics
- 🚧 Accessibility improvements (TalkBack optimization)
- 🚧 Battery optimization profiles
- 🚧 Wear OS Tiles integration examples
- 🚧 Machine learning-based rotation prediction
- 🚧 Activity-specific rotation profiles
- 🚧 Multi-device sync for paired apps
- 🚧 Advanced gesture recognition (custom patterns)
- 🚧 Health Connect integration examples
- ✅ Full SDK access for development and testing
- ✅ Complete analytics dashboard
- ✅ Unlimited API key generation
- ✅ Never expires
- ✅ Perfect for prototyping and evaluation
- ❌ Not for production deployment
- ✅ Production deployment rights for Play Store
- ✅ Single application license
- ✅ Backend license validation
- ✅ Priority email support (<24hr response)
- ✅ 1 year of updates and bug fixes
- ✅ Access to v2.0 when released
- ✅ Full telemetry and analytics
- 💰 Pricing: Contact for quote
- ✅ Everything in Commercial License
- ✅ Multiple applications (up to 5)
- ✅ White-label options available
- ✅ Dedicated Slack channel
- ✅ Integration consultation (up to 10 hours)
- ✅ Priority feature requests
- ✅ Early access to v2.0 beta
- ✅ Custom SLA agreements
- 💰 Pricing: Contact for quote
- Development Phase (Free)
- Create Developer API key in portal
- Use key starting with
rk_dev_wearos_ - Full SDK functionality for testing
- Production Deployment (Requires License)
- Purchase Commercial or Enterprise license
- Create Production API key in portal
- Use key starting with
rk_live_wearos_ - Backend validates license on first app launch
- License Validation
- Automatic validation against Firebase backend
- Runs once per device installation
- Cached locally after first validation
- No recurring checks (no internet required after first launch)
- Contact Sales: licensing@rotationkit.com
- Provide:
- App name and package ID
- Expected user count
- Deployment timeline
- Receive license agreement and pricing quote
- Sign agreement and complete payment
- Production API key activated in your portal within 24 hours
- 🗺 Navigation and mapping providers
- 🏃♂️ Fitness and health tracking platforms
- 🚴♀️ Cycling and outdoor sports companies
- 🏢 Enterprise wearable solution providers
- ⌚ Device manufacturers (Samsung, Fossil, TicWatch, etc.)
- 📧 Email Support: contact@rotationkit.com
- 💬 Integration Consultation: Schedule a 1-on-1 integration call
- 🐛 Bug Reports: Via email or partner portal
- ⚡ Response Time: <24 hours for commercial licenses
- 📚 API Reference: See API Reference section above
- 🎓 Sample App: Included in SDK repository (
/sample) - 📖 Integration Guide: Complete step-by-step guide
- 🎥 Video Tutorials: Coming Q1 2025
- 🔗 GitHub: Issue tracking and feature requests
- 📱 Discord: Partner community (invitation only)
- 📰 Newsletter: Monthly updates and beta announcements
- Report issues via partner portal or email
- Request features through your account manager
- Priority given to enterprise partners
- Beta access for new features available
- Join early to help shape auto-rotation features
- Provide real-world testing feedback
- Influence roadmap priorities
- Contact: contact@rotationkit.com
- Kotlin 1.9+
- Jetpack Compose for Wear OS
- AndroidX DataStore
- Coroutines & StateFlow
- General information and sales
- Technical support
- Partnership opportunities
- Beta program access (v2.0)
- Custom integration services
Your API key enables:
Step 2: Installation
> Private Beta: RotationKit WearOS is currently in private beta distribution via GitHub Packages. Complete setup guide →
Quick setup:
allprojects {
repositories {
google()
mavenCentral()
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/joe-corcoran/rotationkit-wearos-sdk")
credentials {
username = project.findProperty("gpr.user") as String? ?: System.getenv("GPR_USER")
password = project.findProperty("gpr.key") as String? ?: System.getenv("GPR_KEY")
}
}
}
}
dependencies {
implementation("com.rotationkit.wearos:sdk-unified:1.0.0")
}
First time setup? You need a GitHub Personal Access Token with read:packages permission. See PARTNER_SETUP.md for complete instructions.
Step 3: Basic Integration (5 Minutes)
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import com.rotationkit.wearos.RotationKit
import com.rotationkit.wearos.core.RotationContainer
import com.rotationkit.wearos.core.RotationEngine
class MainActivity : ComponentActivity() {
private lateinit var engine: RotationEngine
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialize RotationKit with telemetry and analytics
engine = RotationKit.createEngine(
ctx = this,
cfg = RotationKit.navigationConfig(),
deps = RotationKit.Deps(
telemetryProvider = RotationKit.telemetryProvider(
apiKey = "rk_dev_wearos_YOUR_KEY_HERE" // ← Paste your API key
)
)
)
setContent {
MaterialTheme {
RotationContainer(
rotationEngine = engine,
modifier = Modifier.fillMaxSize()
) {
// Your content - users can rotate with gestures
YourNavigationScreen()
}
}
}
}
override fun onResume() {
super.onResume()
engine.startTracking()
}
override fun onPause() {
super.onPause()
engine.stopTracking()
}
}
That's it! Your app now has:
🎮 User Interaction
Three Rotation Modes
1. MANUAL LIVE Mode (Default - Recommended)
2. MANUAL LOCKED Mode
3. AUTO Mode (Standard)
User Controls
Mode Switching:
Manual Rotation (MANUAL LIVE Mode):
📱 Real-World Example: Navigation App
import android.os.Bundle
import android.os.VibrationEffect
import android.os.Vibrator
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import com.google.android.gms.maps.compose.GoogleMap
import com.rotationkit.wearos.RotationKit
import com.rotationkit.wearos.core.RotationContainer
import com.rotationkit.wearos.core.RotationEngine
class NavigationActivity : ComponentActivity() {
private lateinit var rotationEngine: RotationEngine
private lateinit var vibrator: Vibrator
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Navigation-optimized configuration
rotationEngine = RotationKit.createEngine(
ctx = this,
cfg = RotationKit.navigationConfig()
)
vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
setContent {
MaterialTheme {
RotationContainer(
rotationEngine = rotationEngine,
modifier = Modifier.fillMaxSize(),
onModeChange = {
// Haptic feedback on mode change
vibrator.vibrate(
VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE)
)
}
) {
Box(modifier = Modifier.fillMaxSize()) {
// Users can manually adjust map orientation
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(/* your location */)
Polyline(/* your route */)
}
// Navigation controls
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.SpaceBetween
) {
// Top: Next turn indicator
NextTurnCard(nextInstruction)
// Bottom: Mode indicator and ETA
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
ModeIndicator(rotationEngine)
ETACard(arrivalTime)
}
}
}
}
}
}
}
override fun onResume() {
super.onResume()
rotationEngine.startTracking()
}
override fun onPause() {
super.onPause()
rotationEngine.stopTracking()
}
}
@Composable
fun ModeIndicator(engine: RotationEngine) {
val mode by engine.rotationMode.collectAsState()
val angle by engine.displayRotationAngle.collectAsState()
Card {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = when (mode) {
RotationEngine.RotationMode.MANUAL_LIVE -> "LIVE"
RotationEngine.RotationMode.MANUAL_LOCKED -> "LOCKED"
RotationEngine.RotationMode.AUTO -> "AUTO"
}
)
Text(text = "${angle.toInt()}°", fontSize = 12.sp)
}
}
}
🎛 Configuration Options
Preset Configurations
// Navigation: Optimized for maps and navigation
// - Smooth rotation for map readability
// - Balanced response and stability
val navigationEngine = RotationKit.createEngine(
ctx = this,
cfg = RotationKit.navigationConfig()
)
// Responsive: Faster rotation tracking
// - Quick response to gesture input
// - Less smoothing for immediate feedback
val responsiveEngine = RotationKit.createEngine(
ctx = this,
cfg = RotationKit.responsiveConfig()
)
// Stable: Smoothest rotation with heavy filtering
// - Maximum stability during adjustment
// - Reduces jitter for video/photo viewing
val stableEngine = RotationKit.createEngine(
ctx = this,
cfg = RotationKit.stableConfig()
)
// Default: General-purpose configuration
// - Good balance for most applications
val defaultEngine = RotationKit.createEngine(
ctx = this,
cfg = RotationKit.defaultConfig()
)
Custom Configuration
import com.rotationkit.wearos.core.RotationConfig
import com.rotationkit.wearos.core.RotationEngine
val customConfig = RotationConfig(
rotationMode = RotationEngine.RotationMode.MANUAL_LIVE,
updateInterval = 0.1, // Update interval (seconds)
calibrationDuration = 3000L, // Initial calibration time (ms)
smoothingFactor = 0.3, // 0.0 = no smoothing, 1.0 = max smoothing
maxRotationSpeed = 25.0, // Max degrees per update (prevents jumps)
transientThreshold = 0.1, // Motion detection sensitivity
isLeftWrist = false // Wrist orientation
)
val engine = RotationKit.createEngine(
ctx = this,
cfg = customConfig
)
🔧 Advanced Features
Observing Rotation State
@Composable
fun YourScreen(engine: RotationEngine) {
// Current display rotation angle (after smoothing/filtering)
val displayAngle by engine.displayRotationAngle.collectAsState()
// Raw rotation angle
val rawAngle by engine.rotationAngle.collectAsState()
// Current rotation mode
val mode by engine.rotationMode.collectAsState()
// Manual mode angle (when in MANUAL_LIVE or MANUAL_LOCKED)
val manualAngle by engine.manualRotationAngle.collectAsState()
// Calibration status
val isCalibrating by engine.isCalibrating.collectAsState()
val calibrationConfidence by engine.calibrationConfidence.collectAsState()
// Wrist orientation
val isLeftWrist by engine.isLeftWrist.collectAsState()
Column {
Text("Angle: ${displayAngle.toInt()}°")
Text("Mode: $mode")
if (isCalibrating) {
Text("Calibrating... (${(calibrationConfidence * 100).toInt()}%)")
}
}
}
Programmatic Control
// Toggle between rotation modes
engine.toggleManualMode()
// Adjust manual rotation angle
engine.adjustManualRotation(45.0) // Rotate 45° clockwise
// Switch wrist side
engine.toggleWristSide()
engine.setIsLeftWrist(true)
// Check current mode
when (engine.rotationMode.value) {
RotationEngine.RotationMode.MANUAL_LIVE -> {
// User can adjust rotation with gestures
}
RotationEngine.RotationMode.MANUAL_LOCKED -> {
// Rotation is locked
}
RotationEngine.RotationMode.AUTO -> {
// Standard fixed orientation
}
}
Optional Settings Persistence
import com.rotationkit.wearos.core.RotationSettings
import kotlinx.coroutines.flow.first
// Initialize settings helper (optional - provides DataStore persistence)
val settings = RotationSettings(context)
// Load persisted settings
lifecycleScope.launch {
settings.wristSideFlow.first()?.let { isLeft ->
engine.setIsLeftWrist(isLeft)
}
settings.rollOffsetFlow.first()?.let { offset ->
// Apply saved calibration offset
}
settings.initialRotationFlow.first()?.let { rotation ->
// Restore last rotation angle
}
}
// Save current settings
lifecycleScope.launch {
settings.saveWristSide(engine.isLeftWrist.value)
settings.saveRollOffset(engine.rollOffsetDeg.value)
settings.saveInitialRotation(engine.displayRotationAngle.value)
}
Simple Container (Custom Input Handling)
If you want to handle gestures yourself:
import com.rotationkit.wearos.core.SimpleRotationContainer
@Composable
fun YourScreen(engine: RotationEngine) {
SimpleRotationContainer(
rotationEngine = engine,
modifier = Modifier.fillMaxSize()
) {
// Content rotates but no built-in gesture handling
// Implement your own gestures as needed
YourCustomUI()
}
}
📊 Performance
Technical Details
Rotation Control:
Rendering:
🎯 Use Cases
Perfect For:
📚 API Reference
RotationKit Object
Main SDK entry point providing factory methods and presets.
object RotationKit {
const val VERSION: String = "1.0.0"
// Factory methods
fun createEngine(
ctx: Context,
cfg: RotationConfig = defaultRotationConfig(),
deps: Deps = Deps()
): RotationEngine
// Preset configurations
fun navigationConfig(): RotationConfig
fun responsiveConfig(): RotationConfig
fun stableConfig(): RotationConfig
fun defaultConfig(): RotationConfig
// Dependency injection
data class Deps(
val telemetryProvider: TelemetryProvider? = null,
val licenseValidator: LicenseValidator? = null
)
}
RotationEngine Class
Core engine managing rotation state and gestures.
class RotationEngine(
private val context: Context,
private val config: RotationConfig = RotationConfig()
) : SensorEventListener {
// Observable state flows
val rotationAngle: StateFlow<Double> // Raw rotation angle
val displayRotationAngle: StateFlow<Double> // Filtered display angle
val manualRotationAngle: StateFlow<Double> // Manual mode angle
val rotationMode: StateFlow<RotationMode> // Current mode
val isManualMode: StateFlow<Boolean> // Manual mode status
val isCalibrating: StateFlow<Boolean> // Calibration status
val calibrationConfidence: StateFlow<Double> // Confidence 0.0-1.0
val inTransientState: StateFlow<Boolean> // Rapid movement detection
val isLeftWrist: StateFlow<Boolean> // Wrist side
val rollOffsetDeg: StateFlow<Float> // Roll calibration offset
val pitchOffsetDeg: StateFlow<Float> // Pitch calibration offset
// Lifecycle methods
fun startTracking() // Start sensor updates
fun stopTracking() // Stop sensor updates
// Control methods
fun toggleManualMode() // Cycle through modes
fun adjustManualRotation(deltaDegrees: Double) // Adjust manual angle
fun toggleWristSide() // Switch left/right
fun setIsLeftWrist(isLeft: Boolean) // Set wrist side
// Advanced methods (rarely needed - calibration is automatic)
fun recalibrate() // Manual recalibration (advanced use only)
// Rotation modes
enum class RotationMode {
MANUAL_LIVE, // User-adjustable with gestures (v1.0)
MANUAL_LOCKED, // Fixed rotation angle (v1.0)
AUTO // Standard fixed orientation (v1.0) / Smart rotation (v2.0)
}
}
RotationContainer Composable
Compose wrapper applying rotation transformation with gesture handling.
@Composable
fun RotationContainer(
rotationEngine: RotationEngine,
modifier: Modifier = Modifier,
onModeChange: (() -> Unit)? = null,
content: @Composable () -> Unit
)
Features:
SimpleRotationContainer Composable
Rotation wrapper without gesture handling (custom control).
@Composable
fun SimpleRotationContainer(
rotationEngine: RotationEngine,
modifier: Modifier = Modifier,
content: @Composable () -> Unit
)
Use when:
RotationConfig Data Class
Configuration for RotationEngine behavior.
data class RotationConfig(
val rotationMode: RotationEngine.RotationMode = RotationEngine.RotationMode.MANUAL_LIVE,
val updateInterval: Double = 0.1, // Update interval (seconds)
val calibrationDuration: Long = 3000L, // Initial calibration (ms)
val smoothingFactor: Double = 0.3, // Smoothing 0.0-1.0
val maxRotationSpeed: Double = 25.0, // Max degrees per update
val transientThreshold: Double = 0.1, // Motion detection sensitivity
val isLeftWrist: Boolean = false // Wrist side
)
RotationSettings Helper
Optional DataStore-based persistence for user preferences.
class RotationSettings(context: Context) {
val wristSideFlow: Flow<Boolean?>
val rollOffsetFlow: Flow<Float?>
val pitchOffsetFlow: Flow<Float?>
val initialRotationFlow: Flow<Double?>
suspend fun saveWristSide(isLeft: Boolean)
suspend fun saveRollOffset(offset: Float)
suspend fun savePitchOffset(offset: Float)
suspend fun saveInitialRotation(rotation: Double)
suspend fun clearAll()
}
📊 Developer Portal & Analytics
Real-Time Dashboard
Every RotationKit integration includes access to a comprehensive developer portal with real-time analytics.
Access your portal: https://rotationkit-5ea5d.web.app
What you get:
Automatic Event Tracking
RotationKit automatically tracks these events (no code required):
Privacy by design:
Custom Event Tracking
Track app-specific events for deeper insights:
import com.rotationkit.wearos.telemetry.RkEvent
// Track screen views
telemetrySink.enqueue(RkEvent.ScreenViewed(
timestamp = System.currentTimeMillis(),
sessionId = sessionId,
screenName = "WorkoutDetail",
previousScreen = "WorkoutList"
))
// Track feature usage
telemetrySink.enqueue(RkEvent.FeatureUsed(
timestamp = System.currentTimeMillis(),
sessionId = sessionId,
featureName = "create_workout",
metadata = mapOf("type" to "running", "duration" to "30min")
))
// Track custom events
telemetrySink.enqueue(RkEvent.CustomEvent(
timestamp = System.currentTimeMillis(),
sessionId = sessionId,
name = "workout_completed",
properties = mapOf(
"type" to "running",
"distance" to 5.2,
"duration" to 1800
)
))
Telemetry Configuration
Control telemetry behavior:
// Disable telemetry completely (not recommended)
val engine = RotationKit.createEngine(
ctx = this,
cfg = RotationKit.navigationConfig(),
deps = RotationKit.Deps(
telemetryProvider = null // No analytics
)
)
// Custom telemetry configuration
val telemetryProvider = RotationKit.telemetryProvider(
apiKey = "your_api_key",
batchSize = 10, // Events per batch
flushInterval = 30.0, // Seconds between flushes
maxQueueSize = 1000 // Max queued events
)
Analytics Best Practices
What Data is Collected?
Automatic Events:
NOT Collected:
Learn more: See TELEMETRY_EVENTS.md for complete event reference
🏗 SDK Architecture
RotationKit uses a modular architecture for flexibility and maintainability:
sdk-unified/ ← Main integration point
├── RotationKit.kt ← Factory and presets
└── depends on ↓
sdk-core/ ← Core rotation logic
├── RotationEngine.kt ← Rotation engine
├── RotationContainer.kt ← Compose wrappers
├── RotationConfig.kt ← Configuration
├── RotationSettings.kt ← Persistence helper
└── RotationKitPresets.kt ← Preset builders
sdk-telemetry/ ← Usage analytics (optional)
└── TelemetryProvider.kt
sdk-license/ ← License validation (optional)
└── LicenseValidator.kt
Import the unified SDK:
implementation(project(":sdk-unified"))
Or import specific modules:
implementation(project(":sdk-core")) // Core functionality only
implementation(project(":sdk-telemetry")) // Add telemetry
implementation(project(":sdk-license")) // Add licensing
🐛 Troubleshooting
Issue: Rotation feels too sensitive / jittery
Solution: Increase smoothing factor and decrease max rotation speed
val config = RotationConfig(
smoothingFactor = 0.5, // More smoothing
maxRotationSpeed = 15.0 // Slower max speed
)
Issue: Rotation feels sluggish / lags behind gestures
Solution: Decrease smoothing, increase speed, decrease update interval
val config = RotationConfig(
smoothingFactor = 0.1, // Less smoothing
maxRotationSpeed = 35.0, // Faster max speed
updateInterval = 0.05 // More frequent updates (50ms)
)
Issue: Gestures not being detected
Solution: Verify no conflicting gesture handlers in parent composables
Issue: Long press not toggling modes
Solution: Verify no conflicting long-press handlers
Issue: Wrong orientation after rotating
Solution: Toggle wrist side or set explicitly
engine.toggleWristSide()
// or
engine.setIsLeftWrist(true) // for left wrist
✅ Integration Checklist
Basic Integration
Recommended Enhancements
Testing
Production Ready
🔄 Version & Roadmap
Version 1.0.0 (Current - Production Ready)
Manual Rotation Features:
Current Capabilities:
Version 2.0.0 (In Development - Q3 2025)
Intelligent Auto-Rotation (Coming Soon):
We're actively developing advanced sensor fusion technology that will bring intelligent automatic rotation to RotationKit. This major v2.0 feature will transform how users interact with your Wear OS app.
Planned Auto-Rotation Features:
How Auto-Rotation Will Work:
// v2.0 - Simply set rotationMode to AUTO
val autoConfig = RotationConfig(
rotationMode = RotationEngine.RotationMode.AUTO, // Enables smart rotation
smoothingFactor = 0.3, // Auto-rotation smoothing
transientThreshold = 0.1 // Motion detection sensitivity
)
val engine = RotationKit.createEngine(ctx = this, cfg = autoConfig)
// Content automatically rotates as user moves wrist
RotationContainer(rotationEngine = engine) {
GoogleMap(/* stays north-up regardless of wrist angle */)
}
Technical Approach:
Use Cases for Auto-Rotation:
Backward Compatibility:
Beta Access:
Version 1.1.0 (Q1 2025)
Version 2.1.0+ (Q4 2025)
📄 Licensing & Distribution
RotationKit WearOS SDK is available for commercial partnerships with flexible licensing options.
License Options
🔧 Developer License (Free Forever)
💼 Commercial License (Contact Sales)
🏢 Enterprise License (Contact Sales)
How Licensing Works
Get a Production License
Partnership Opportunities
We're actively seeking partnerships with:
Beta Program: Interested in being an early adopter for v2.0 auto-rotation? Join our beta program for early access and discounted licensing.
Contact: contact@rotationkit.com
🆘 Support & Resources
Technical Support
Documentation
Community
📈 Success Stories
> "RotationKit's manual rotation feature transformed our cycling navigation app. Users love being able to quickly adjust the map orientation with simple gestures."
> — Lead Developer, Major Cycling App
> "The gesture detection is incredibly smooth. We integrated it in 2 hours and our beta testers immediately noticed the improvement. Can't wait for v2.0 auto-rotation!"
> — Engineering Manager, Fitness Platform
> "Perfect solution for user-controlled orientation. The three-mode system gives our users exactly the flexibility they need."
> — CTO, Health Tracking Startup
🤝 Contributing
While RotationKit is commercial software, we welcome feedback and feature requests from integration partners.
Partner Feedback Process:
v2.0 Beta Program:
📜 Credits
Developed by the RotationKit Team
Manual rotation engine built for Wear OS with Jetpack Compose. Auto-rotation sensor fusion algorithms (v2.0) adapted from the proven WatchOS RotationKit SDK.
Built with:
📞 Contact
All Inquiries: contact@rotationkit.com
Topics:
Business Hours: Monday-Friday, 9am-6pm EST
Emergency Support: Available for Enterprise license holders
Built for professional Wear OS developers
Transform your Wear OS app with precision manual rotation control
v2.0: Intelligent auto-rotation coming Q3 2025
© 2025 RotationKit. All rights reserved.
© 2025 RotationKit. All rights reserved.